diff --git a/neutron/conf/plugins/ml2/drivers/ovs_conf.py b/neutron/conf/plugins/ml2/drivers/ovs_conf.py index d1dac485204..48028110fa1 100644 --- a/neutron/conf/plugins/ml2/drivers/ovs_conf.py +++ b/neutron/conf/plugins/ml2/drivers/ovs_conf.py @@ -95,10 +95,6 @@ ovs_opts = [ "integration bridge to physical networks. " "Support kernel without Open vSwitch patch port " "support so long as it is set to True.")), - cfg.StrOpt('of_interface', default='native', - deprecated_for_removal=True, - choices=['ovs-ofctl', 'native'], - help=_("OpenFlow interface to use.")), cfg.StrOpt('datapath_type', default=constants.OVS_DATAPATH_SYSTEM, choices=[constants.OVS_DATAPATH_SYSTEM, constants.OVS_DATAPATH_NETDEV], diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/main.py b/neutron/plugins/ml2/drivers/openvswitch/agent/main.py index 4e07cfb17b8..59709f3638f 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/main.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/main.py @@ -18,30 +18,20 @@ import sys from oslo_config import cfg -from oslo_utils import importutils from neutron.common import config as common_config from neutron.common import profiler +from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.native import \ + main as of_main cfg.CONF.import_group('OVS', 'neutron.plugins.ml2.drivers.openvswitch.agent.' 'common.config') -_main_modules = { - 'ovs-ofctl': 'neutron.plugins.ml2.drivers.openvswitch.agent.openflow.' - 'ovs_ofctl.main', - 'native': 'neutron.plugins.ml2.drivers.openvswitch.agent.openflow.' - 'native.main', -} - - def main(): common_config.init(sys.argv[1:]) - driver_name = cfg.CONF.OVS.of_interface - mod_name = _main_modules[driver_name] - mod = importutils.import_module(mod_name) - mod.init_config() + of_main.init_config() common_config.setup_logging() profiler.setup("neutron-ovs-agent", cfg.CONF.host) - mod.main() + of_main.main() diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/ofswitch.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/ofswitch.py index e816d99e3d2..ca611198f50 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/ofswitch.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/ofswitch.py @@ -17,6 +17,7 @@ import functools import random +import debtcollector import eventlet import netaddr from neutron_lib import exceptions @@ -220,9 +221,8 @@ class OpenFlowSwitchMixin(object): (dp, ofp, ofpp) = self._get_dp() match = self._match(ofp, ofpp, match, **match_kwargs) if isinstance(instructions, six.string_types): - # NOTE: instructions must be str for the ofctl of_interface. - # After the ofctl driver is removed, a deprecation warning - # could be added here. + debtcollector.deprecate("Use of string instruction is " + "deprecated", removal_version='U') jsonlist = ofctl_string.ofp_instruction_from_str( ofp, instructions) instructions = ofproto_parser.ofp_instruction_from_jsondict( diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/__init__.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_dvr_process.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_dvr_process.py deleted file mode 100644 index 18a8525dc85..00000000000 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_dvr_process.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright (C) 2014,2015 VA Linux Systems Japan K.K. -# Copyright (C) 2014,2015 YAMAMOTO Takashi -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# Copyright 2011 VMware, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from neutron_lib import constants - - -class OVSDVRProcessMixin(object): - """Common logic for br-tun and br-phys' DVR_PROCESS tables. - - Inheriters should provide self.dvr_process_table_id and - self.dvr_process_next_table_id. - """ - - def install_dvr_process_ipv4(self, vlan_tag, gateway_ip): - # block ARP - self.add_flow(table=self.dvr_process_table_id, - priority=3, - dl_vlan=vlan_tag, - proto='arp', - nw_dst=gateway_ip, - actions='drop') - - def delete_dvr_process_ipv4(self, vlan_tag, gateway_ip): - self.delete_flows(table=self.dvr_process_table_id, - dl_vlan=vlan_tag, - proto='arp', - nw_dst=gateway_ip) - - def install_dvr_process_ipv6(self, vlan_tag, gateway_mac): - # block RA - self.add_flow(table=self.dvr_process_table_id, - priority=3, - dl_vlan=vlan_tag, - proto='icmp6', - icmp_type=constants.ICMPV6_TYPE_RA, - dl_src=gateway_mac, - actions='drop') - - def delete_dvr_process_ipv6(self, vlan_tag, gateway_mac): - self.delete_flows(table=self.dvr_process_table_id, - dl_vlan=vlan_tag, - proto='icmp6', - icmp_type=constants.ICMPV6_TYPE_RA, - dl_src=gateway_mac) - - def install_dvr_process(self, vlan_tag, vif_mac, dvr_mac_address): - self.add_flow(table=self.dvr_process_table_id, - priority=2, - dl_vlan=vlan_tag, - dl_dst=vif_mac, - actions="drop") - self.add_flow(table=self.dvr_process_table_id, - priority=1, - dl_vlan=vlan_tag, - dl_src=vif_mac, - actions="mod_dl_src:%s,resubmit(,%s)" % - (dvr_mac_address, self.dvr_process_next_table_id)) - - def delete_dvr_process(self, vlan_tag, vif_mac): - self.delete_flows(table=self.dvr_process_table_id, - dl_vlan=vlan_tag, - dl_dst=vif_mac) - self.delete_flows(table=self.dvr_process_table_id, - dl_vlan=vlan_tag, - dl_src=vif_mac) diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_int.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_int.py deleted file mode 100644 index fc99a58e3ba..00000000000 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_int.py +++ /dev/null @@ -1,203 +0,0 @@ -# Copyright (C) 2014,2015 VA Linux Systems Japan K.K. -# Copyright (C) 2014,2015 YAMAMOTO Takashi -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -* references -** OVS agent https://wiki.openstack.org/wiki/Ovs-flow-logic -""" - -import netaddr - -from neutron_lib import constants as const - -from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ - import ovs_bridge - - -class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge): - """openvswitch agent br-int specific logic.""" - - def setup_default_table(self): - self.setup_canary_table() - self.install_goto(dest_table_id=constants.TRANSIENT_TABLE) - self.install_normal(table_id=constants.TRANSIENT_TABLE, priority=3) - self.install_drop(table_id=constants.ARP_SPOOF_TABLE) - self.install_drop(table_id=constants.LOCAL_SWITCHING, - priority=constants.OPENFLOW_MAX_PRIORITY, - dl_vlan=constants.DEAD_VLAN_TAG) - - def setup_canary_table(self): - self.install_drop(constants.CANARY_TABLE) - - def check_canary_table(self): - canary_flows = self.dump_flows(constants.CANARY_TABLE) - if canary_flows == '': - return constants.OVS_RESTARTED - elif canary_flows is None: - return constants.OVS_DEAD - else: - return constants.OVS_NORMAL - - def provision_local_vlan(self, port, lvid, segmentation_id): - if segmentation_id is None: - dl_vlan = 0xffff - else: - dl_vlan = segmentation_id - self.add_flow(priority=3, - in_port=port, - dl_vlan=dl_vlan, - actions="mod_vlan_vid:%s,resubmit(,%d)" % ( - lvid, constants.TRANSIENT_TABLE)) - - def reclaim_local_vlan(self, port, segmentation_id): - if segmentation_id is None: - dl_vlan = 0xffff - else: - dl_vlan = segmentation_id - self.delete_flows(in_port=port, dl_vlan=dl_vlan) - - @staticmethod - def _dvr_to_src_mac_table_id(network_type): - if network_type == const.TYPE_VLAN: - return constants.DVR_TO_SRC_MAC_VLAN - else: - return constants.DVR_TO_SRC_MAC - - def install_dvr_to_src_mac(self, network_type, - vlan_tag, gateway_mac, dst_mac, dst_port): - table_id = self._dvr_to_src_mac_table_id(network_type) - self.add_flow(table=table_id, - priority=4, - dl_vlan=vlan_tag, - dl_dst=dst_mac, - actions="mod_dl_src:%s," - "resubmit(,%d)" % ( - gateway_mac, constants.TRANSIENT_TABLE)) - self.add_flow(table=constants.TRANSIENT_TABLE, - priority=4, - dl_vlan=vlan_tag, - dl_dst=dst_mac, - actions="strip_vlan,output:%s" % dst_port) - - def delete_dvr_to_src_mac(self, network_type, vlan_tag, dst_mac): - table_id = self._dvr_to_src_mac_table_id(network_type) - for table in (table_id, constants.TRANSIENT_TABLE): - self.delete_flows(strict=True, - priority=4, - table=table, - dl_vlan=vlan_tag, - dl_dst=dst_mac) - - def add_dvr_mac_vlan(self, mac, port): - self.install_goto(table_id=constants.LOCAL_SWITCHING, - priority=4, - in_port=port, - eth_src=mac, - dest_table_id=constants.DVR_TO_SRC_MAC_VLAN) - - def remove_dvr_mac_vlan(self, mac): - # REVISIT(yamamoto): match in_port as well? - self.delete_flows(table=constants.LOCAL_SWITCHING, - dl_src=mac) - - def add_dvr_mac_tun(self, mac, port): - # Table LOCAL_SWITCHING will now sort DVR traffic from other - # traffic depending on in_port - self.install_goto(table_id=constants.LOCAL_SWITCHING, - priority=2, - in_port=port, - eth_src=mac, - dest_table_id=constants.DVR_TO_SRC_MAC) - - def remove_dvr_mac_tun(self, mac, port): - self.delete_flows(table=constants.LOCAL_SWITCHING, - in_port=port, dl_src=mac) - - def install_icmpv6_na_spoofing_protection(self, port, ip_addresses): - # Allow neighbor advertisements as long as they match addresses - # that actually belong to the port. - for ip in ip_addresses: - self.install_goto( - table_id=constants.ARP_SPOOF_TABLE, priority=2, - dl_type=const.ETHERTYPE_IPV6, - nw_proto=const.PROTO_NUM_IPV6_ICMP, - icmp_type=const.ICMPV6_TYPE_NA, nd_target=ip, in_port=port, - dest_table_id=constants.TRANSIENT_TABLE) - - # Now that the rules are ready, direct icmpv6 neighbor advertisement - # traffic from the port into the anti-spoof table. - self.add_flow(table=constants.LOCAL_SWITCHING, - priority=10, dl_type=const.ETHERTYPE_IPV6, - nw_proto=const.PROTO_NUM_IPV6_ICMP, - icmp_type=const.ICMPV6_TYPE_NA, in_port=port, - actions=("resubmit(,%s)" % constants.ARP_SPOOF_TABLE)) - - def set_allowed_macs_for_port(self, port, mac_addresses=None, - allow_all=False): - if allow_all: - self.delete_flows(table=constants.LOCAL_SWITCHING, in_port=port) - self.delete_flows(table=constants.MAC_SPOOF_TABLE, in_port=port) - return - mac_addresses = mac_addresses or [] - for address in mac_addresses: - self.install_goto( - table_id=constants.MAC_SPOOF_TABLE, priority=2, - eth_src=address, in_port=port, - dest_table_id=constants.TRANSIENT_TABLE) - # normalize so we can see if macs are the same - mac_addresses = {netaddr.EUI(mac) for mac in mac_addresses} - flows = self.dump_flows_for(table=constants.MAC_SPOOF_TABLE, - in_port=port).splitlines() - for flow in flows: - if 'dl_src' not in flow: - continue - flow_mac = flow.split('dl_src=')[1].split(' ')[0].split(',')[0] - if netaddr.EUI(flow_mac) not in mac_addresses: - self.delete_flows(table=constants.MAC_SPOOF_TABLE, - in_port=port, dl_src=flow_mac) - self.add_flow(table=constants.LOCAL_SWITCHING, - priority=9, in_port=port, - actions=("resubmit(,%s)" % constants.MAC_SPOOF_TABLE)) - - def install_arp_spoofing_protection(self, port, ip_addresses): - # allow ARPs as long as they match addresses that actually - # belong to the port. - for ip in ip_addresses: - self.add_flow( - table=constants.ARP_SPOOF_TABLE, priority=2, - proto='arp', arp_spa=ip, in_port=port, - actions=("resubmit(,%s)" % constants.MAC_SPOOF_TABLE)) - - # Now that the rules are ready, direct ARP traffic from the port into - # the anti-spoof table. - # This strategy fails gracefully because OVS versions that can't match - # on ARP headers will just process traffic normally. - self.add_flow(table=constants.LOCAL_SWITCHING, - priority=10, proto='arp', in_port=port, - actions=("resubmit(,%s)" % constants.ARP_SPOOF_TABLE)) - - def delete_arp_spoofing_protection(self, port): - self.delete_flows(table=constants.LOCAL_SWITCHING, - in_port=port, proto='arp') - self.delete_flows(table=constants.LOCAL_SWITCHING, - in_port=port, nw_proto=const.PROTO_NUM_IPV6_ICMP, - icmp_type=const.ICMPV6_TYPE_NA) - self.delete_arp_spoofing_allow_rules(port) - - def delete_arp_spoofing_allow_rules(self, port): - self.delete_flows(table=constants.ARP_SPOOF_TABLE, - in_port=port) diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_phys.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_phys.py deleted file mode 100644 index 8031889586d..00000000000 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_phys.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (C) 2014,2015 VA Linux Systems Japan K.K. -# Copyright (C) 2014,2015 YAMAMOTO Takashi -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ - import br_dvr_process -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ - import ovs_bridge - - -class OVSPhysicalBridge(ovs_bridge.OVSAgentBridge, - br_dvr_process.OVSDVRProcessMixin): - """openvswitch agent physical bridge specific logic.""" - - # Used by OVSDVRProcessMixin - dvr_process_table_id = constants.DVR_PROCESS_VLAN - dvr_process_next_table_id = constants.LOCAL_VLAN_TRANSLATION - - def setup_default_table(self): - self.install_normal() - - def provision_local_vlan(self, port, lvid, segmentation_id, distributed): - table_id = constants.LOCAL_VLAN_TRANSLATION if distributed else 0 - if segmentation_id is None: - self.add_flow(table=table_id, - priority=4, - in_port=port, - dl_vlan=lvid, - actions="strip_vlan,normal") - else: - self.add_flow(table=table_id, - priority=4, - in_port=port, - dl_vlan=lvid, - actions="mod_vlan_vid:%s,normal" % segmentation_id) - - def reclaim_local_vlan(self, port, lvid): - self.delete_flows(in_port=port, dl_vlan=lvid) - - def add_dvr_mac_vlan(self, mac, port): - self.install_output(table_id=constants.DVR_NOT_LEARN_VLAN, - priority=2, eth_src=mac, port=port) - - def remove_dvr_mac_vlan(self, mac): - # REVISIT(yamamoto): match in_port as well? - self.delete_flows(table=constants.DVR_NOT_LEARN_VLAN, - dl_src=mac) 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 deleted file mode 100644 index 085fb38c5d1..00000000000 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_tun.py +++ /dev/null @@ -1,260 +0,0 @@ -# Copyright (C) 2014,2015 VA Linux Systems Japan K.K. -# Copyright (C) 2014,2015 YAMAMOTO Takashi -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# Copyright 2011 VMware, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import functools - -import netaddr - -from neutron.agent.common import ovs_lib -from neutron.plugins.ml2.drivers.openvswitch.agent.common \ - import constants -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ - import br_dvr_process -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ - import ovs_bridge - - -class OVSTunnelBridge(ovs_bridge.OVSAgentBridge, - br_dvr_process.OVSDVRProcessMixin): - """openvswitch agent tunnel bridge specific logic.""" - - # Used by OVSDVRProcessMixin - dvr_process_table_id = constants.DVR_PROCESS - dvr_process_next_table_id = constants.PATCH_LV_TO_TUN - - def setup_default_table(self, patch_int_ofport, arp_responder_enabled): - # Table 0 (default) will sort incoming traffic depending on in_port - 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): add arp_op=arp.ARP_REQUEST matcher? - 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 - 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 - 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: - 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 = ("cookie=%(cookie)s," - "table=%(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[]" % - {'cookie': self.default_cookie, - 'table': 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 - 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 - 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 - self.install_drop(table_id=constants.FLOOD_TO_TUN) - - def provision_local_vlan(self, network_type, lvid, segmentation_id, - distributed=False): - if distributed: - table_id = constants.DVR_NOT_LEARN - else: - table_id = constants.LEARN_FROM_TUN - self.add_flow(table=constants.TUN_TABLE[network_type], - priority=1, - tun_id=segmentation_id, - actions="mod_vlan_vid:%s," - "resubmit(,%s)" % - (lvid, table_id)) - - def reclaim_local_vlan(self, network_type, segmentation_id): - self.delete_flows(table=constants.TUN_TABLE[network_type], - tun_id=segmentation_id) - - @staticmethod - def _ofport_set_to_str(ports_set): - return ",".join(map(str, ports_set)) - - def install_flood_to_tun(self, vlan, tun_id, ports, deferred_br=None): - br = deferred_br if deferred_br else self - br.mod_flow(table=constants.FLOOD_TO_TUN, - dl_vlan=vlan, - actions="strip_vlan,set_tunnel:%s,output:%s" % - (tun_id, self._ofport_set_to_str(ports))) - - def delete_flood_to_tun(self, vlan, deferred_br=None): - br = deferred_br if deferred_br else self - br.delete_flows(table=constants.FLOOD_TO_TUN, dl_vlan=vlan) - - def install_unicast_to_tun(self, vlan, tun_id, port, mac, - deferred_br=None): - br = deferred_br if deferred_br else self - br.add_flow(table=constants.UCAST_TO_TUN, - priority=2, - dl_vlan=vlan, - dl_dst=mac, - actions="strip_vlan,set_tunnel:%s,output:%s" % - (tun_id, port)) - - def delete_unicast_to_tun(self, vlan, mac, deferred_br=None): - br = deferred_br if deferred_br else self - if mac is None: - br.delete_flows(table=constants.UCAST_TO_TUN, - dl_vlan=vlan) - else: - br.delete_flows(table=constants.UCAST_TO_TUN, - dl_vlan=vlan, - dl_dst=mac) - - def install_arp_responder(self, vlan, ip, mac, deferred_br=None): - br = deferred_br if deferred_br else self - actions = constants.ARP_RESPONDER_ACTIONS % { - 'mac': netaddr.EUI(mac, dialect=netaddr.mac_unix), - 'ip': netaddr.IPAddress(ip), - } - br.add_flow(table=constants.ARP_RESPONDER, - priority=1, - proto='arp', - dl_vlan=vlan, - nw_dst='%s' % ip, - actions=actions) - - def delete_arp_responder(self, vlan, ip, deferred_br=None): - br = deferred_br if deferred_br else self - if ip is None: - br.delete_flows(table=constants.ARP_RESPONDER, - proto='arp', - dl_vlan=vlan) - else: - br.delete_flows(table=constants.ARP_RESPONDER, - proto='arp', - dl_vlan=vlan, - nw_dst='%s' % ip) - - def setup_tunnel_port(self, network_type, port, deferred_br=None): - br = deferred_br if deferred_br else self - br.add_flow(priority=1, - in_port=port, - actions="resubmit(,%s)" % - constants.TUN_TABLE[network_type]) - - def cleanup_tunnel_port(self, port, deferred_br=None): - br = deferred_br if deferred_br else self - br.delete_flows(in_port=port) - - def add_dvr_mac_tun(self, mac, port): - # Table DVR_NOT_LEARN ensures unique dvr macs in the cloud - # are not learnt, as they may result in flow explosions - self.install_output(table_id=constants.DVR_NOT_LEARN, - priority=1, - eth_src=mac, - port=port) - - def remove_dvr_mac_tun(self, mac): - # REVISIT(yamamoto): match in_port as well? - self.delete_flows(table=constants.DVR_NOT_LEARN, - dl_src=mac) - - def deferred(self): - return DeferredOVSTunnelBridge(self) - - -class DeferredOVSTunnelBridge(ovs_lib.DeferredOVSBridge): - _METHODS = [ - 'install_unicast_to_tun', - 'delete_unicast_to_tun', - 'install_flood_to_tun', - 'delete_flood_to_tun', - 'install_arp_responder', - 'delete_arp_responder', - 'setup_tunnel_port', - 'cleanup_tunnel_port', - ] - - def __getattr__(self, name): - if name in self._METHODS: - m = getattr(self.br, name) - return functools.partial(m, deferred_br=self) - return super(DeferredOVSTunnelBridge, self).__getattr__(name) diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/main.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/main.py deleted file mode 100644 index 51ed82c8a6c..00000000000 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/main.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2015 VA Linux Systems Japan K.K. -# Copyright (C) 2015 YAMAMOTO Takashi -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ - import br_int -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ - import br_phys -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ - import br_tun -from neutron.plugins.ml2.drivers.openvswitch.agent import ovs_neutron_agent - - -def init_config(): - pass - - -def main(): - bridge_classes = { - 'br_int': br_int.OVSIntegrationBridge, - 'br_phys': br_phys.OVSPhysicalBridge, - 'br_tun': br_tun.OVSTunnelBridge, - } - ovs_neutron_agent.main(bridge_classes) diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ofswitch.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ofswitch.py deleted file mode 100644 index a5a49edc532..00000000000 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ofswitch.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright (C) 2014,2015 VA Linux Systems Japan K.K. -# Copyright (C) 2014,2015 YAMAMOTO Takashi -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re - -from oslo_log import log as logging - -LOG = logging.getLogger(__name__) - -# Field name mappings (from os-ken to ovs-ofctl) -_keywords = { - 'eth_src': 'dl_src', - 'eth_dst': 'dl_dst', - 'ipv4_src': 'nw_src', - 'ipv4_dst': 'nw_dst', - 'table_id': 'table', -} - - -class OpenFlowSwitchMixin(object): - """Mixin to provide common convenient routines for an openflow switch.""" - - @staticmethod - def _conv_args(kwargs): - for our_name, ovs_ofctl_name in _keywords.items(): - if our_name in kwargs: - kwargs[ovs_ofctl_name] = kwargs.pop(our_name) - return kwargs - - def dump_flows(self, table_id): - return self.dump_flows_for_table(table_id) - - def dump_flows_all_tables(self): - return self.dump_all_flows() - - def install_goto_next(self, table_id): - self.install_goto(table_id=table_id, dest_table_id=table_id + 1) - - def install_output(self, port, table_id=0, priority=0, **kwargs): - self.add_flow(table=table_id, - priority=priority, - actions="output:%s" % port, - **self._conv_args(kwargs)) - - def install_normal(self, table_id=0, priority=0, **kwargs): - self.add_flow(table=table_id, - priority=priority, - actions="normal", - **self._conv_args(kwargs)) - - def install_goto(self, dest_table_id, table_id=0, priority=0, **kwargs): - self.add_flow(table=table_id, - priority=priority, - actions="resubmit(,%s)" % dest_table_id, - **self._conv_args(kwargs)) - - def install_drop(self, table_id=0, priority=0, **kwargs): - self.add_flow(table=table_id, - priority=priority, - actions="drop", - **self._conv_args(kwargs)) - - def install_instructions(self, instructions, - table_id=0, priority=0, **kwargs): - self.add_flow(table=table_id, - priority=priority, - actions=instructions, - **self._conv_args(kwargs)) - - def uninstall_flows(self, **kwargs): - # NOTE(yamamoto): super() points to ovs_lib.OVSBridge. - # See ovs_bridge.py how this class is actually used. - super(OpenFlowSwitchMixin, self).delete_flows( - **self._conv_args(kwargs)) - - def _filter_flows(self, flows): - cookie_list = self.reserved_cookies - LOG.debug("Bridge cookies used to filter flows: %s", - cookie_list) - cookie_re = re.compile('cookie=(0x[A-Fa-f0-9]*)') - table_re = re.compile('table=([0-9]*)') - for flow in flows: - fl_cookie = cookie_re.search(flow) - if not fl_cookie: - continue - fl_cookie = fl_cookie.group(1) - if int(fl_cookie, 16) not in cookie_list: - fl_table = table_re.search(flow) - if not fl_table: - continue - fl_table = fl_table.group(1) - yield flow, fl_cookie, fl_table - - def cleanup_flows(self): - flows = self.dump_flows_all_tables() - for flow, cookie, table in self._filter_flows(flows): - # deleting a stale flow should be rare. - # it might deserve some attention - LOG.warning("Deleting flow %s", flow) - self.delete_flows(cookie=cookie + '/-1', table=table) diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ovs_bridge.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ovs_bridge.py deleted file mode 100644 index e5da02c175c..00000000000 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ovs_bridge.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (C) 2014,2015 VA Linux Systems Japan K.K. -# Copyright (C) 2014,2015 YAMAMOTO Takashi -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from neutron.agent.common import ovs_lib -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow \ - import br_cookie -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ - import ofswitch - - -class OVSAgentBridge(ofswitch.OpenFlowSwitchMixin, - br_cookie.OVSBridgeCookieMixin, ovs_lib.OVSBridge): - """Common code for bridges used by OVS agent""" - - def setup_controllers(self, conf): - self.del_controller() - - def drop_port(self, in_port): - self.install_drop(priority=2, in_port=in_port) diff --git a/neutron/tests/common/conn_testers.py b/neutron/tests/common/conn_testers.py index 675bb22e087..414a5fa7db6 100644 --- a/neutron/tests/common/conn_testers.py +++ b/neutron/tests/common/conn_testers.py @@ -17,13 +17,12 @@ import functools import fixtures import netaddr from neutron_lib import constants +from oslo_config import cfg from oslo_utils import uuidutils from neutron.common import utils as common_utils from neutron.plugins.ml2.drivers.openvswitch.agent.common import ( constants as ovs_consts) -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl import ( - br_int) from neutron.tests.common import machine_fixtures from neutron.tests.common import net_helpers @@ -400,11 +399,17 @@ class OVSConnectionTester(OVSBaseConnectionTester): """ + def __init__(self, ip_cidr, br_int_cls): + super(OVSConnectionTester, self).__init__(ip_cidr) + self.br_int_cls = br_int_cls + def _setUp(self): super(OVSConnectionTester, self)._setUp() br_name = self.useFixture( net_helpers.OVSBridgeFixture()).bridge.br_name - self.bridge = br_int.OVSIntegrationBridge(br_name) + self.bridge = self.br_int_cls(br_name) + self.bridge.set_secure_mode() + self.bridge.setup_controllers(cfg.CONF) self.bridge.setup_default_table() machines = self.useFixture( machine_fixtures.PeerMachines( diff --git a/neutron/tests/fullstack/resources/config.py b/neutron/tests/fullstack/resources/config.py index 11f6419468a..0226c171db0 100644 --- a/neutron/tests/fullstack/resources/config.py +++ b/neutron/tests/fullstack/resources/config.py @@ -197,7 +197,6 @@ class OVSConfigFixture(ConfigFixture): 'ovs': { 'local_ip': local_ip, 'integration_bridge': self._generate_integration_bridge(), - 'of_interface': host_desc.of_interface, 'bridge_mappings': '%s:%s' % (PHYSICAL_NETWORK_NAME, ext_dev) }, 'securitygroup': { @@ -236,13 +235,12 @@ class OVSConfigFixture(ConfigFixture): }) def _setUp(self): - if self.config['ovs']['of_interface'] == 'native': - self.config['ovs'].update({ - 'of_listen_port': self.useFixture( - port.ExclusivePort(constants.PROTO_NAME_TCP, - start=OVS_OF_PORT_LISTEN_START, - end=OVS_OF_PORT_LISTEN_END)).port - }) + self.config['ovs'].update({ + 'of_listen_port': self.useFixture( + port.ExclusivePort(constants.PROTO_NAME_TCP, + start=OVS_OF_PORT_LISTEN_START, + end=OVS_OF_PORT_LISTEN_END)).port + }) super(OVSConfigFixture, self)._setUp() def _generate_integration_bridge(self): diff --git a/neutron/tests/fullstack/resources/environment.py b/neutron/tests/fullstack/resources/environment.py index 85edbfadaf6..e1a133749f0 100644 --- a/neutron/tests/fullstack/resources/environment.py +++ b/neutron/tests/fullstack/resources/environment.py @@ -72,14 +72,12 @@ class HostDescription(object): under? """ def __init__(self, l3_agent=False, dhcp_agent=False, - of_interface='ovs-ofctl', l2_agent_type=constants.AGENT_TYPE_OVS, firewall_driver='noop', availability_zone=None, l3_agent_mode=None): self.l2_agent_type = l2_agent_type self.l3_agent = l3_agent self.dhcp_agent = dhcp_agent - self.of_interface = of_interface self.firewall_driver = firewall_driver self.availability_zone = availability_zone self.l3_agent_mode = l3_agent_mode diff --git a/neutron/tests/fullstack/test_connectivity.py b/neutron/tests/fullstack/test_connectivity.py index 3f498e88cfe..cf00ee3cd6d 100644 --- a/neutron/tests/fullstack/test_connectivity.py +++ b/neutron/tests/fullstack/test_connectivity.py @@ -25,7 +25,6 @@ from neutron.tests.fullstack import base from neutron.tests.fullstack.resources import config from neutron.tests.fullstack.resources import environment from neutron.tests.fullstack.resources import machine -from neutron.tests.fullstack import utils from neutron.tests.unit import testlib_api load_tests = testlib_api.module_load_tests @@ -37,7 +36,6 @@ LOG = logging.getLogger(__name__) class BaseConnectivitySameNetworkTest(base.BaseFullStackTestCase): - of_interface = None arp_responder = False use_dhcp = True @@ -50,7 +48,6 @@ class BaseConnectivitySameNetworkTest(base.BaseFullStackTestCase): # agent types present on machines. environment.HostDescription( l3_agent=self.l2_pop, - of_interface=self.of_interface, l2_agent_type=self.l2_agent_type, dhcp_agent=self.use_dhcp, ) @@ -104,7 +101,7 @@ class BaseConnectivitySameNetworkTest(base.BaseFullStackTestCase): class TestOvsConnectivitySameNetwork(BaseConnectivitySameNetworkTest): l2_agent_type = constants.AGENT_TYPE_OVS - network_scenarios = [ + scenarios = [ ('VXLAN', {'network_type': 'vxlan', 'l2_pop': False}), ('GRE-l2pop-arp_responder', {'network_type': 'gre', @@ -112,8 +109,6 @@ class TestOvsConnectivitySameNetwork(BaseConnectivitySameNetworkTest): 'arp_responder': True}), ('VLANs', {'network_type': 'vlan', 'l2_pop': False})] - scenarios = testscenarios.multiply_scenarios( - network_scenarios, utils.get_ovs_interface_scenarios()) def test_connectivity(self): self._test_connectivity() @@ -125,7 +120,7 @@ class TestOvsConnectivitySameNetworkOnOvsBridgeControllerStop( num_hosts = 2 l2_agent_type = constants.AGENT_TYPE_OVS - network_scenarios = [ + scenarios = [ ('VXLAN', {'network_type': 'vxlan', 'l2_pop': False}), ('GRE and l2pop', {'network_type': 'gre', @@ -133,12 +128,6 @@ class TestOvsConnectivitySameNetworkOnOvsBridgeControllerStop( ('VLANs', {'network_type': 'vlan', 'l2_pop': False})] - # Do not test for CLI ofctl interface as controller is irrelevant for CLI - scenarios = testscenarios.multiply_scenarios( - network_scenarios, - [(m, v) for (m, v) in utils.get_ovs_interface_scenarios() - if v['of_interface'] != 'ovs-ofctl']) - def _test_controller_timeout_does_not_break_connectivity(self, kill_signal=None): # Environment preparation is effectively the same as connectivity test @@ -203,7 +192,6 @@ class TestConnectivitySameNetworkNoDhcp(BaseConnectivitySameNetworkTest): use_dhcp = False network_type = 'vxlan' l2_pop = False - of_interface = 'native' def test_connectivity(self): self._test_connectivity() @@ -228,8 +216,8 @@ class TestUninterruptedConnectivityOnL2AgentRestart( 'l2_pop': False}), ] scenarios = ( - testscenarios.multiply_scenarios(ovs_agent_scenario, network_scenarios, - utils.get_ovs_interface_scenarios()) + + testscenarios.multiply_scenarios(ovs_agent_scenario, + network_scenarios) + testscenarios.multiply_scenarios(lb_agent_scenario, network_scenarios) ) diff --git a/neutron/tests/fullstack/test_firewall.py b/neutron/tests/fullstack/test_firewall.py index 05d5479edfd..8d15118e8bb 100644 --- a/neutron/tests/fullstack/test_firewall.py +++ b/neutron/tests/fullstack/test_firewall.py @@ -44,7 +44,6 @@ class FirewallMigrationTestCase(base.BaseFullStackTestCase): host_descriptions = [ environment.HostDescription( l3_agent=False, - of_interface='native', l2_agent_type=constants.AGENT_TYPE_OVS, firewall_driver='iptables_hybrid', dhcp_agent=False, diff --git a/neutron/tests/fullstack/test_logging.py b/neutron/tests/fullstack/test_logging.py index 57c1017ea0a..07a1a6a9e09 100644 --- a/neutron/tests/fullstack/test_logging.py +++ b/neutron/tests/fullstack/test_logging.py @@ -27,13 +27,11 @@ from neutron.tests.fullstack.resources import machine class BaseLoggingTestCase(base.BaseFullStackTestCase): - of_interface = None number_of_hosts = 1 def setUp(self): host_desc = [ environment.HostDescription( - of_interface=self.of_interface, l2_agent_type=constants.AGENT_TYPE_OVS, firewall_driver='openvswitch', dhcp_agent=True) for _ in range(self.number_of_hosts)] @@ -90,8 +88,6 @@ class BaseLoggingTestCase(base.BaseFullStackTestCase): class TestLogging(BaseLoggingTestCase): - of_interface = 'native' - def _create_network_log(self, resource_type, resource_id=None, target_id=None): return self.safe_client.create_network_log( diff --git a/neutron/tests/fullstack/test_qos.py b/neutron/tests/fullstack/test_qos.py index 8de05257a16..36d6c2029f5 100644 --- a/neutron/tests/fullstack/test_qos.py +++ b/neutron/tests/fullstack/test_qos.py @@ -18,7 +18,6 @@ from neutron_lib import constants from neutron_lib.services.qos import constants as qos_consts from neutronclient.common import exceptions from oslo_utils import uuidutils -import testscenarios from neutron.agent.common import ovs_lib from neutron.agent.linux import tc_lib @@ -28,7 +27,6 @@ from neutron.tests.fullstack import base from neutron.tests.fullstack.resources import config as fullstack_config from neutron.tests.fullstack.resources import environment from neutron.tests.fullstack.resources import machine -from neutron.tests.fullstack import utils as fullstack_utils from neutron.tests.unit import testlib_api from neutron.conf.plugins.ml2.drivers import linuxbridge as \ @@ -48,7 +46,6 @@ DSCP_MARK = 16 class BaseQoSRuleTestCase(object): - of_interface = None number_of_hosts = 1 physical_network = None @@ -63,7 +60,6 @@ class BaseQoSRuleTestCase(object): host_desc = [ environment.HostDescription( l3_agent=False, - of_interface=self.of_interface, l2_agent_type=self.l2_agent_type ) for _ in range(self.number_of_hosts)] env_desc = environment.EnvironmentDescription( @@ -344,12 +340,10 @@ class _TestBwLimitQoS(BaseQoSRuleTestCase): class TestBwLimitQoSOvs(_TestBwLimitQoS, base.BaseFullStackTestCase): l2_agent_type = constants.AGENT_TYPE_OVS - direction_scenarios = [ + scenarios = [ ('ingress', {'direction': constants.INGRESS_DIRECTION}), ('egress', {'direction': constants.EGRESS_DIRECTION}) ] - scenarios = testscenarios.multiply_scenarios( - direction_scenarios, fullstack_utils.get_ovs_interface_scenarios()) @staticmethod def _get_expected_burst_value(limit, direction): @@ -520,7 +514,6 @@ class _TestDscpMarkingQoS(BaseQoSRuleTestCase): class TestDscpMarkingQoSOvs(_TestDscpMarkingQoS, base.BaseFullStackTestCase): - scenarios = fullstack_utils.get_ovs_interface_scenarios() l2_agent_type = constants.AGENT_TYPE_OVS def _wait_for_dscp_marking_rule_applied(self, vm, dscp_mark): @@ -670,11 +663,9 @@ class _TestMinBwQoS(BaseQoSRuleTestCase): class TestMinBwQoSOvs(_TestMinBwQoS, base.BaseFullStackTestCase): l2_agent_type = constants.AGENT_TYPE_OVS - direction_scenarios = [ + scenarios = [ ('egress', {'direction': constants.EGRESS_DIRECTION}) ] - scenarios = testscenarios.multiply_scenarios( - direction_scenarios, fullstack_utils.get_ovs_interface_scenarios()) def _wait_for_min_bw_rule_applied(self, vm, min_bw, direction): if direction == constants.EGRESS_DIRECTION: diff --git a/neutron/tests/fullstack/test_securitygroup.py b/neutron/tests/fullstack/test_securitygroup.py index 4f4f3118411..cc9fda6fd24 100644 --- a/neutron/tests/fullstack/test_securitygroup.py +++ b/neutron/tests/fullstack/test_securitygroup.py @@ -40,13 +40,10 @@ class OVSVersionChecker(object): class BaseSecurityGroupsSameNetworkTest(base.BaseFullStackTestCase): - of_interface = None - def setUp(self): debug_iptables = self.firewall_driver.startswith("iptables") host_descriptions = [ environment.HostDescription( - of_interface=self.of_interface, l2_agent_type=self.l2_agent_type, firewall_driver=self.firewall_driver, dhcp_agent=True) for _ in range(self.num_hosts)] @@ -92,17 +89,10 @@ class TestSecurityGroupsSameNetwork(BaseSecurityGroupsSameNetworkTest): # because of that using only one host is enough ('ovs-hybrid', { 'firewall_driver': 'iptables_hybrid', - 'of_interface': 'native', 'l2_agent_type': constants.AGENT_TYPE_OVS, 'num_hosts': 1}), - ('ovs-openflow-cli', { + ('ovs-openflow', { 'firewall_driver': 'openvswitch', - 'of_interface': 'ovs-ofctl', - 'l2_agent_type': constants.AGENT_TYPE_OVS, - 'num_hosts': 2}), - ('ovs-openflow-native', { - 'firewall_driver': 'openvswitch', - 'of_interface': 'native', 'l2_agent_type': constants.AGENT_TYPE_OVS, 'num_hosts': 2}), ('linuxbridge-iptables', { diff --git a/neutron/tests/fullstack/utils.py b/neutron/tests/fullstack/utils.py deleted file mode 100644 index c11be262f5a..00000000000 --- a/neutron/tests/fullstack/utils.py +++ /dev/null @@ -1,18 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -def get_ovs_interface_scenarios(): - return [ - ('openflow-cli', {'of_interface': 'ovs-ofctl'}), - ('openflow-native', {'of_interface': 'native'}), - ] diff --git a/neutron/tests/functional/agent/l2/base.py b/neutron/tests/functional/agent/l2/base.py index 5bb9a0ddca8..34b67d9acb6 100644 --- a/neutron/tests/functional/agent/l2/base.py +++ b/neutron/tests/functional/agent/l2/base.py @@ -17,6 +17,7 @@ import random import eventlet +import fixtures import mock from neutron_lib import constants as n_const from neutron_lib.utils import net @@ -35,19 +36,77 @@ from neutron.conf.plugins.ml2.drivers import ovs_conf from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants from neutron.plugins.ml2.drivers.openvswitch.agent.extension_drivers \ import qos_driver as ovs_qos_driver -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ - import br_int -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ - import br_phys -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ - import br_tun +from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.native \ + import main as main_mod from neutron.plugins.ml2.drivers.openvswitch.agent import ovs_neutron_agent \ as ovs_agent from neutron.tests.common import net_helpers from neutron.tests.functional.agent.linux import base -class OVSAgentTestFramework(base.BaseOVSLinuxTestCase): +class OVSOFControllerHelper(object): + """Helper class that runs os-ken openflow controller.""" + + def start_of_controller(self, conf): + self.br_int_cls = None + self.br_tun_cls = None + self.br_phys_cls = None + self.init_done = False + self.init_done_ev = eventlet.event.Event() + self.main_ev = eventlet.event.Event() + self.addCleanup(self._kill_main) + retry_count = 3 + while True: + # Try a few different ports as a port conflict + # causes the test to fail. + conf.set_override('of_listen_port', + net_helpers.get_free_namespace_port( + n_const.PROTO_NAME_TCP), + group='OVS') + cfg.CONF.set_override('of_listen_port', + conf.OVS.of_listen_port, + group='OVS') + main_mod.init_config() + self._main_thread = eventlet.spawn(self._kick_main) + + # Wait for _kick_main -> openflow main -> _agent_main + # NOTE(yamamoto): This complexity came from how we run openflow + # controller. Main routine blocks while running the embedded + # openflow controller. In that case, the agent rpc_loop runs in + # another thread. However, for FT we need to run setUp() and + # test_xxx() in the same thread. So I made this run openflow main + # in a separate thread instead. + try: + while not self.init_done: + self.init_done_ev.wait() + break + except fixtures.TimeoutException: + self._kill_main() + retry_count -= 1 + if retry_count < 0: + raise Exception('port allocation failed') + + def _kick_main(self): + with mock.patch.object(ovs_agent, 'main', self._agent_main): + main_mod.main() + + def _kill_main(self): + self.main_ev.send() + self._main_thread.wait() + + def _agent_main(self, bridge_classes): + self.br_int_cls = bridge_classes['br_int'] + self.br_phys_cls = bridge_classes['br_phys'] + self.br_tun_cls = bridge_classes['br_tun'] + + # signal to setUp() + self.init_done = True + self.init_done_ev.send() + + self.main_ev.wait() + + +class OVSAgentTestFramework(base.BaseOVSLinuxTestCase, OVSOFControllerHelper): def setUp(self): super(OVSAgentTestFramework, self).setUp() @@ -68,6 +127,7 @@ class OVSAgentTestFramework(base.BaseOVSLinuxTestCase): self.config = self._configure_agent() self.driver = interface.OVSInterfaceDriver(self.config) self.namespace = self.useFixture(net_helpers.NamespaceFixture()).name + self.start_of_controller(self.config) def _get_config_opts(self): config = cfg.ConfigOpts() @@ -95,9 +155,9 @@ class OVSAgentTestFramework(base.BaseOVSLinuxTestCase): def _bridge_classes(self): return { - 'br_int': br_int.OVSIntegrationBridge, - 'br_phys': br_phys.OVSPhysicalBridge, - 'br_tun': br_tun.OVSTunnelBridge + 'br_int': self.br_int_cls, + 'br_phys': self.br_phys_cls, + 'br_tun': self.br_tun_cls } def create_agent(self, create_tunnels=True, ancillary_bridge=None, diff --git a/neutron/tests/functional/agent/test_firewall.py b/neutron/tests/functional/agent/test_firewall.py index 9543823a4a6..3f0d96ce7c5 100644 --- a/neutron/tests/functional/agent/test_firewall.py +++ b/neutron/tests/functional/agent/test_firewall.py @@ -34,6 +34,7 @@ from neutron.cmd.sanity import checks from neutron.conf.agent import securitygroups_rpc as security_config from neutron.tests.common import conn_testers from neutron.tests.common import helpers +from neutron.tests.functional.agent.l2 import base as l2_base from neutron.tests.functional.agent.linux import base as linux_base from neutron.tests.functional import constants as test_constants @@ -131,8 +132,12 @@ class BaseFirewallTestCase(linux_base.BaseOVSLinuxTestCase): "OVS>=2.5). More info at " "https://github.com/openvswitch/ovs/blob/master/" "FAQ.md") + self.of_helper = l2_base.OVSOFControllerHelper() + self.of_helper.addCleanup = self.addCleanup + self.of_helper.start_of_controller(cfg.CONF) tester = self.useFixture( - conn_testers.OVSConnectionTester(self.ip_cidr)) + conn_testers.OVSConnectionTester(self.ip_cidr, + self.of_helper.br_int_cls)) firewall_drv = openvswitch_firewall.OVSFirewallDriver(tester.bridge) return tester, firewall_drv diff --git a/neutron/tests/functional/agent/test_l2_ovs_agent.py b/neutron/tests/functional/agent/test_l2_ovs_agent.py index 02e3224950c..bc7332c68f3 100644 --- a/neutron/tests/functional/agent/test_l2_ovs_agent.py +++ b/neutron/tests/functional/agent/test_l2_ovs_agent.py @@ -40,8 +40,10 @@ class TestOVSAgent(base.OVSAgentTestFramework): def test_no_stale_flows_after_port_delete(self): def find_drop_flow(ofport, flows): - for flow in flows.split("\n"): - if "in_port=%d" % ofport in flow and "actions=drop" in flow: + for flow in flows: + # flow.instruction == [] means actions=drop + if (not flow.instructions and + ('in_port', ofport) in flow.match.items()): return True return False @@ -96,6 +98,7 @@ class TestOVSAgent(base.OVSAgentTestFramework): ('br_int', 'br_tun', 'br_phys')): actual = self.ovs.db_get_val('Bridge', br_name, 'datapath_type') self.assertEqual(expected, actual) + self.stop_agent(agent, self.agent_thread) def test_datapath_type_change(self): self._check_datapath_type_netdev('system') diff --git a/neutron/tests/functional/agent/test_ovs_flows.py b/neutron/tests/functional/agent/test_ovs_flows.py index fd136c78c48..87a559f06b9 100644 --- a/neutron/tests/functional/agent/test_ovs_flows.py +++ b/neutron/tests/functional/agent/test_ovs_flows.py @@ -13,15 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. -import eventlet -import fixtures -import mock -import testscenarios - from neutron_lib import constants as n_const from oslo_config import cfg from oslo_serialization import jsonutils -from oslo_utils import importutils from testtools.content import text_content from neutron.agent.common import ovs_lib @@ -35,11 +29,11 @@ from neutron.plugins.ml2.drivers.openvswitch.agent \ from neutron.tests.common import base as common_base from neutron.tests.common import helpers from neutron.tests.common import net_helpers +from neutron.tests.functional.agent.l2 import base as l2_base from neutron.tests.functional.agent import test_ovs_lib +from neutron.tests.functional import base from neutron.tests import tools -load_tests = testscenarios.load_tests_apply_scenarios - OVS_TRACE_FINAL_FLOW = 'Final flow' OVS_TRACE_DATAPATH_ACTIONS = 'Datapath actions' @@ -47,52 +41,18 @@ cfg.CONF.import_group('OVS', 'neutron.plugins.ml2.drivers.openvswitch.agent.' 'common.config') -class OVSAgentTestBase(test_ovs_lib.OVSBridgeTestBase): - scenarios = [ - ('ofctl', {'main_module': ('neutron.plugins.ml2.drivers.openvswitch.' - 'agent.openflow.ovs_ofctl.main')}), - ('native', {'main_module': ('neutron.plugins.ml2.drivers.openvswitch.' - 'agent.openflow.native.main')})] +class OVSAgentTestBase(test_ovs_lib.OVSBridgeTestBase, + base.BaseSudoTestCase, + l2_base.OVSOFControllerHelper): def setUp(self): super(OVSAgentTestBase, self).setUp() self.br = self.useFixture(net_helpers.OVSBridgeFixture()).bridge - self.of_interface_mod = importutils.import_module(self.main_module) - self.br_int_cls = None - self.br_tun_cls = None - self.br_phys_cls = None - self.br_int = None - self.init_done = False - self.init_done_ev = eventlet.event.Event() - self.main_ev = eventlet.event.Event() - self.addCleanup(self._kill_main) - retry_count = 3 - while True: - cfg.CONF.set_override('of_listen_port', - net_helpers.get_free_namespace_port( - n_const.PROTO_NAME_TCP), - group='OVS') - self.of_interface_mod.init_config() - self._main_thread = eventlet.spawn(self._kick_main) - - # Wait for _kick_main -> of_interface main -> _agent_main - # NOTE(yamamoto): This complexity came from how "native" - # of_interface runs its openflow controller. "native" - # of_interface's main routine blocks while running the - # embedded openflow controller. In that case, the agent - # rpc_loop runs in another thread. However, for FT we - # need to run setUp() and test_xxx() in the same thread. - # So I made this run of_interface's main in a separate - # thread instead. - try: - while not self.init_done: - self.init_done_ev.wait() - break - except fixtures.TimeoutException: - self._kill_main() - retry_count -= 1 - if retry_count < 0: - raise Exception('port allocation failed') + self.start_of_controller(cfg.CONF) + self.br_int = self.br_int_cls(self.br.br_name) + self.br_int.set_secure_mode() + self.br_int.setup_controllers(cfg.CONF) + self.br_int.setup_default_table() def _run_trace(self, brname, spec): required_keys = [OVS_TRACE_FINAL_FLOW, OVS_TRACE_DATAPATH_ACTIONS] @@ -112,29 +72,6 @@ class OVSAgentTestBase(test_ovs_lib.OVSBridgeTestBase): return trace - def _kick_main(self): - with mock.patch.object(ovsagt, 'main', self._agent_main): - self.of_interface_mod.main() - - def _kill_main(self): - self.main_ev.send() - self._main_thread.wait() - - def _agent_main(self, bridge_classes): - self.br_int_cls = bridge_classes['br_int'] - self.br_phys_cls = bridge_classes['br_phys'] - self.br_tun_cls = bridge_classes['br_tun'] - self.br_int = self.br_int_cls(self.br.br_name) - self.br_int.set_secure_mode() - self.br_int.setup_controllers(cfg.CONF) - self.br_int.setup_default_table() - - # signal to setUp() - self.init_done = True - self.init_done_ev.send() - - self.main_ev.wait() - class ARPSpoofTestCase(OVSAgentTestBase): def setUp(self): @@ -357,9 +294,7 @@ class DeleteFlowsTestCase(OVSAgentTestBase): class OVSFlowTestCase(OVSAgentTestBase): """Tests defined in this class use ovs-appctl ofproto/trace commands, which simulate processing of imaginary packets, to check desired actions - are correctly set up by OVS flows. In this way, subtle variations in - flows between of_interface drivers are absorbed and the same tests work - against those drivers. + are correctly set up by OVS flows. """ def setUp(self): @@ -466,9 +401,6 @@ class OVSFlowTestCase(OVSAgentTestBase): self.assertIn("pop_vlan,", trace["Datapath actions"]) def test_bundled_install(self): - if 'ovs_ofctl' in self.main_module: - self.skip("ovs-ofctl of_interface doesn't have bundled()") - kwargs = {'in_port': 345, 'vlan_tci': 0x1321} dst_p = self.useFixture( net_helpers.OVSPortFixture(self.br_tun, self.namespace)).port diff --git a/neutron/tests/functional/services/logapi/test_logging.py b/neutron/tests/functional/services/logapi/test_logging.py index 282bf4d0114..887620cb96f 100644 --- a/neutron/tests/functional/services/logapi/test_logging.py +++ b/neutron/tests/functional/services/logapi/test_logging.py @@ -27,8 +27,6 @@ from neutron.plugins.ml2.drivers.openvswitch.agent import ( ovs_agent_extension_api as ovs_ext_api) from neutron.plugins.ml2.drivers.openvswitch.agent.common import ( constants as ovs_consts) -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl import ( - ovs_bridge) from neutron.services.logapi.drivers.openvswitch import ( ovs_firewall_log as ovs_fw_log) from neutron.tests.functional.agent import test_firewall @@ -62,11 +60,12 @@ class LoggingExtensionTestFramework(test_firewall.BaseFirewallTestCase): self.log_driver = self.initialize_ovs_fw_log() def initialize_ovs_fw_log(self): - mock.patch('os_ken.base.app_manager.AppManager.get_instance').start() + self.int_br = ovs_ext_api.OVSCookieBridge( + self.of_helper.br_int_cls(self.tester.bridge.br_name)) + self.tun_br = self.of_helper.br_tun_cls('br-tun') agent_api = ovs_ext_api.OVSAgentExtensionAPI( - ovs_bridge.OVSAgentBridge(self.tester.bridge.br_name), - ovs_bridge.OVSAgentBridge('br-tun'), - {'physnet1': ovs_bridge.OVSAgentBridge('br-physnet1')}) + self.int_br, self.tun_br, + {'physnet1': self.of_helper.br_phys_cls('br-physnet1')}) log_driver = ovs_fw_log.OVSFirewallLoggingDriver(agent_api) log_driver.initialize(self.resource_rpc) return log_driver diff --git a/neutron/tests/unit/agent/l2/extensions/test_qos.py b/neutron/tests/unit/agent/l2/extensions/test_qos.py index 23557c88f00..bde30b437d8 100644 --- a/neutron/tests/unit/agent/l2/extensions/test_qos.py +++ b/neutron/tests/unit/agent/l2/extensions/test_qos.py @@ -32,7 +32,7 @@ from neutron.objects.qos import rule from neutron.plugins.ml2.drivers.openvswitch.agent import ( ovs_agent_extension_api as ovs_ext_api) from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl import ( +from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.native import ( ovs_bridge) from neutron.tests import base @@ -224,10 +224,14 @@ class QosExtensionBaseTestCase(base.BaseTestCase): self.qos_ext = qos.QosAgentExtension() self.context = context.get_admin_context() self.connection = mock.Mock() + os_ken_app = mock.Mock() self.agent_api = ovs_ext_api.OVSAgentExtensionAPI( - ovs_bridge.OVSAgentBridge('br-int'), - ovs_bridge.OVSAgentBridge('br-tun'), - {'phynet1': ovs_bridge.OVSAgentBridge('br-phynet1')}) + ovs_bridge.OVSAgentBridge( + 'br-int', os_ken_app=os_ken_app), + ovs_bridge.OVSAgentBridge( + 'br-tun', os_ken_app=os_ken_app), + {'phynet1': ovs_bridge.OVSAgentBridge( + 'br-phynet1', os_ken_app=os_ken_app)}) self.qos_ext.consume_api(self.agent_api) # Don't rely on used driver diff --git a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py index 2e73971fb57..3727c5f4365 100644 --- a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py +++ b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py @@ -26,7 +26,7 @@ from neutron.agent.linux.openvswitch_firewall import exceptions from neutron.agent.linux.openvswitch_firewall import firewall as ovsfw from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \ as ovs_consts -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ +from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.native \ import ovs_bridge from neutron.tests import base @@ -752,7 +752,7 @@ class TestCookieContext(base.BaseTestCase): self.execute = mock.patch.object( utils, "execute", spec=utils.execute).start() - bridge = ovs_bridge.OVSAgentBridge('foo') + bridge = ovs_bridge.OVSAgentBridge('foo', os_ken_app=mock.Mock()) mock.patch.object( ovsfw.OVSFirewallDriver, 'initialize_bridge', return_value=bridge.deferred( diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/extension_drivers/test_qos_driver.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/extension_drivers/test_qos_driver.py index 2d260f95c63..ac94133d8f8 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/extension_drivers/test_qos_driver.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/extension_drivers/test_qos_driver.py @@ -23,7 +23,7 @@ from neutron.plugins.ml2.drivers.openvswitch.agent import ( ovs_agent_extension_api as ovs_ext_api) from neutron.plugins.ml2.drivers.openvswitch.agent.extension_drivers import ( qos_driver) -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl import ( +from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.native import ( ovs_bridge) from neutron.tests.unit.plugins.ml2.drivers.openvswitch.agent import ( ovs_test_base) @@ -41,10 +41,14 @@ class QosOVSAgentDriverTestCase(ovs_test_base.OVSAgentConfigTestBase): self.qos_driver = qos_driver.QosOVSAgentDriver() self.mock_clear_minimum_bandwidth_qos = mock.patch.object( self.qos_driver, '_minimum_bandwidth_initialize').start() + os_ken_app = mock.Mock() self.agent_api = ovs_ext_api.OVSAgentExtensionAPI( - ovs_bridge.OVSAgentBridge('br-int'), - ovs_bridge.OVSAgentBridge('br-tun'), - {'phys1': ovs_bridge.OVSAgentBridge('br-phys1')}) + ovs_bridge.OVSAgentBridge( + 'br-int', os_ken_app=os_ken_app), + ovs_bridge.OVSAgentBridge( + 'br-tun', os_ken_app=os_ken_app), + {'phys1': ovs_bridge.OVSAgentBridge( + 'br-phys1', os_ken_app=os_ken_app)}) self.qos_driver.consume_api(self.agent_api) self.qos_driver.initialize() self.qos_driver.br_int = mock.Mock() diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/__init__.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ovs_bridge_test_base.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ovs_bridge_test_base.py deleted file mode 100644 index e845c978175..00000000000 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ovs_bridge_test_base.py +++ /dev/null @@ -1,175 +0,0 @@ -# Copyright (C) 2014,2015 VA Linux Systems Japan K.K. -# Copyright (C) 2014,2015 YAMAMOTO Takashi -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -from neutron_lib import constants - -from neutron.tests.unit.plugins.ml2.drivers.openvswitch.agent \ - import ovs_test_base - - -call = mock.call # short hand - - -class OVSBridgeTestBase(ovs_test_base.OVSOFCtlTestBase): - def setup_bridge_mock(self, name, cls): - self.br = cls(name) - mock_add_flow = mock.patch.object(self.br, 'add_flow').start() - mock_mod_flow = mock.patch.object(self.br, 'mod_flow').start() - mock_delete_flows = mock.patch.object(self.br, 'delete_flows').start() - self.mock = mock.Mock() - self.mock.attach_mock(mock_add_flow, 'add_flow') - self.mock.attach_mock(mock_mod_flow, 'mod_flow') - self.mock.attach_mock(mock_delete_flows, 'delete_flows') - - def test_drop_port(self): - in_port = 2345 - self.br.drop_port(in_port=in_port) - expected = [ - call.add_flow(priority=2, table=0, actions='drop', - in_port=in_port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_install_goto(self): - dest_table_id = 123 - priority = 99 - in_port = 666 - self.br.install_goto(dest_table_id=dest_table_id, - priority=priority, in_port=in_port) - expected = [ - call.add_flow(priority=priority, table=0, - actions='resubmit(,%s)' % dest_table_id, - in_port=in_port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_install_drop(self): - priority = 99 - in_port = 666 - self.br.install_drop(priority=priority, in_port=in_port) - expected = [ - call.add_flow(priority=priority, table=0, - actions='drop', - in_port=in_port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_install_normal(self): - priority = 99 - in_port = 666 - self.br.install_normal(priority=priority, in_port=in_port) - expected = [ - call.add_flow(priority=priority, table=0, - actions='normal', - in_port=in_port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_dump_flows_for_table(self): - table = 23 - with mock.patch.object(self.br, 'run_ofctl') as run_ofctl: - self.br.dump_flows(table) - run_ofctl.assert_has_calls([mock.call("dump-flows", mock.ANY)]) - - def test_dump_all_flows(self): - with mock.patch.object(self.br, 'run_ofctl') as run_ofctl: - self.br.dump_flows_all_tables() - run_ofctl.assert_has_calls([mock.call("dump-flows", [])]) - - -class OVSDVRProcessTestMixin(object): - def test_install_dvr_process_ipv4(self): - vlan_tag = 999 - gateway_ip = '192.0.2.1' - self.br.install_dvr_process_ipv4(vlan_tag=vlan_tag, - gateway_ip=gateway_ip) - expected = [ - call.add_flow(table=self.dvr_process_table_id, - proto='arp', nw_dst=gateway_ip, actions='drop', - priority=3, dl_vlan=vlan_tag), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_delete_dvr_process_ipv4(self): - vlan_tag = 999 - gateway_ip = '192.0.2.1' - self.br.delete_dvr_process_ipv4(vlan_tag=vlan_tag, - gateway_ip=gateway_ip) - expected = [ - call.delete_flows(table=self.dvr_process_table_id, - dl_vlan=vlan_tag, proto='arp', - nw_dst=gateway_ip), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_install_dvr_process_ipv6(self): - vlan_tag = 999 - gateway_mac = '08:60:6e:7f:74:e7' - self.br.install_dvr_process_ipv6(vlan_tag=vlan_tag, - gateway_mac=gateway_mac) - expected = [ - call.add_flow(table=self.dvr_process_table_id, - proto='icmp6', dl_src=gateway_mac, actions='drop', - priority=3, dl_vlan=vlan_tag, - icmp_type=constants.ICMPV6_TYPE_RA), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_delete_dvr_process_ipv6(self): - vlan_tag = 999 - gateway_mac = '08:60:6e:7f:74:e7' - self.br.delete_dvr_process_ipv6(vlan_tag=vlan_tag, - gateway_mac=gateway_mac) - expected = [ - call.delete_flows(table=self.dvr_process_table_id, - dl_vlan=vlan_tag, dl_src=gateway_mac, - proto='icmp6', - icmp_type=constants.ICMPV6_TYPE_RA), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_install_dvr_process(self): - vlan_tag = 999 - vif_mac = '00:0e:0c:5e:95:d0' - dvr_mac_address = 'f2:0b:a4:5b:b2:ab' - self.br.install_dvr_process(vlan_tag=vlan_tag, - vif_mac=vif_mac, - dvr_mac_address=dvr_mac_address) - expected = [ - call.add_flow(priority=2, table=self.dvr_process_table_id, - dl_dst=vif_mac, dl_vlan=vlan_tag, actions='drop'), - call.add_flow(priority=1, table=self.dvr_process_table_id, - dl_vlan=vlan_tag, dl_src=vif_mac, - actions='mod_dl_src:%(mac)s,resubmit(,%(next)s)' % { - 'mac': dvr_mac_address, - 'next': self.dvr_process_next_table_id, - }), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_delete_dvr_process(self): - vlan_tag = 999 - vif_mac = '00:0e:0c:5e:95:d0' - self.br.delete_dvr_process(vlan_tag=vlan_tag, - vif_mac=vif_mac) - expected = [ - call.delete_flows(table=self.dvr_process_table_id, - dl_dst=vif_mac, dl_vlan=vlan_tag), - call.delete_flows(table=self.dvr_process_table_id, - dl_vlan=vlan_tag, dl_src=vif_mac), - ] - self.assertEqual(expected, self.mock.mock_calls) diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_int.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_int.py deleted file mode 100644 index 09d1cfc1918..00000000000 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_int.py +++ /dev/null @@ -1,260 +0,0 @@ -# Copyright (C) 2014,2015 VA Linux Systems Japan K.K. -# Copyright (C) 2014,2015 YAMAMOTO Takashi -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -from neutron_lib import constants as const - -from neutron.tests.unit.plugins.ml2.drivers.openvswitch.agent.\ - openflow.ovs_ofctl import ovs_bridge_test_base - - -call = mock.call # short hand - - -class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase): - def setUp(self): - super(OVSIntegrationBridgeTest, self).setUp() - self.setup_bridge_mock('br-int', self.br_int_cls) - - def test_setup_default_table(self): - self.br.setup_default_table() - expected = [ - call.add_flow(priority=0, table=23, actions='drop'), - call.add_flow(priority=0, table=0, actions='resubmit(,60)'), - call.add_flow(priority=3, table=60, actions='normal'), - call.add_flow(priority=0, table=24, actions='drop'), - call.add_flow(actions='drop', dl_vlan=4095, - priority=65535, table=0) - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_provision_local_vlan(self): - port = 999 - lvid = 888 - segmentation_id = 777 - self.br.provision_local_vlan(port=port, lvid=lvid, - segmentation_id=segmentation_id) - expected = [ - call.add_flow(priority=3, dl_vlan=segmentation_id, - in_port=port, - actions='mod_vlan_vid:%s,resubmit(,60)' % lvid), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_provision_local_vlan_novlan(self): - port = 999 - lvid = 888 - segmentation_id = None - self.br.provision_local_vlan(port=port, lvid=lvid, - segmentation_id=segmentation_id) - expected = [ - call.add_flow(priority=3, dl_vlan=0xffff, - in_port=port, - actions='mod_vlan_vid:%s,resubmit(,60)' % lvid), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_reclaim_local_vlan(self): - port = 999 - segmentation_id = 777 - self.br.reclaim_local_vlan(port=port, segmentation_id=segmentation_id) - expected = [ - call.delete_flows(dl_vlan=segmentation_id, in_port=port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_reclaim_local_vlan_novlan(self): - port = 999 - segmentation_id = None - self.br.reclaim_local_vlan(port=port, segmentation_id=segmentation_id) - expected = [ - call.delete_flows(dl_vlan=0xffff, in_port=port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_install_dvr_to_src_mac(self): - network_type = 'vxlan' - vlan_tag = 1111 - gateway_mac = '08:60:6e:7f:74:e7' - dst_mac = '00:02:b3:13:fe:3d' - dst_port = 6666 - self.br.install_dvr_to_src_mac(network_type=network_type, - vlan_tag=vlan_tag, - gateway_mac=gateway_mac, - dst_mac=dst_mac, - dst_port=dst_port) - expected = [ - call.add_flow(priority=4, table=1, dl_dst=dst_mac, - dl_vlan=vlan_tag, - actions='mod_dl_src:%(mac)s,resubmit(,60)' % { - 'mac': gateway_mac, - }), - call.add_flow(priority=4, table=60, dl_dst=dst_mac, - dl_vlan=vlan_tag, - actions='strip_vlan,output:%(port)s' % { - 'port': dst_port, - }), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_delete_dvr_to_src_mac(self): - network_type = 'vxlan' - vlan_tag = 1111 - dst_mac = '00:02:b3:13:fe:3d' - self.br.delete_dvr_to_src_mac(network_type=network_type, - vlan_tag=vlan_tag, - dst_mac=dst_mac) - expected = [ - call.delete_flows( - strict=True, priority=4, table=1, dl_dst=dst_mac, - dl_vlan=vlan_tag), - call.delete_flows( - strict=True, priority=4, table=60, dl_dst=dst_mac, - dl_vlan=vlan_tag), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_install_dvr_to_src_mac_vlan(self): - network_type = 'vlan' - vlan_tag = 1111 - gateway_mac = '08:60:6e:7f:74:e7' - dst_mac = '00:02:b3:13:fe:3d' - dst_port = 6666 - self.br.install_dvr_to_src_mac(network_type=network_type, - vlan_tag=vlan_tag, - gateway_mac=gateway_mac, - dst_mac=dst_mac, - dst_port=dst_port) - expected = [ - call.add_flow(priority=4, table=2, dl_dst=dst_mac, - dl_vlan=vlan_tag, - actions='mod_dl_src:%(mac)s,resubmit(,60)' % { - 'mac': gateway_mac, - }), - call.add_flow(priority=4, table=60, dl_dst=dst_mac, - dl_vlan=vlan_tag, - actions='strip_vlan,output:%(port)s' % { - 'port': dst_port, - }), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_delete_dvr_to_src_mac_vlan(self): - network_type = 'vlan' - vlan_tag = 1111 - dst_mac = '00:02:b3:13:fe:3d' - self.br.delete_dvr_to_src_mac(network_type=network_type, - vlan_tag=vlan_tag, - dst_mac=dst_mac) - expected = [ - call.delete_flows( - strict=True, priority=4, table=2, dl_dst=dst_mac, - dl_vlan=vlan_tag), - call.delete_flows( - strict=True, priority=4, table=60, dl_dst=dst_mac, - dl_vlan=vlan_tag), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_add_dvr_mac_vlan(self): - mac = '00:02:b3:13:fe:3d' - port = 8888 - self.br.add_dvr_mac_vlan(mac=mac, port=port) - expected = [ - call.add_flow(priority=4, table=0, actions='resubmit(,2)', - dl_src=mac, in_port=port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_remove_dvr_mac_vlan(self): - mac = '00:02:b3:13:fe:3d' - self.br.remove_dvr_mac_vlan(mac=mac) - expected = [ - call.delete_flows(dl_src=mac, table=0), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_add_dvr_mac_tun(self): - mac = '00:02:b3:13:fe:3d' - port = 8888 - self.br.add_dvr_mac_tun(mac=mac, port=port) - expected = [ - call.add_flow(priority=2, table=0, actions='resubmit(,1)', - dl_src=mac, in_port=port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_remove_dvr_mac_tun(self): - mac = '00:02:b3:13:fe:3d' - port = 8888 - self.br.remove_dvr_mac_tun(mac=mac, port=port) - expected = [ - call.delete_flows(dl_src=mac, table=0, in_port=port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_install_icmpv6_na_spoofing_protection(self): - port = 8888 - ip_addresses = ['2001:db8::1', 'fdf8:f53b:82e4::1/128'] - self.br.install_icmpv6_na_spoofing_protection(port, ip_addresses) - expected = [ - call.add_flow(dl_type=const.ETHERTYPE_IPV6, - actions='resubmit(,60)', - icmp_type=const.ICMPV6_TYPE_NA, - nw_proto=const.PROTO_NUM_IPV6_ICMP, - nd_target='2001:db8::1', - priority=2, table=24, in_port=8888), - call.add_flow(dl_type=const.ETHERTYPE_IPV6, - actions='resubmit(,60)', - icmp_type=const.ICMPV6_TYPE_NA, - nw_proto=const.PROTO_NUM_IPV6_ICMP, - nd_target='fdf8:f53b:82e4::1/128', - priority=2, table=24, in_port=8888), - call.add_flow(dl_type=const.ETHERTYPE_IPV6, - icmp_type=const.ICMPV6_TYPE_NA, - nw_proto=const.PROTO_NUM_IPV6_ICMP, - priority=10, table=0, in_port=8888, - actions='resubmit(,24)') - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_install_arp_spoofing_protection(self): - port = 8888 - ip_addresses = ['192.0.2.1', '192.0.2.2/32'] - self.br.install_arp_spoofing_protection(port, ip_addresses) - expected = [ - call.add_flow(proto='arp', actions='resubmit(,25)', - arp_spa='192.0.2.1', - priority=2, table=24, in_port=8888), - call.add_flow(proto='arp', actions='resubmit(,25)', - arp_spa='192.0.2.2/32', - priority=2, table=24, in_port=8888), - call.add_flow(priority=10, table=0, in_port=8888, - actions='resubmit(,24)', proto='arp') - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_delete_arp_spoofing_protection(self): - port = 8888 - self.br.delete_arp_spoofing_protection(port) - expected = [ - call.delete_flows(table=0, in_port=8888, proto='arp'), - call.delete_flows(table=0, in_port=8888, - icmp_type=const.ICMPV6_TYPE_NA, - nw_proto=const.PROTO_NUM_IPV6_ICMP), - call.delete_flows(table=24, in_port=8888), - ] - self.assertEqual(expected, self.mock.mock_calls) diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_phys.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_phys.py deleted file mode 100644 index 317294f5515..00000000000 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_phys.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (C) 2014,2015 VA Linux Systems Japan K.K. -# Copyright (C) 2014,2015 YAMAMOTO Takashi -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -import neutron.plugins.ml2.drivers.openvswitch.agent.common.constants \ - as ovs_const -from neutron.tests.unit.plugins.ml2.drivers.openvswitch.agent.\ - openflow.ovs_ofctl import ovs_bridge_test_base - - -call = mock.call # short hand - - -class OVSPhysicalBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase, - ovs_bridge_test_base.OVSDVRProcessTestMixin): - dvr_process_table_id = ovs_const.DVR_PROCESS_VLAN - dvr_process_next_table_id = ovs_const.LOCAL_VLAN_TRANSLATION - - def setUp(self): - super(OVSPhysicalBridgeTest, self).setUp() - self.setup_bridge_mock('br-phys', self.br_phys_cls) - - def test_setup_default_table(self): - self.br.setup_default_table() - expected = [ - call.add_flow(priority=0, table=0, actions='normal'), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_provision_local_vlan(self): - port = 999 - lvid = 888 - segmentation_id = 777 - distributed = False - self.br.provision_local_vlan(port=port, lvid=lvid, - segmentation_id=segmentation_id, - distributed=distributed) - expected = [ - call.add_flow(priority=4, table=0, dl_vlan=lvid, in_port=port, - actions='mod_vlan_vid:%s,normal' % segmentation_id), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_provision_local_vlan_novlan(self): - port = 999 - lvid = 888 - segmentation_id = None - distributed = False - self.br.provision_local_vlan(port=port, lvid=lvid, - segmentation_id=segmentation_id, - distributed=distributed) - expected = [ - call.add_flow(priority=4, table=0, dl_vlan=lvid, in_port=port, - actions='strip_vlan,normal') - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_reclaim_local_vlan(self): - port = 999 - lvid = 888 - self.br.reclaim_local_vlan(port=port, lvid=lvid) - expected = [ - call.delete_flows(dl_vlan=lvid, in_port=port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_add_dvr_mac_vlan(self): - mac = '00:02:b3:13:fe:3d' - port = 8888 - self.br.add_dvr_mac_vlan(mac=mac, port=port) - expected = [ - call.add_flow(priority=2, table=3, dl_src=mac, - actions='output:%s' % port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_remove_dvr_mac_vlan(self): - mac = '00:02:b3:13:fe:3d' - self.br.remove_dvr_mac_vlan(mac=mac) - expected = [ - call.delete_flows(dl_src=mac, table=3), - ] - self.assertEqual(expected, self.mock.mock_calls) 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 deleted file mode 100644 index 574a4f2062b..00000000000 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_tun.py +++ /dev/null @@ -1,320 +0,0 @@ -# Copyright (C) 2014,2015 VA Linux Systems Japan K.K. -# Copyright (C) 2014,2015 YAMAMOTO Takashi -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -import netaddr - -import neutron.plugins.ml2.drivers.openvswitch.agent.common.constants \ - as ovs_const -from neutron.tests.unit.plugins.ml2.drivers.openvswitch.agent.\ - openflow.ovs_ofctl import ovs_bridge_test_base - - -call = mock.call # short hand - - -class OVSTunnelBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase, - ovs_bridge_test_base.OVSDVRProcessTestMixin): - dvr_process_table_id = ovs_const.DVR_PROCESS - dvr_process_next_table_id = ovs_const.PATCH_LV_TO_TUN - - def setUp(self): - super(OVSTunnelBridgeTest, self).setUp() - self.setup_bridge_mock('br-tun', self.br_tun_cls) - self.stamp = self.br.default_cookie - - def test_setup_default_table(self): - patch_int_ofport = 5555 - 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=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': 0, 'table': 6, 'actions': 'drop'}, - {'priority': 1, 'table': 10, - 'actions': 'learn(cookie=' + str(self.stamp) + - ',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, False), - 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 - 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=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': 0, 'table': 6, 'actions': 'drop'}, - {'priority': 1, 'table': 10, - 'actions': 'learn(cookie=' + str(self.stamp) + - ',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, False), - call.add_flow(priority=0, table=22, actions='drop')] - self.assertEqual(expected, self.mock.mock_calls) - - def test_provision_local_vlan(self): - network_type = 'vxlan' - lvid = 888 - segmentation_id = 777 - distributed = False - self.br.provision_local_vlan(network_type=network_type, lvid=lvid, - segmentation_id=segmentation_id, - distributed=distributed) - expected = [ - call.add_flow(priority=1, tun_id=segmentation_id, - actions='mod_vlan_vid:%s,resubmit(,10)' % lvid, - table=4), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_reclaim_local_vlan(self): - network_type = 'vxlan' - segmentation_id = 777 - self.br.reclaim_local_vlan(network_type=network_type, - segmentation_id=segmentation_id) - expected = [ - call.delete_flows(tun_id=segmentation_id, table=4), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_install_flood_to_tun(self): - vlan = 3333 - tun_id = 2222 - ports = [11, 44, 22, 33] - self.br.install_flood_to_tun(vlan=vlan, - tun_id=tun_id, - ports=ports) - expected = [ - call.mod_flow(table=22, dl_vlan=vlan, - actions='strip_vlan,set_tunnel:%(tun)s,' - 'output:%(ports)s' % { - 'tun': tun_id, - 'ports': ','.join(map(str, ports)), - }), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_delete_flood_to_tun(self): - vlan = 3333 - self.br.delete_flood_to_tun(vlan=vlan) - expected = [ - call.delete_flows(table=22, dl_vlan=vlan), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_install_unicast_to_tun(self): - vlan = 3333 - port = 55 - mac = '08:60:6e:7f:74:e7' - tun_id = 2222 - self.br.install_unicast_to_tun(vlan=vlan, - tun_id=tun_id, - port=port, - mac=mac) - expected = [ - call.add_flow(priority=2, table=20, dl_dst=mac, dl_vlan=vlan, - actions='strip_vlan,set_tunnel:%(tun)s,' - 'output:%(port)s' % { - 'tun': tun_id, - 'port': port, - }), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_delete_unicast_to_tun(self): - vlan = 3333 - mac = '08:60:6e:7f:74:e7' - self.br.delete_unicast_to_tun(vlan=vlan, mac=mac) - expected = [ - call.delete_flows(table=20, dl_dst=mac, dl_vlan=vlan), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_delete_unicast_to_tun_without_mac(self): - vlan = 3333 - mac = None - self.br.delete_unicast_to_tun(vlan=vlan, mac=mac) - expected = [ - call.delete_flows(table=20, dl_vlan=vlan), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_install_arp_responder(self): - vlan = 3333 - ip = '192.0.2.1' - mac = '08:60:6e:7f:74:e7' - self.br.install_arp_responder(vlan=vlan, ip=ip, mac=mac) - expected = [ - call.add_flow(proto='arp', nw_dst=ip, - actions='move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],' - 'mod_dl_src:%(mac)s,load:0x2->NXM_OF_ARP_OP[],' - 'move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],' - 'move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],' - 'load:%(mac)#x->NXM_NX_ARP_SHA[],' - 'load:%(ip)#x->NXM_OF_ARP_SPA[],in_port' % { - 'mac': netaddr.EUI(mac, - dialect=netaddr.mac_unix), - 'ip': netaddr.IPAddress(ip), - }, - priority=1, table=21, dl_vlan=vlan), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_delete_arp_responder(self): - vlan = 3333 - ip = '192.0.2.1' - self.br.delete_arp_responder(vlan=vlan, ip=ip) - expected = [ - call.delete_flows(table=21, dl_vlan=vlan, proto='arp', nw_dst=ip), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_delete_arp_responder_without_ip(self): - vlan = 3333 - ip = None - self.br.delete_arp_responder(vlan=vlan, ip=ip) - expected = [ - call.delete_flows(table=21, dl_vlan=vlan, proto='arp'), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_setup_tunnel_port(self): - network_type = 'vxlan' - port = 11111 - self.br.setup_tunnel_port(network_type=network_type, port=port) - expected = [ - call.add_flow(priority=1, in_port=port, actions='resubmit(,4)'), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_cleanup_tunnel_port(self): - port = 11111 - self.br.cleanup_tunnel_port(port=port) - expected = [ - call.delete_flows(in_port=port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_add_dvr_mac_tun(self): - mac = '00:02:b3:13:fe:3d' - port = 8888 - self.br.add_dvr_mac_tun(mac=mac, port=port) - expected = [ - call.add_flow(priority=1, table=9, dl_src=mac, - actions='output:%s' % port), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def test_remove_dvr_mac_tun(self): - mac = '00:02:b3:13:fe:3d' - self.br.remove_dvr_mac_tun(mac=mac) - expected = [ - call.delete_flows(dl_src=mac, table=9), - ] - self.assertEqual(expected, self.mock.mock_calls) - - def _mock_add_tunnel_port(self, deferred_br=False): - port_name = 'fake_port' - remote_ip = '192.168.1.3' - local_ip = '192.168.1.2' - tunnel_type = 'vxlan' - vxlan_udp_port = '4789' - dont_fragment = True - if deferred_br: - with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.add_port', - return_value=9999) as add_port, \ - self.br.deferred() as deferred_br: - ofport = deferred_br.add_tunnel_port(port_name, remote_ip, - local_ip, tunnel_type, - vxlan_udp_port, - dont_fragment) - else: - with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.add_port', - return_value=9999) as add_port: - ofport = self.br.add_tunnel_port(port_name, remote_ip, - local_ip, tunnel_type, - vxlan_udp_port, - dont_fragment) - self.assertEqual(9999, ofport) - self.assertEqual(1, add_port.call_count) - self.assertEqual(port_name, add_port.call_args[0][0]) - - def _mock_delete_port(self, deferred_br=False): - port_name = 'fake_port' - if deferred_br: - with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'delete_port') as delete_port, \ - self.br.deferred() as deferred_br: - deferred_br.delete_port(port_name) - else: - with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'delete_port') as delete_port: - self.br.delete_port(port_name) - self.assertEqual([call(port_name)], delete_port.mock_calls) - - def test_add_tunnel_port(self): - self._mock_add_tunnel_port() - - def test_delete_port(self): - self._mock_delete_port() - - def test_deferred_br_add_tunnel_port(self): - self._mock_add_tunnel_port(True) - - def test_deferred_br_delete_port(self): - self._mock_delete_port(True) diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/test_br_cookie.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/test_br_cookie.py index acf32996896..d0df579c020 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/test_br_cookie.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/test_br_cookie.py @@ -16,7 +16,7 @@ import mock from neutron.agent.common import ovs_lib -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ +from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.native \ import ovs_bridge from neutron.tests import base @@ -29,7 +29,7 @@ class TestBRCookieOpenflow(base.BaseTestCase): 'neutron.agent.ovsdb.impl_idl._connection') conn_patcher.start() self.addCleanup(conn_patcher.stop) - self.br = ovs_bridge.OVSAgentBridge('br-int') + self.br = ovs_bridge.OVSAgentBridge('br-int', os_ken_app=mock.Mock()) def test_reserved_cookies(self): def_cookie = self.br.default_cookie @@ -49,7 +49,7 @@ class TestBRCookieOpenflow(base.BaseTestCase): self.assertNotIn(requested_cookie, self.br.reserved_cookies) def test_set_agent_uuid_stamp(self): - self.br = ovs_bridge.OVSAgentBridge('br-int') + self.br = ovs_bridge.OVSAgentBridge('br-int', os_ken_app=mock.Mock()) def_cookie = self.br.default_cookie new_cookie = ovs_lib.generate_random_cookie() @@ -60,7 +60,7 @@ class TestBRCookieOpenflow(base.BaseTestCase): self.assertNotIn(def_cookie, self.br.reserved_cookies) def test_set_agent_uuid_stamp_with_reserved_cookie(self): - self.br = ovs_bridge.OVSAgentBridge('br-int') + self.br = ovs_bridge.OVSAgentBridge('br-int', os_ken_app=mock.Mock()) def_cookie = self.br.default_cookie new_cookie = self.br.request_cookie() diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/ovs_test_base.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/ovs_test_base.py index b71e82083dd..a9435a20ff4 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/ovs_test_base.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/ovs_test_base.py @@ -38,33 +38,8 @@ class OVSAgentConfigTestBase(base.BaseTestCase): self.mod_dvr_agent = importutils.import_module(_DVR_AGENT_NAME) -class OVSAgentTestBase(OVSAgentConfigTestBase): - def setUp(self): - super(OVSAgentTestBase, self).setUp() - conn_patcher = mock.patch( - 'neutron.agent.ovsdb.impl_idl._connection') - conn_patcher.start() - self.addCleanup(conn_patcher.stop) - self.br_int_cls = importutils.import_class(self._BR_INT_CLASS) - self.br_phys_cls = importutils.import_class(self._BR_PHYS_CLASS) - self.br_tun_cls = importutils.import_class(self._BR_TUN_CLASS) +class OVSOSKenTestBase(OVSAgentConfigTestBase): - def _bridge_classes(self): - return { - 'br_int': self.br_int_cls, - 'br_phys': self.br_phys_cls, - 'br_tun': self.br_tun_cls, - } - - -class OVSOFCtlTestBase(OVSAgentTestBase): - _DRIVER_PACKAGE = _AGENT_PACKAGE + '.openflow.ovs_ofctl' - _BR_INT_CLASS = _DRIVER_PACKAGE + '.br_int.OVSIntegrationBridge' - _BR_TUN_CLASS = _DRIVER_PACKAGE + '.br_tun.OVSTunnelBridge' - _BR_PHYS_CLASS = _DRIVER_PACKAGE + '.br_phys.OVSPhysicalBridge' - - -class OVSOSKenTestBase(OVSAgentTestBase): _DRIVER_PACKAGE = _AGENT_PACKAGE + '.openflow.native' _BR_INT_CLASS = _DRIVER_PACKAGE + '.br_int.OVSIntegrationBridge' _BR_TUN_CLASS = _DRIVER_PACKAGE + '.br_tun.OVSTunnelBridge' @@ -75,6 +50,13 @@ class OVSOSKenTestBase(OVSAgentTestBase): self.fake_oflib_of.start() self.addCleanup(self.fake_oflib_of.stop) super(OVSOSKenTestBase, self).setUp() + conn_patcher = mock.patch( + 'neutron.agent.ovsdb.impl_idl._connection') + conn_patcher.start() + self.addCleanup(conn_patcher.stop) + self.br_int_cls = importutils.import_class(self._BR_INT_CLASS) + self.br_phys_cls = importutils.import_class(self._BR_PHYS_CLASS) + self.br_tun_cls = importutils.import_class(self._BR_TUN_CLASS) os_ken_app = mock.Mock() self.br_int_cls = functools.partial(self.br_int_cls, os_ken_app=os_ken_app) @@ -82,3 +64,10 @@ class OVSOSKenTestBase(OVSAgentTestBase): os_ken_app=os_ken_app) self.br_tun_cls = functools.partial(self.br_tun_cls, os_ken_app=os_ken_app) + + def _bridge_classes(self): + return { + 'br_int': self.br_int_cls, + 'br_phys': self.br_phys_cls, + 'br_tun': self.br_tun_cls, + } diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_agent_extension_api.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_agent_extension_api.py index 9fe5551dd4e..c44f6fbae43 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_agent_extension_api.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_agent_extension_api.py @@ -26,7 +26,7 @@ from neutron.tests.unit.plugins.ml2.drivers.openvswitch.agent \ import ovs_test_base -class TestOVSAgentExtensionAPI(ovs_test_base.OVSOFCtlTestBase): +class TestOVSAgentExtensionAPI(ovs_test_base.OVSOSKenTestBase): def setUp(self): super(TestOVSAgentExtensionAPI, self).setUp() @@ -69,121 +69,6 @@ class TestOVSAgentExtensionAPI(ovs_test_base.OVSOFCtlTestBase): self._test_bridge(self.br_phys[phys_br.br_name], phys_br) -class TestOVSCookieBridgeOFCtl(ovs_test_base.OVSOFCtlTestBase): - - def setUp(self): - super(TestOVSCookieBridgeOFCtl, self).setUp() - self.bridge = self.br_int_cls("br-int") - mock.patch.object(self.bridge, "run_ofctl").start() - - self.tested_bridge = ovs_ext_agt.OVSCookieBridge(self.bridge) - - # mocking do_action_flows does not work, because this method is - # later wrapped by the cookie bridge code, and six.wraps apparently - # can't wrap a mock, so we mock deeper - self.mock_build_flow_expr_str = mock.patch( - 'neutron.agent.common.ovs_lib._build_flow_expr_str', - return_value="").start() - - def test_cookie(self): - self.assertNotEqual(self.bridge._default_cookie, - self.tested_bridge._default_cookie) - - def test_reserved(self): - self.assertIn(self.tested_bridge._default_cookie, - self.bridge.reserved_cookies) - - def assert_mock_build_flow_expr_str_call(self, action, kwargs_list, - strict=False): - self.mock_build_flow_expr_str.assert_called_once_with( - kwargs_list[0], - action, - strict - ) - - def test_add_flow_without_cookie(self): - self.tested_bridge.add_flow(in_port=1, actions="output:2") - self.assert_mock_build_flow_expr_str_call( - 'add', - [{"in_port": 1, - "actions": "output:2", - "cookie": self.tested_bridge._default_cookie}] - ) - - def test_mod_flow_without_cookie(self): - self.tested_bridge.mod_flow(in_port=1, actions="output:2") - self.assert_mock_build_flow_expr_str_call( - 'mod', - [{"in_port": 1, - "actions": "output:2", - "cookie": self.tested_bridge._default_cookie}] - ) - - def test_del_flows_without_cookie(self): - self.tested_bridge.delete_flows(in_port=1) - self.assert_mock_build_flow_expr_str_call( - 'del', - [{"in_port": 1, - "cookie": str(self.tested_bridge._default_cookie) + '/-1'}] - ) - - def test_add_flow_with_cookie(self): - self.tested_bridge.add_flow(cookie=1234, - in_port=1, actions="output:2") - self.assert_mock_build_flow_expr_str_call( - 'add', - [{"in_port": 1, - "actions": "output:2", - "cookie": 1234}] - ) - - def test_mod_flow_with_cookie(self): - self.tested_bridge.mod_flow(cookie='1234', - in_port=1, actions="output:2") - self.assert_mock_build_flow_expr_str_call( - 'mod', - [{"in_port": 1, - "actions": "output:2", - "cookie": "1234"}] - ) - - def test_del_flows_with_cookie(self): - self.tested_bridge.delete_flows(cookie=1234, in_port=1) - self.assert_mock_build_flow_expr_str_call( - 'del', - [{"in_port": 1, - "cookie": "1234/-1"}] - ) - - def test_mod_flow_with_cookie_mask(self): - self.tested_bridge.mod_flow(cookie='1234/3', - in_port=1, actions="output:2") - self.assert_mock_build_flow_expr_str_call( - 'mod', - [{"in_port": 1, - "actions": "output:2", - "cookie": str(1234) + '/3'}] - ) - - def test_del_flows_with_cookie_mask(self): - self.tested_bridge.delete_flows(cookie='1234/7', in_port=1) - self.assert_mock_build_flow_expr_str_call( - 'del', - [{"in_port": 1, - "cookie": str(1234) + '/7'}] - ) - - def test_install_drop(self): - self.tested_bridge.install_drop() - self.assert_mock_build_flow_expr_str_call( - 'add', - [{"table": 0, - "priority": 0, - "actions": "drop", - "cookie": self.tested_bridge._default_cookie}] - ) - - class TestOVSCookieBridgeOSKen(native_ovs_bridge_test_base.OVSBridgeTestBase): def setUp(self): diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py index 3beb3368ca7..b1b148f90a3 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py @@ -2422,31 +2422,8 @@ class TestOvsNeutronAgent(object): mock_update_segid.assert_not_called() -class TestOvsNeutronAgentOFCtl(TestOvsNeutronAgent, - ovs_test_base.OVSOFCtlTestBase): - def test_cleanup_stale_flows(self): - with mock.patch.object(self.agent.int_br, - 'dump_flows_all_tables') as dump_flows,\ - mock.patch.object(self.agent.int_br, - 'delete_flows') as del_flow: - self.agent.int_br.set_agent_uuid_stamp(1234) - dump_flows.return_value = [ - 'cookie=0x4d2, duration=50.156s, table=0,actions=drop', - 'cookie=0x4321, duration=54.143s, table=2, priority=0', - 'cookie=0x2345, duration=50.125s, table=2, priority=0', - 'cookie=0x4d2, duration=52.112s, table=3, actions=drop', - ] - self.agent.iter_num = 3 - self.agent.cleanup_stale_flows() - expected = [ - mock.call(cookie='0x4321/-1', table='2'), - mock.call(cookie='0x2345/-1', table='2'), - ] - self.assertEqual(expected, del_flow.mock_calls) - - class TestOvsNeutronAgentOSKen(TestOvsNeutronAgent, - ovs_test_base.OVSOSKenTestBase): + ovs_test_base.OVSOSKenTestBase): def test_cleanup_stale_flows(self): uint64_max = (1 << 64) - 1 with mock.patch.object(self.agent.int_br, @@ -2600,11 +2577,6 @@ class AncillaryBridgesTest(object): self.assertEqual(expected, actual) -class AncillaryBridgesTestOFCtl(AncillaryBridgesTest, - ovs_test_base.OVSOFCtlTestBase): - pass - - class AncillaryBridgesTestOSKen(AncillaryBridgesTest, ovs_test_base.OVSOSKenTestBase): pass @@ -3614,11 +3586,6 @@ class TestOvsDvrNeutronAgent(object): self._test_scan_ports_failure('scan_ancillary_ports') -class TestOvsDvrNeutronAgentOFCtl(TestOvsDvrNeutronAgent, - ovs_test_base.OVSOFCtlTestBase): - pass - - class TestOvsDvrNeutronAgentOSKen(TestOvsDvrNeutronAgent, ovs_test_base.OVSOSKenTestBase): pass 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 e6645398961..5af98a6a233 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 @@ -648,10 +648,6 @@ class TunnelTest(object): self._verify_mock_calls() -class TunnelTestOFCtl(TunnelTest, ovs_test_base.OVSOFCtlTestBase): - pass - - class TunnelTestOSKen(TunnelTest, ovs_test_base.OVSOSKenTestBase): pass @@ -745,11 +741,6 @@ class TunnelTestUseVethInterco(TunnelTest): '--timeout=10'])] -class TunnelTestUseVethIntercoOFCtl(TunnelTestUseVethInterco, - ovs_test_base.OVSOFCtlTestBase): - pass - - class TunnelTestUseVethIntercoOSKen(TunnelTestUseVethInterco, ovs_test_base.OVSOSKenTestBase): pass @@ -764,11 +755,6 @@ class TunnelTestWithMTU(TunnelTestUseVethInterco): self.intb_expected.append(mock.call.link.set_mtu(self.VETH_MTU)) -class TunnelTestWithMTUOFCtl(TunnelTestWithMTU, - ovs_test_base.OVSOFCtlTestBase): - pass - - class TunnelTestWithMTUOSKen(TunnelTestWithMTU, ovs_test_base.OVSOSKenTestBase): pass diff --git a/neutron/tests/unit/services/logapi/agent/test_log_extension.py b/neutron/tests/unit/services/logapi/agent/test_log_extension.py index e18ceba1168..ff909c61a0c 100644 --- a/neutron/tests/unit/services/logapi/agent/test_log_extension.py +++ b/neutron/tests/unit/services/logapi/agent/test_log_extension.py @@ -24,7 +24,7 @@ from neutron.api.rpc.handlers import resources_rpc from neutron.plugins.ml2.drivers.openvswitch.agent import ( ovs_agent_extension_api as ovs_ext_api) from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants -from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl import ( +from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.native import ( ovs_bridge) from neutron.services.logapi.agent import log_extension as log_ext from neutron.tests import base @@ -54,10 +54,12 @@ class LoggingExtensionBaseTestCase(base.BaseTestCase): self.agent_ext = log_ext.LoggingExtension() self.context = context.get_admin_context() self.connection = mock.Mock() + os_ken_app = mock.Mock() agent_api = ovs_ext_api.OVSAgentExtensionAPI( - ovs_bridge.OVSAgentBridge('br-int'), - ovs_bridge.OVSAgentBridge('br-tun'), - {'physnet1': ovs_bridge.OVSAgentBridge('br-physnet1')}) + ovs_bridge.OVSAgentBridge('br-int', os_ken_app=os_ken_app), + ovs_bridge.OVSAgentBridge('br-tun', os_ken_app=os_ken_app), + {'physnet1': ovs_bridge.OVSAgentBridge( + 'br-physnet1', os_ken_app=os_ken_app)}) self.agent_ext.consume_api(agent_api) mock.patch( 'neutron.manager.NeutronManager.load_class_for_provider').start() diff --git a/releasenotes/notes/remove-of_interface-option-531ac8a1c767603a.yaml b/releasenotes/notes/remove-of_interface-option-531ac8a1c767603a.yaml new file mode 100644 index 00000000000..c81fc5c6241 --- /dev/null +++ b/releasenotes/notes/remove-of_interface-option-531ac8a1c767603a.yaml @@ -0,0 +1,9 @@ +--- +upgrade: + - | + The deprecated ``of_interface`` option is removed. Neutron will + always use the ``native`` driver, which has been the default + since Pike (11.0). + If old driver ``ovs-ofctl`` was used before upgrade, automatically + done change to ``native`` driver will cause short break of data plane + connectivity during neutron-ovs-agent upgrade.