Make DVR router support FLAT network for ovs-agent
Currently codes only support assocate tunnel network and vlan network to DVR router. This patch add codes that make the flat network assocate to DVR router and make it work fine. The patch also remove two unused constant entries: 'FLAT_VLAN_ID' and 'LOCAL_VLAN_ID' Change-Id: I7d792ce288d96548298f169748565266a130bd86 Closes-Bug: #1876092
This commit is contained in:
parent
64b92687a5
commit
cd721a7dcb
|
@ -771,32 +771,47 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
||||||
return {id_: port.neutron_port_dict
|
return {id_: port.neutron_port_dict
|
||||||
for id_, port in self.sg_port_map.ports.items()}
|
for id_, port in self.sg_port_map.ports.items()}
|
||||||
|
|
||||||
def install_vlan_direct_flow(self, mac, segment_id, ofport, local_vlan):
|
def install_physical_direct_flow(self, mac, segment_id,
|
||||||
# If the port segment_id is not None/0, the
|
ofport, local_vlan, network_type):
|
||||||
# port's network type must be VLAN type.
|
actions = ('set_field:{:d}->reg{:d},'
|
||||||
if segment_id:
|
'set_field:{:d}->reg{:d},').format(
|
||||||
|
ofport,
|
||||||
|
ovsfw_consts.REG_PORT,
|
||||||
|
# This always needs the local vlan.
|
||||||
|
local_vlan,
|
||||||
|
ovsfw_consts.REG_NET)
|
||||||
|
if network_type == lib_const.TYPE_VLAN:
|
||||||
|
actions += 'strip_vlan,resubmit(,{:d})'.format(
|
||||||
|
ovs_consts.BASE_INGRESS_TABLE)
|
||||||
self._add_flow(
|
self._add_flow(
|
||||||
table=ovs_consts.TRANSIENT_TABLE,
|
table=ovs_consts.TRANSIENT_TABLE,
|
||||||
priority=90,
|
priority=90,
|
||||||
dl_dst=mac,
|
dl_dst=mac,
|
||||||
dl_vlan='0x%x' % segment_id,
|
dl_vlan='0x%x' % segment_id,
|
||||||
actions='set_field:{:d}->reg{:d},'
|
actions=actions)
|
||||||
'set_field:{:d}->reg{:d},'
|
elif network_type == lib_const.TYPE_FLAT:
|
||||||
'strip_vlan,resubmit(,{:d})'.format(
|
# If the port belong to flat network, we need match vlan_tci and
|
||||||
ofport,
|
# needn't pop vlan
|
||||||
ovsfw_consts.REG_PORT,
|
actions += 'resubmit(,{:d})'.format(
|
||||||
# This always needs the local vlan.
|
ovs_consts.BASE_INGRESS_TABLE)
|
||||||
local_vlan,
|
self._add_flow(
|
||||||
ovsfw_consts.REG_NET,
|
table=ovs_consts.TRANSIENT_TABLE,
|
||||||
ovs_consts.BASE_INGRESS_TABLE)
|
priority=90,
|
||||||
)
|
dl_dst=mac,
|
||||||
|
vlan_tci=ovs_consts.FLAT_VLAN_TCI,
|
||||||
|
actions=actions)
|
||||||
|
|
||||||
def delete_vlan_direct_flow(self, mac, segment_id):
|
def delete_physical_direct_flow(self, mac, segment_id):
|
||||||
if segment_id:
|
if segment_id:
|
||||||
self._strict_delete_flow(priority=90,
|
self._strict_delete_flow(priority=90,
|
||||||
table=ovs_consts.TRANSIENT_TABLE,
|
table=ovs_consts.TRANSIENT_TABLE,
|
||||||
dl_dst=mac,
|
dl_dst=mac,
|
||||||
dl_vlan=segment_id)
|
dl_vlan=segment_id)
|
||||||
|
else:
|
||||||
|
self._strict_delete_flow(priority=90,
|
||||||
|
table=ovs_consts.TRANSIENT_TABLE,
|
||||||
|
dl_dst=mac,
|
||||||
|
vlan_tci=ovs_consts.FLAT_VLAN_TCI)
|
||||||
|
|
||||||
def initialize_port_flows(self, port):
|
def initialize_port_flows(self, port):
|
||||||
"""Set base flows for port
|
"""Set base flows for port
|
||||||
|
@ -821,8 +836,9 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
||||||
|
|
||||||
# Identify ingress flows
|
# Identify ingress flows
|
||||||
for mac_addr in port.all_allowed_macs:
|
for mac_addr in port.all_allowed_macs:
|
||||||
self.install_vlan_direct_flow(
|
self.install_physical_direct_flow(
|
||||||
mac_addr, port.segment_id, port.ofport, port.vlan_tag)
|
mac_addr, port.segment_id, port.ofport,
|
||||||
|
port.vlan_tag, port.network_type)
|
||||||
|
|
||||||
self._add_flow(
|
self._add_flow(
|
||||||
table=ovs_consts.TRANSIENT_TABLE,
|
table=ovs_consts.TRANSIENT_TABLE,
|
||||||
|
@ -1406,7 +1422,7 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
||||||
table=ovs_consts.TRANSIENT_TABLE,
|
table=ovs_consts.TRANSIENT_TABLE,
|
||||||
dl_dst=mac_addr,
|
dl_dst=mac_addr,
|
||||||
dl_vlan=port.vlan_tag)
|
dl_vlan=port.vlan_tag)
|
||||||
self.delete_vlan_direct_flow(mac_addr, port.segment_id)
|
self.delete_physical_direct_flow(mac_addr, port.segment_id)
|
||||||
self._delete_flows(table=ovs_consts.ACCEPT_OR_INGRESS_TABLE,
|
self._delete_flows(table=ovs_consts.ACCEPT_OR_INGRESS_TABLE,
|
||||||
dl_dst=mac_addr, reg_net=port.vlan_tag)
|
dl_dst=mac_addr, reg_net=port.vlan_tag)
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,6 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
FLAT_VLAN_ID = -1
|
|
||||||
LOCAL_VLAN_ID = -2
|
|
||||||
|
|
||||||
# Supported VXLAN features
|
# Supported VXLAN features
|
||||||
VXLAN_NONE = 'not_supported'
|
VXLAN_NONE = 'not_supported'
|
||||||
VXLAN_MCAST = 'multicast_flooding'
|
VXLAN_MCAST = 'multicast_flooding'
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
from neutron_lib import constants as p_const
|
from neutron_lib import constants as p_const
|
||||||
|
|
||||||
|
|
||||||
# Special vlan_id value in ovs_vlan_allocations table indicating flat network
|
# Special vlan_tci value indicating flat network
|
||||||
FLAT_VLAN_ID = -1
|
FLAT_VLAN_TCI = '0x0000/0x1fff'
|
||||||
|
|
||||||
# Topic for tunnel notifications between the plugin and agent
|
# Topic for tunnel notifications between the plugin and agent
|
||||||
TUNNEL = 'tunnel'
|
TUNNEL = 'tunnel'
|
||||||
|
@ -41,11 +41,14 @@ TUNNEL_NETWORK_TYPES = [p_const.TYPE_GRE, p_const.TYPE_VXLAN,
|
||||||
|
|
||||||
LOCAL_SWITCHING = 0
|
LOCAL_SWITCHING = 0
|
||||||
|
|
||||||
|
# The pyhsical network types of support DVR router
|
||||||
|
DVR_PHYSICAL_NETWORK_TYPES = [p_const.TYPE_VLAN, p_const.TYPE_FLAT]
|
||||||
|
|
||||||
# Various tables for DVR use of integration bridge flows
|
# Various tables for DVR use of integration bridge flows
|
||||||
DVR_TO_SRC_MAC = 1
|
DVR_TO_SRC_MAC = 1
|
||||||
DVR_TO_SRC_MAC_VLAN = 2
|
DVR_TO_SRC_MAC_PHYSICAL = 2
|
||||||
ARP_DVR_MAC_TO_DST_MAC = 3
|
ARP_DVR_MAC_TO_DST_MAC = 3
|
||||||
ARP_DVR_MAC_TO_DST_MAC_VLAN = 4
|
ARP_DVR_MAC_TO_DST_MAC_PHYSICAL = 4
|
||||||
CANARY_TABLE = 23
|
CANARY_TABLE = 23
|
||||||
|
|
||||||
# Table for ARP poison/spoofing prevention rules
|
# Table for ARP poison/spoofing prevention rules
|
||||||
|
@ -82,7 +85,7 @@ ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE = 94
|
||||||
INT_BR_ALL_TABLES = (
|
INT_BR_ALL_TABLES = (
|
||||||
LOCAL_SWITCHING,
|
LOCAL_SWITCHING,
|
||||||
DVR_TO_SRC_MAC,
|
DVR_TO_SRC_MAC,
|
||||||
DVR_TO_SRC_MAC_VLAN,
|
DVR_TO_SRC_MAC_PHYSICAL,
|
||||||
CANARY_TABLE,
|
CANARY_TABLE,
|
||||||
ARP_SPOOF_TABLE,
|
ARP_SPOOF_TABLE,
|
||||||
MAC_SPOOF_TABLE,
|
MAC_SPOOF_TABLE,
|
||||||
|
@ -128,15 +131,15 @@ TUN_BR_ALL_TABLES = (
|
||||||
# --- Physical Bridges (phys_brs)
|
# --- Physical Bridges (phys_brs)
|
||||||
|
|
||||||
# Various tables for DVR use of physical bridge flows
|
# Various tables for DVR use of physical bridge flows
|
||||||
DVR_PROCESS_VLAN = 1
|
DVR_PROCESS_PHYSICAL = 1
|
||||||
LOCAL_VLAN_TRANSLATION = 2
|
LOCAL_VLAN_TRANSLATION = 2
|
||||||
DVR_NOT_LEARN_VLAN = 3
|
DVR_NOT_LEARN_PHYSICAL = 3
|
||||||
|
|
||||||
PHY_BR_ALL_TABLES = (
|
PHY_BR_ALL_TABLES = (
|
||||||
LOCAL_SWITCHING,
|
LOCAL_SWITCHING,
|
||||||
DVR_PROCESS_VLAN,
|
DVR_PROCESS_PHYSICAL,
|
||||||
LOCAL_VLAN_TRANSLATION,
|
LOCAL_VLAN_TRANSLATION,
|
||||||
DVR_NOT_LEARN_VLAN)
|
DVR_NOT_LEARN_PHYSICAL)
|
||||||
|
|
||||||
# --- end of OpenFlow table IDs
|
# --- end of OpenFlow table IDs
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
from neutron_lib import constants as p_const
|
|
||||||
from os_ken.lib.packet import ether_types
|
from os_ken.lib.packet import ether_types
|
||||||
from os_ken.lib.packet import icmpv6
|
from os_ken.lib.packet import icmpv6
|
||||||
from os_ken.lib.packet import in_proto
|
from os_ken.lib.packet import in_proto
|
||||||
|
@ -103,13 +102,15 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge):
|
||||||
def _arp_dvr_dst_mac_match(ofp, ofpp, vlan, dvr_mac):
|
def _arp_dvr_dst_mac_match(ofp, ofpp, vlan, dvr_mac):
|
||||||
# If eth_dst is equal to the dvr mac of this host, then
|
# If eth_dst is equal to the dvr mac of this host, then
|
||||||
# flag it as matched.
|
# flag it as matched.
|
||||||
|
if not vlan:
|
||||||
|
return ofpp.OFPMatch(vlan_vid=ofp.OFPVID_NONE, eth_dst=dvr_mac)
|
||||||
return ofpp.OFPMatch(vlan_vid=vlan | ofp.OFPVID_PRESENT,
|
return ofpp.OFPMatch(vlan_vid=vlan | ofp.OFPVID_PRESENT,
|
||||||
eth_dst=dvr_mac)
|
eth_dst=dvr_mac)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _dvr_dst_mac_table_id(network_type):
|
def _dvr_dst_mac_table_id(network_type):
|
||||||
if network_type == p_const.TYPE_VLAN:
|
if network_type in constants.DVR_PHYSICAL_NETWORK_TYPES:
|
||||||
return constants.ARP_DVR_MAC_TO_DST_MAC_VLAN
|
return constants.ARP_DVR_MAC_TO_DST_MAC_PHYSICAL
|
||||||
else:
|
else:
|
||||||
return constants.ARP_DVR_MAC_TO_DST_MAC
|
return constants.ARP_DVR_MAC_TO_DST_MAC
|
||||||
|
|
||||||
|
@ -137,13 +138,16 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _dvr_to_src_mac_match(ofp, ofpp, vlan_tag, dst_mac):
|
def _dvr_to_src_mac_match(ofp, ofpp, vlan_tag, dst_mac):
|
||||||
|
if not vlan_tag:
|
||||||
|
# When the network is flat type, the vlan_tag will be None.
|
||||||
|
return ofpp.OFPMatch(vlan_vid=ofp.OFPVID_NONE, eth_dst=dst_mac)
|
||||||
return ofpp.OFPMatch(vlan_vid=vlan_tag | ofp.OFPVID_PRESENT,
|
return ofpp.OFPMatch(vlan_vid=vlan_tag | ofp.OFPVID_PRESENT,
|
||||||
eth_dst=dst_mac)
|
eth_dst=dst_mac)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _dvr_to_src_mac_table_id(network_type):
|
def _dvr_to_src_mac_table_id(network_type):
|
||||||
if network_type == p_const.TYPE_VLAN:
|
if network_type in constants.DVR_PHYSICAL_NETWORK_TYPES:
|
||||||
return constants.DVR_TO_SRC_MAC_VLAN
|
return constants.DVR_TO_SRC_MAC_PHYSICAL
|
||||||
else:
|
else:
|
||||||
return constants.DVR_TO_SRC_MAC
|
return constants.DVR_TO_SRC_MAC
|
||||||
|
|
||||||
|
@ -164,10 +168,10 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge):
|
||||||
priority=20,
|
priority=20,
|
||||||
match=match,
|
match=match,
|
||||||
instructions=instructions)
|
instructions=instructions)
|
||||||
actions = [
|
actions = []
|
||||||
ofpp.OFPActionPopVlan(),
|
if vlan_tag:
|
||||||
ofpp.OFPActionOutput(dst_port, 0),
|
actions.append(ofpp.OFPActionPopVlan())
|
||||||
]
|
actions.append(ofpp.OFPActionOutput(dst_port, 0))
|
||||||
self.install_apply_actions(table_id=constants.TRANSIENT_TABLE,
|
self.install_apply_actions(table_id=constants.TRANSIENT_TABLE,
|
||||||
priority=20,
|
priority=20,
|
||||||
match=match,
|
match=match,
|
||||||
|
@ -182,12 +186,12 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge):
|
||||||
self.uninstall_flows(
|
self.uninstall_flows(
|
||||||
strict=True, priority=20, table_id=table, match=match)
|
strict=True, priority=20, table_id=table, match=match)
|
||||||
|
|
||||||
def add_dvr_mac_vlan(self, mac, port):
|
def add_dvr_mac_physical(self, mac, port):
|
||||||
self.install_goto(table_id=constants.LOCAL_SWITCHING,
|
self.install_goto(table_id=constants.LOCAL_SWITCHING,
|
||||||
priority=4,
|
priority=4,
|
||||||
in_port=port,
|
in_port=port,
|
||||||
eth_src=mac,
|
eth_src=mac,
|
||||||
dest_table_id=constants.DVR_TO_SRC_MAC_VLAN)
|
dest_table_id=constants.DVR_TO_SRC_MAC_PHYSICAL)
|
||||||
|
|
||||||
def remove_dvr_mac_vlan(self, mac):
|
def remove_dvr_mac_vlan(self, mac):
|
||||||
# REVISIT(yamamoto): match in_port as well?
|
# REVISIT(yamamoto): match in_port as well?
|
||||||
|
@ -214,11 +218,12 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge):
|
||||||
strict=True, priority=5, table_id=table_id, match=match)
|
strict=True, priority=5, table_id=table_id, match=match)
|
||||||
|
|
||||||
def add_dvr_gateway_mac_arp_vlan(self, mac, port):
|
def add_dvr_gateway_mac_arp_vlan(self, mac, port):
|
||||||
self.install_goto(table_id=constants.LOCAL_SWITCHING,
|
self.install_goto(
|
||||||
priority=5,
|
table_id=constants.LOCAL_SWITCHING,
|
||||||
in_port=port,
|
priority=5,
|
||||||
eth_dst=mac,
|
in_port=port,
|
||||||
dest_table_id=constants.ARP_DVR_MAC_TO_DST_MAC_VLAN)
|
eth_dst=mac,
|
||||||
|
dest_table_id=constants.ARP_DVR_MAC_TO_DST_MAC_PHYSICAL)
|
||||||
|
|
||||||
def remove_dvr_gateway_mac_arp_vlan(self, mac, port):
|
def remove_dvr_gateway_mac_arp_vlan(self, mac, port):
|
||||||
self.uninstall_flows(table_id=constants.LOCAL_SWITCHING,
|
self.uninstall_flows(table_id=constants.LOCAL_SWITCHING,
|
||||||
|
|
|
@ -26,7 +26,7 @@ class OVSPhysicalBridge(ovs_bridge.OVSAgentBridge,
|
||||||
"""openvswitch agent physical bridge specific logic."""
|
"""openvswitch agent physical bridge specific logic."""
|
||||||
|
|
||||||
# Used by OVSDVRProcessMixin
|
# Used by OVSDVRProcessMixin
|
||||||
dvr_process_table_id = constants.DVR_PROCESS_VLAN
|
dvr_process_table_id = constants.DVR_PROCESS_PHYSICAL
|
||||||
dvr_process_next_table_id = constants.LOCAL_VLAN_TRANSLATION
|
dvr_process_next_table_id = constants.LOCAL_VLAN_TRANSLATION
|
||||||
of_tables = constants.PHY_BR_ALL_TABLES
|
of_tables = constants.PHY_BR_ALL_TABLES
|
||||||
|
|
||||||
|
@ -57,12 +57,12 @@ class OVSPhysicalBridge(ovs_bridge.OVSAgentBridge,
|
||||||
match = self._local_vlan_match(ofp, ofpp, port, lvid)
|
match = self._local_vlan_match(ofp, ofpp, port, lvid)
|
||||||
self.uninstall_flows(match=match)
|
self.uninstall_flows(match=match)
|
||||||
|
|
||||||
def add_dvr_mac_vlan(self, mac, port):
|
def add_dvr_mac_physical(self, mac, port):
|
||||||
self.install_output(table_id=constants.DVR_NOT_LEARN_VLAN,
|
self.install_output(table_id=constants.DVR_NOT_LEARN_PHYSICAL,
|
||||||
priority=2, eth_src=mac, port=port)
|
priority=2, eth_src=mac, port=port)
|
||||||
|
|
||||||
def remove_dvr_mac_vlan(self, mac):
|
def remove_dvr_mac_vlan(self, mac):
|
||||||
# REVISIT(yamamoto): match in_port as well?
|
# REVISIT(yamamoto): match in_port as well?
|
||||||
self.uninstall_flows(
|
self.uninstall_flows(
|
||||||
table_id=constants.DVR_NOT_LEARN_VLAN,
|
table_id=constants.DVR_NOT_LEARN_PHYSICAL,
|
||||||
eth_src=mac)
|
eth_src=mac)
|
||||||
|
|
|
@ -224,7 +224,7 @@ class OVSDVRNeutronAgent(object):
|
||||||
# Insert 'drop' action as the default for Table DVR_TO_SRC_MAC
|
# Insert 'drop' action as the default for Table DVR_TO_SRC_MAC
|
||||||
self.int_br.install_drop(table_id=constants.DVR_TO_SRC_MAC, priority=1)
|
self.int_br.install_drop(table_id=constants.DVR_TO_SRC_MAC, priority=1)
|
||||||
|
|
||||||
self.int_br.install_drop(table_id=constants.DVR_TO_SRC_MAC_VLAN,
|
self.int_br.install_drop(table_id=constants.DVR_TO_SRC_MAC_PHYSICAL,
|
||||||
priority=1)
|
priority=1)
|
||||||
|
|
||||||
for physical_network in self.bridge_mappings:
|
for physical_network in self.bridge_mappings:
|
||||||
|
@ -256,12 +256,12 @@ class OVSDVRNeutronAgent(object):
|
||||||
self.phys_brs[physical_network].install_goto(
|
self.phys_brs[physical_network].install_goto(
|
||||||
in_port=self.phys_ofports[physical_network],
|
in_port=self.phys_ofports[physical_network],
|
||||||
priority=2,
|
priority=2,
|
||||||
dest_table_id=constants.DVR_PROCESS_VLAN)
|
dest_table_id=constants.DVR_PROCESS_PHYSICAL)
|
||||||
self.phys_brs[physical_network].install_goto(
|
self.phys_brs[physical_network].install_goto(
|
||||||
priority=1,
|
priority=1,
|
||||||
dest_table_id=constants.DVR_NOT_LEARN_VLAN)
|
dest_table_id=constants.DVR_NOT_LEARN_PHYSICAL)
|
||||||
self.phys_brs[physical_network].install_goto(
|
self.phys_brs[physical_network].install_goto(
|
||||||
table_id=constants.DVR_PROCESS_VLAN,
|
table_id=constants.DVR_PROCESS_PHYSICAL,
|
||||||
priority=0,
|
priority=0,
|
||||||
dest_table_id=constants.LOCAL_VLAN_TRANSLATION)
|
dest_table_id=constants.LOCAL_VLAN_TRANSLATION)
|
||||||
self.phys_brs[physical_network].install_drop(
|
self.phys_brs[physical_network].install_drop(
|
||||||
|
@ -269,15 +269,15 @@ class OVSDVRNeutronAgent(object):
|
||||||
in_port=self.phys_ofports[physical_network],
|
in_port=self.phys_ofports[physical_network],
|
||||||
priority=2)
|
priority=2)
|
||||||
self.phys_brs[physical_network].install_normal(
|
self.phys_brs[physical_network].install_normal(
|
||||||
table_id=constants.DVR_NOT_LEARN_VLAN,
|
table_id=constants.DVR_NOT_LEARN_PHYSICAL,
|
||||||
priority=1)
|
priority=1)
|
||||||
|
|
||||||
def _add_dvr_mac_for_phys_br(self, physical_network, mac):
|
def _add_dvr_mac_for_phys_br(self, physical_network, mac):
|
||||||
self.int_br.add_dvr_mac_vlan(mac=mac,
|
self.int_br.add_dvr_mac_physical(
|
||||||
port=self.int_ofports[physical_network])
|
mac=mac, port=self.int_ofports[physical_network])
|
||||||
phys_br = self.phys_brs[physical_network]
|
phys_br = self.phys_brs[physical_network]
|
||||||
phys_br.add_dvr_mac_vlan(mac=mac,
|
phys_br.add_dvr_mac_physical(
|
||||||
port=self.phys_ofports[physical_network])
|
mac=mac, port=self.phys_ofports[physical_network])
|
||||||
|
|
||||||
def _add_arp_dvr_mac_for_phys_br(self, physical_network, mac):
|
def _add_arp_dvr_mac_for_phys_br(self, physical_network, mac):
|
||||||
self.int_br.add_dvr_gateway_mac_arp_vlan(
|
self.int_br.add_dvr_gateway_mac_arp_vlan(
|
||||||
|
@ -402,7 +402,7 @@ class OVSDVRNeutronAgent(object):
|
||||||
ldm.set_dvr_owned(True)
|
ldm.set_dvr_owned(True)
|
||||||
|
|
||||||
vlan_to_use = lvm.vlan
|
vlan_to_use = lvm.vlan
|
||||||
if lvm.network_type == n_const.TYPE_VLAN:
|
if lvm.network_type in constants.DVR_PHYSICAL_NETWORK_TYPES:
|
||||||
vlan_to_use = lvm.segmentation_id
|
vlan_to_use = lvm.segmentation_id
|
||||||
|
|
||||||
subnet_info = ldm.get_subnet_info()
|
subnet_info = ldm.get_subnet_info()
|
||||||
|
@ -456,7 +456,7 @@ class OVSDVRNeutronAgent(object):
|
||||||
dvr_mac=self.dvr_mac_address,
|
dvr_mac=self.dvr_mac_address,
|
||||||
rtr_port=port.ofport)
|
rtr_port=port.ofport)
|
||||||
|
|
||||||
if lvm.network_type == n_const.TYPE_VLAN:
|
if lvm.network_type in constants.DVR_PHYSICAL_NETWORK_TYPES:
|
||||||
# TODO(vivek) remove the IPv6 related flows once SNAT is not
|
# TODO(vivek) remove the IPv6 related flows once SNAT is not
|
||||||
# used for IPv6 DVR.
|
# used for IPv6 DVR.
|
||||||
br = self.phys_brs[lvm.physical_network]
|
br = self.phys_brs[lvm.physical_network]
|
||||||
|
@ -517,7 +517,7 @@ class OVSDVRNeutronAgent(object):
|
||||||
ovsport.add_subnet(subnet_uuid)
|
ovsport.add_subnet(subnet_uuid)
|
||||||
self.local_ports[port.vif_id] = ovsport
|
self.local_ports[port.vif_id] = ovsport
|
||||||
vlan_to_use = lvm.vlan
|
vlan_to_use = lvm.vlan
|
||||||
if lvm.network_type == n_const.TYPE_VLAN:
|
if lvm.network_type in constants.DVR_PHYSICAL_NETWORK_TYPES:
|
||||||
vlan_to_use = lvm.segmentation_id
|
vlan_to_use = lvm.segmentation_id
|
||||||
# create a rule for this vm port
|
# create a rule for this vm port
|
||||||
self.int_br.install_dvr_to_src_mac(
|
self.int_br.install_dvr_to_src_mac(
|
||||||
|
@ -577,7 +577,7 @@ class OVSDVRNeutronAgent(object):
|
||||||
ovsport.add_subnet(subnet_uuid)
|
ovsport.add_subnet(subnet_uuid)
|
||||||
self.local_ports[port.vif_id] = ovsport
|
self.local_ports[port.vif_id] = ovsport
|
||||||
vlan_to_use = lvm.vlan
|
vlan_to_use = lvm.vlan
|
||||||
if lvm.network_type == n_const.TYPE_VLAN:
|
if lvm.network_type in constants.DVR_PHYSICAL_NETWORK_TYPES:
|
||||||
vlan_to_use = lvm.segmentation_id
|
vlan_to_use = lvm.segmentation_id
|
||||||
self.int_br.install_dvr_to_src_mac(
|
self.int_br.install_dvr_to_src_mac(
|
||||||
network_type=lvm.network_type,
|
network_type=lvm.network_type,
|
||||||
|
@ -591,8 +591,9 @@ class OVSDVRNeutronAgent(object):
|
||||||
if not self.in_distributed_mode():
|
if not self.in_distributed_mode():
|
||||||
return
|
return
|
||||||
|
|
||||||
if local_vlan_map.network_type not in (constants.TUNNEL_NETWORK_TYPES +
|
if (local_vlan_map.network_type not in
|
||||||
[n_const.TYPE_VLAN]):
|
(constants.TUNNEL_NETWORK_TYPES +
|
||||||
|
constants.DVR_PHYSICAL_NETWORK_TYPES)):
|
||||||
LOG.debug("DVR: Port %s is with network_type %s not supported"
|
LOG.debug("DVR: Port %s is with network_type %s not supported"
|
||||||
" for dvr plumbing", port.vif_id,
|
" for dvr plumbing", port.vif_id,
|
||||||
local_vlan_map.network_type)
|
local_vlan_map.network_type)
|
||||||
|
@ -629,7 +630,7 @@ class OVSDVRNeutronAgent(object):
|
||||||
network_type = lvm.network_type
|
network_type = lvm.network_type
|
||||||
physical_network = lvm.physical_network
|
physical_network = lvm.physical_network
|
||||||
vlan_to_use = lvm.vlan
|
vlan_to_use = lvm.vlan
|
||||||
if network_type == n_const.TYPE_VLAN:
|
if network_type in constants.DVR_PHYSICAL_NETWORK_TYPES:
|
||||||
vlan_to_use = lvm.segmentation_id
|
vlan_to_use = lvm.segmentation_id
|
||||||
# ensure we process for all the subnets laid on this removed port
|
# ensure we process for all the subnets laid on this removed port
|
||||||
for sub_uuid in subnet_set:
|
for sub_uuid in subnet_set:
|
||||||
|
@ -660,7 +661,7 @@ class OVSDVRNeutronAgent(object):
|
||||||
# this subnet from local_dvr_map, as no dvr (or) csnat
|
# this subnet from local_dvr_map, as no dvr (or) csnat
|
||||||
# ports available on this agent anymore
|
# ports available on this agent anymore
|
||||||
self.local_dvr_map.pop(sub_uuid, None)
|
self.local_dvr_map.pop(sub_uuid, None)
|
||||||
if network_type == n_const.TYPE_VLAN:
|
if network_type in constants.DVR_PHYSICAL_NETWORK_TYPES:
|
||||||
br = self.phys_brs[physical_network]
|
br = self.phys_brs[physical_network]
|
||||||
if network_type in constants.TUNNEL_NETWORK_TYPES:
|
if network_type in constants.TUNNEL_NETWORK_TYPES:
|
||||||
br = self.tun_br
|
br = self.tun_br
|
||||||
|
@ -679,7 +680,7 @@ class OVSDVRNeutronAgent(object):
|
||||||
self.firewall.delete_accepted_egress_direct_flow(
|
self.firewall.delete_accepted_egress_direct_flow(
|
||||||
subnet_info['gateway_mac'], lvm.vlan)
|
subnet_info['gateway_mac'], lvm.vlan)
|
||||||
|
|
||||||
if lvm.network_type == n_const.TYPE_VLAN:
|
if lvm.network_type in constants.DVR_PHYSICAL_NETWORK_TYPES:
|
||||||
br = self.phys_brs[physical_network]
|
br = self.phys_brs[physical_network]
|
||||||
if lvm.network_type in constants.TUNNEL_NETWORK_TYPES:
|
if lvm.network_type in constants.TUNNEL_NETWORK_TYPES:
|
||||||
br = self.tun_br
|
br = self.tun_br
|
||||||
|
@ -701,7 +702,7 @@ class OVSDVRNeutronAgent(object):
|
||||||
ldm = self.local_dvr_map[sub_uuid]
|
ldm = self.local_dvr_map[sub_uuid]
|
||||||
ldm.remove_compute_ofport(port.vif_id)
|
ldm.remove_compute_ofport(port.vif_id)
|
||||||
vlan_to_use = lvm.vlan
|
vlan_to_use = lvm.vlan
|
||||||
if lvm.network_type == n_const.TYPE_VLAN:
|
if lvm.network_type in constants.DVR_PHYSICAL_NETWORK_TYPES:
|
||||||
vlan_to_use = lvm.segmentation_id
|
vlan_to_use = lvm.segmentation_id
|
||||||
# first remove this vm port rule
|
# first remove this vm port rule
|
||||||
self.int_br.delete_dvr_to_src_mac(
|
self.int_br.delete_dvr_to_src_mac(
|
||||||
|
@ -722,7 +723,7 @@ class OVSDVRNeutronAgent(object):
|
||||||
ldm = self.local_dvr_map[sub_uuid]
|
ldm = self.local_dvr_map[sub_uuid]
|
||||||
ldm.set_csnat_ofport(constants.OFPORT_INVALID)
|
ldm.set_csnat_ofport(constants.OFPORT_INVALID)
|
||||||
vlan_to_use = lvm.vlan
|
vlan_to_use = lvm.vlan
|
||||||
if lvm.network_type == n_const.TYPE_VLAN:
|
if lvm.network_type in constants.DVR_PHYSICAL_NETWORK_TYPES:
|
||||||
vlan_to_use = lvm.segmentation_id
|
vlan_to_use = lvm.segmentation_id
|
||||||
# then remove csnat port rule
|
# then remove csnat port rule
|
||||||
self.int_br.delete_dvr_to_src_mac(
|
self.int_br.delete_dvr_to_src_mac(
|
||||||
|
|
|
@ -896,18 +896,8 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin,
|
||||||
else:
|
else:
|
||||||
LOG.warning('Action %s not supported', action)
|
LOG.warning('Action %s not supported', action)
|
||||||
|
|
||||||
def _local_vlan_for_flat(self, lvid, physical_network):
|
def _local_vlan_for_physical(self, lvid, physical_network,
|
||||||
phys_br = self.phys_brs[physical_network]
|
segmentation_id=None):
|
||||||
phys_port = self.phys_ofports[physical_network]
|
|
||||||
int_br = self.int_br
|
|
||||||
int_port = self.int_ofports[physical_network]
|
|
||||||
phys_br.provision_local_vlan(port=phys_port, lvid=lvid,
|
|
||||||
segmentation_id=None,
|
|
||||||
distributed=False)
|
|
||||||
int_br.provision_local_vlan(port=int_port, lvid=lvid,
|
|
||||||
segmentation_id=None)
|
|
||||||
|
|
||||||
def _local_vlan_for_vlan(self, lvid, physical_network, segmentation_id):
|
|
||||||
distributed = self.enable_distributed_routing
|
distributed = self.enable_distributed_routing
|
||||||
phys_br = self.phys_brs[physical_network]
|
phys_br = self.phys_brs[physical_network]
|
||||||
phys_port = self.phys_ofports[physical_network]
|
phys_port = self.phys_ofports[physical_network]
|
||||||
|
@ -988,7 +978,7 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin,
|
||||||
'net_uuid': net_uuid})
|
'net_uuid': net_uuid})
|
||||||
elif network_type == n_const.TYPE_FLAT:
|
elif network_type == n_const.TYPE_FLAT:
|
||||||
if physical_network in self.phys_brs:
|
if physical_network in self.phys_brs:
|
||||||
self._local_vlan_for_flat(lvid, physical_network)
|
self._local_vlan_for_physical(lvid, physical_network)
|
||||||
else:
|
else:
|
||||||
LOG.error("Cannot provision flat network for "
|
LOG.error("Cannot provision flat network for "
|
||||||
"net-id=%(net_uuid)s - no bridge for "
|
"net-id=%(net_uuid)s - no bridge for "
|
||||||
|
@ -997,8 +987,8 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin,
|
||||||
'physical_network': physical_network})
|
'physical_network': physical_network})
|
||||||
elif network_type == n_const.TYPE_VLAN:
|
elif network_type == n_const.TYPE_VLAN:
|
||||||
if physical_network in self.phys_brs:
|
if physical_network in self.phys_brs:
|
||||||
self._local_vlan_for_vlan(lvid, physical_network,
|
self._local_vlan_for_physical(lvid, physical_network,
|
||||||
segmentation_id)
|
segmentation_id)
|
||||||
else:
|
else:
|
||||||
LOG.error("Cannot provision VLAN network for "
|
LOG.error("Cannot provision VLAN network for "
|
||||||
"net-id=%(net_uuid)s - no bridge for "
|
"net-id=%(net_uuid)s - no bridge for "
|
||||||
|
|
|
@ -344,7 +344,8 @@ class OVSFlowTestCase(OVSAgentTestBase):
|
||||||
'dst_mac': '12:34:56:78:cc:dd',
|
'dst_mac': '12:34:56:78:cc:dd',
|
||||||
'dst_port': 123}
|
'dst_port': 123}
|
||||||
self.br_int.install_dvr_to_src_mac(network_type='vlan', **kwargs)
|
self.br_int.install_dvr_to_src_mac(network_type='vlan', **kwargs)
|
||||||
self.br_int.add_dvr_mac_vlan(mac=other_dvr_mac, port=other_dvr_port)
|
self.br_int.add_dvr_mac_physical(mac=other_dvr_mac,
|
||||||
|
port=other_dvr_port)
|
||||||
|
|
||||||
trace = self._run_trace(self.br.br_name,
|
trace = self._run_trace(self.br.br_name,
|
||||||
"in_port=%d," % other_dvr_port +
|
"in_port=%d," % other_dvr_port +
|
||||||
|
|
|
@ -38,11 +38,12 @@ TESTING_VLAN_TAG = 1
|
||||||
TESTING_SEGMENT = 1000
|
TESTING_SEGMENT = 1000
|
||||||
|
|
||||||
|
|
||||||
def create_ofport(port_dict, network_type=None, physical_network=None):
|
def create_ofport(port_dict, network_type=None,
|
||||||
|
physical_network=None, segment_id=TESTING_SEGMENT):
|
||||||
ovs_port = mock.Mock(vif_mac='00:00:00:00:00:00', ofport=1,
|
ovs_port = mock.Mock(vif_mac='00:00:00:00:00:00', ofport=1,
|
||||||
port_name="port-name")
|
port_name="port-name")
|
||||||
return ovsfw.OFPort(port_dict, ovs_port, vlan_tag=TESTING_VLAN_TAG,
|
return ovsfw.OFPort(port_dict, ovs_port, vlan_tag=TESTING_VLAN_TAG,
|
||||||
segment_id=TESTING_SEGMENT,
|
segment_id=segment_id,
|
||||||
network_type=network_type,
|
network_type=network_type,
|
||||||
physical_network=physical_network)
|
physical_network=physical_network)
|
||||||
|
|
||||||
|
@ -590,18 +591,23 @@ class TestOVSFirewallDriver(base.BaseTestCase):
|
||||||
self.firewall.prepare_port_filter(port_dict)
|
self.firewall.prepare_port_filter(port_dict)
|
||||||
self.assertFalse(m_init_flows.called)
|
self.assertFalse(m_init_flows.called)
|
||||||
|
|
||||||
def test_initialize_port_flows_vlan_dvr_conntrack_direct(self):
|
def _test_initialize_port_flows_dvr_conntrack_direct(self, network_type):
|
||||||
port_dict = {
|
port_dict = {
|
||||||
'device': 'port-id',
|
'device': 'port-id',
|
||||||
'security_groups': [1]}
|
'security_groups': [1]}
|
||||||
|
segment_id = None
|
||||||
|
if network_type == constants.TYPE_VLAN:
|
||||||
|
segment_id = TESTING_SEGMENT
|
||||||
of_port = create_ofport(port_dict,
|
of_port = create_ofport(port_dict,
|
||||||
network_type=constants.TYPE_VXLAN)
|
network_type=network_type,
|
||||||
|
segment_id=segment_id)
|
||||||
self.firewall.sg_port_map.ports[of_port.id] = of_port
|
self.firewall.sg_port_map.ports[of_port.id] = of_port
|
||||||
port = self.firewall.get_or_create_ofport(port_dict)
|
port = self.firewall.get_or_create_ofport(port_dict)
|
||||||
|
|
||||||
fake_patch_port = 999
|
fake_patch_port = 999
|
||||||
self.mock_bridge.br.get_port_ofport.return_value = fake_patch_port
|
self.mock_bridge.br.get_port_ofport.return_value = fake_patch_port
|
||||||
|
|
||||||
|
expected_calls = []
|
||||||
self.firewall.initialize_port_flows(port)
|
self.firewall.initialize_port_flows(port)
|
||||||
|
|
||||||
call_args1 = {
|
call_args1 = {
|
||||||
|
@ -616,22 +622,39 @@ class TestOVSFirewallDriver(base.BaseTestCase):
|
||||||
port.vlan_tag,
|
port.vlan_tag,
|
||||||
ovsfw_consts.REG_NET,
|
ovsfw_consts.REG_NET,
|
||||||
ovs_consts.BASE_EGRESS_TABLE)}
|
ovs_consts.BASE_EGRESS_TABLE)}
|
||||||
egress_flow_call = mock.call(**call_args1)
|
expected_calls.append(mock.call(**call_args1))
|
||||||
|
|
||||||
call_args2 = {
|
if network_type == constants.TYPE_VLAN:
|
||||||
'table': ovs_consts.TRANSIENT_TABLE,
|
call_args2 = {
|
||||||
'priority': 90,
|
'table': ovs_consts.TRANSIENT_TABLE,
|
||||||
'dl_dst': port.mac,
|
'priority': 90,
|
||||||
'dl_vlan': '0x%x' % port.segment_id,
|
'dl_dst': port.mac,
|
||||||
'actions': 'set_field:{:d}->reg{:d},'
|
'dl_vlan': '0x%x' % port.segment_id,
|
||||||
'set_field:{:d}->reg{:d},'
|
'actions': 'set_field:{:d}->reg{:d},'
|
||||||
'strip_vlan,resubmit(,{:d})'.format(
|
'set_field:{:d}->reg{:d},'
|
||||||
port.ofport,
|
'strip_vlan,resubmit(,{:d})'.format(
|
||||||
ovsfw_consts.REG_PORT,
|
port.ofport,
|
||||||
port.vlan_tag,
|
ovsfw_consts.REG_PORT,
|
||||||
ovsfw_consts.REG_NET,
|
port.vlan_tag,
|
||||||
ovs_consts.BASE_INGRESS_TABLE)}
|
ovsfw_consts.REG_NET,
|
||||||
ingress_flow_call1 = mock.call(**call_args2)
|
ovs_consts.BASE_INGRESS_TABLE)}
|
||||||
|
expected_calls.append(mock.call(**call_args2))
|
||||||
|
|
||||||
|
if network_type == constants.TYPE_FLAT:
|
||||||
|
call_args2 = {
|
||||||
|
'table': ovs_consts.TRANSIENT_TABLE,
|
||||||
|
'priority': 90,
|
||||||
|
'dl_dst': port.mac,
|
||||||
|
'vlan_tci': ovs_consts.FLAT_VLAN_TCI,
|
||||||
|
'actions': 'set_field:{:d}->reg{:d},'
|
||||||
|
'set_field:{:d}->reg{:d},'
|
||||||
|
'resubmit(,{:d})'.format(
|
||||||
|
port.ofport,
|
||||||
|
ovsfw_consts.REG_PORT,
|
||||||
|
port.vlan_tag,
|
||||||
|
ovsfw_consts.REG_NET,
|
||||||
|
ovs_consts.BASE_INGRESS_TABLE)}
|
||||||
|
expected_calls.append(mock.call(**call_args2))
|
||||||
|
|
||||||
call_args3 = {
|
call_args3 = {
|
||||||
'table': ovs_consts.TRANSIENT_TABLE,
|
'table': ovs_consts.TRANSIENT_TABLE,
|
||||||
|
@ -646,9 +669,20 @@ class TestOVSFirewallDriver(base.BaseTestCase):
|
||||||
port.vlan_tag,
|
port.vlan_tag,
|
||||||
ovsfw_consts.REG_NET,
|
ovsfw_consts.REG_NET,
|
||||||
ovs_consts.BASE_INGRESS_TABLE)}
|
ovs_consts.BASE_INGRESS_TABLE)}
|
||||||
ingress_flow_call2 = mock.call(**call_args3)
|
expected_calls.append(mock.call(**call_args3))
|
||||||
self.mock_bridge.br.add_flow.assert_has_calls(
|
self.mock_bridge.br.add_flow.assert_has_calls(expected_calls)
|
||||||
[egress_flow_call, ingress_flow_call1, ingress_flow_call2])
|
|
||||||
|
def test_initialize_port_flows_dvr_conntrack_direct_vxlan(self):
|
||||||
|
self._test_initialize_port_flows_dvr_conntrack_direct(
|
||||||
|
network_type='vxlan')
|
||||||
|
|
||||||
|
def test_initialize_port_flows_dvr_conntrack_direct_vlan(self):
|
||||||
|
self._test_initialize_port_flows_dvr_conntrack_direct(
|
||||||
|
network_type='vlan')
|
||||||
|
|
||||||
|
def test_initialize_port_flows_dvr_conntrack_direct_flat(self):
|
||||||
|
self._test_initialize_port_flows_dvr_conntrack_direct(
|
||||||
|
network_type='flat')
|
||||||
|
|
||||||
def test_initialize_port_flows_vlan_dvr_conntrack_direct_vlan(self):
|
def test_initialize_port_flows_vlan_dvr_conntrack_direct_vlan(self):
|
||||||
port_dict = {
|
port_dict = {
|
||||||
|
|
|
@ -286,6 +286,48 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
|
||||||
]
|
]
|
||||||
self.assertEqual(expected, self.mock.mock_calls)
|
self.assertEqual(expected, self.mock.mock_calls)
|
||||||
|
|
||||||
|
def test_install_dvr_to_src_mac_flat(self):
|
||||||
|
network_type = 'flat'
|
||||||
|
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=None,
|
||||||
|
gateway_mac=gateway_mac,
|
||||||
|
dst_mac=dst_mac,
|
||||||
|
dst_port=dst_port)
|
||||||
|
(dp, ofp, ofpp) = self._get_dp()
|
||||||
|
expected = [
|
||||||
|
call._send_msg(ofpp.OFPFlowMod(dp,
|
||||||
|
cookie=self.stamp,
|
||||||
|
instructions=[
|
||||||
|
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
|
||||||
|
ofpp.OFPActionSetField(eth_src=gateway_mac),
|
||||||
|
]),
|
||||||
|
ofpp.OFPInstructionGotoTable(table_id=60),
|
||||||
|
],
|
||||||
|
match=ofpp.OFPMatch(
|
||||||
|
eth_dst=dst_mac,
|
||||||
|
vlan_vid=ofp.OFPVID_NONE),
|
||||||
|
priority=20,
|
||||||
|
table_id=2),
|
||||||
|
active_bundle=None),
|
||||||
|
call._send_msg(ofpp.OFPFlowMod(dp,
|
||||||
|
cookie=self.stamp,
|
||||||
|
instructions=[
|
||||||
|
ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
|
||||||
|
ofpp.OFPActionOutput(dst_port, 0),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
match=ofpp.OFPMatch(
|
||||||
|
eth_dst=dst_mac,
|
||||||
|
vlan_vid=ofp.OFPVID_NONE),
|
||||||
|
priority=20,
|
||||||
|
table_id=60),
|
||||||
|
active_bundle=None),
|
||||||
|
]
|
||||||
|
self.assertEqual(expected, self.mock.mock_calls)
|
||||||
|
|
||||||
def test_delete_dvr_to_src_mac_vlan(self):
|
def test_delete_dvr_to_src_mac_vlan(self):
|
||||||
network_type = 'vlan'
|
network_type = 'vlan'
|
||||||
vlan_tag = 1111
|
vlan_tag = 1111
|
||||||
|
@ -312,10 +354,36 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
|
||||||
]
|
]
|
||||||
self.assertEqual(expected, self.mock.mock_calls)
|
self.assertEqual(expected, self.mock.mock_calls)
|
||||||
|
|
||||||
def test_add_dvr_mac_vlan(self):
|
def test_delete_dvr_to_src_mac_flat(self):
|
||||||
|
network_type = 'flat'
|
||||||
|
vlan_tag = None
|
||||||
|
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)
|
||||||
|
(dp, ofp, ofpp) = self._get_dp()
|
||||||
|
expected = [
|
||||||
|
call.uninstall_flows(
|
||||||
|
strict=True,
|
||||||
|
priority=20,
|
||||||
|
table_id=2,
|
||||||
|
match=ofpp.OFPMatch(
|
||||||
|
eth_dst=dst_mac,
|
||||||
|
vlan_vid=ofp.OFPVID_NONE)),
|
||||||
|
call.uninstall_flows(
|
||||||
|
strict=True,
|
||||||
|
priority=20,
|
||||||
|
table_id=60,
|
||||||
|
match=ofpp.OFPMatch(
|
||||||
|
eth_dst=dst_mac,
|
||||||
|
vlan_vid=ofp.OFPVID_NONE)),
|
||||||
|
]
|
||||||
|
self.assertEqual(expected, self.mock.mock_calls)
|
||||||
|
|
||||||
|
def test_add_dvr_mac_physical(self):
|
||||||
mac = '00:02:b3:13:fe:3d'
|
mac = '00:02:b3:13:fe:3d'
|
||||||
port = 8888
|
port = 8888
|
||||||
self.br.add_dvr_mac_vlan(mac=mac, port=port)
|
self.br.add_dvr_mac_physical(mac=mac, port=port)
|
||||||
(dp, ofp, ofpp) = self._get_dp()
|
(dp, ofp, ofpp) = self._get_dp()
|
||||||
expected = [
|
expected = [
|
||||||
call._send_msg(ofpp.OFPFlowMod(dp,
|
call._send_msg(ofpp.OFPFlowMod(dp,
|
||||||
|
@ -488,12 +556,15 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
|
||||||
self.assertEqual(expected, self.mock.mock_calls)
|
self.assertEqual(expected, self.mock.mock_calls)
|
||||||
|
|
||||||
def _test_delete_dvr_dst_mac_for_arp(self, network_type):
|
def _test_delete_dvr_dst_mac_for_arp(self, network_type):
|
||||||
if network_type == p_const.TYPE_VLAN:
|
if network_type in (p_const.TYPE_VLAN, p_const.TYPE_FLAT):
|
||||||
table_id = constants.DVR_TO_SRC_MAC_VLAN
|
table_id = constants.DVR_TO_SRC_MAC_PHYSICAL
|
||||||
else:
|
else:
|
||||||
table_id = constants.DVR_TO_SRC_MAC
|
table_id = constants.DVR_TO_SRC_MAC
|
||||||
|
|
||||||
vlan_tag = 1111
|
if network_type == p_const.TYPE_FLAT:
|
||||||
|
vlan_tag = None
|
||||||
|
else:
|
||||||
|
vlan_tag = 1111
|
||||||
gateway_mac = '00:02:b3:13:fe:3e'
|
gateway_mac = '00:02:b3:13:fe:3e'
|
||||||
dvr_mac = '00:02:b3:13:fe:3f'
|
dvr_mac = '00:02:b3:13:fe:3f'
|
||||||
rtr_port = 8888
|
rtr_port = 8888
|
||||||
|
@ -503,15 +574,26 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
|
||||||
dvr_mac=dvr_mac,
|
dvr_mac=dvr_mac,
|
||||||
rtr_port=rtr_port)
|
rtr_port=rtr_port)
|
||||||
(dp, ofp, ofpp) = self._get_dp()
|
(dp, ofp, ofpp) = self._get_dp()
|
||||||
expected = [
|
if network_type == p_const.TYPE_FLAT:
|
||||||
call.uninstall_flows(
|
expected = [
|
||||||
strict=True,
|
call.uninstall_flows(
|
||||||
priority=5,
|
strict=True,
|
||||||
table_id=table_id,
|
priority=5,
|
||||||
match=ofpp.OFPMatch(
|
table_id=table_id,
|
||||||
eth_dst=dvr_mac,
|
match=ofpp.OFPMatch(
|
||||||
vlan_vid=vlan_tag | ofp.OFPVID_PRESENT)),
|
eth_dst=dvr_mac,
|
||||||
]
|
vlan_vid=ofp.OFPVID_NONE)),
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
expected = [
|
||||||
|
call.uninstall_flows(
|
||||||
|
strict=True,
|
||||||
|
priority=5,
|
||||||
|
table_id=table_id,
|
||||||
|
match=ofpp.OFPMatch(
|
||||||
|
eth_dst=dvr_mac,
|
||||||
|
vlan_vid=vlan_tag | ofp.OFPVID_PRESENT)),
|
||||||
|
]
|
||||||
self.assertEqual(expected, self.mock.mock_calls)
|
self.assertEqual(expected, self.mock.mock_calls)
|
||||||
|
|
||||||
def test_delete_dvr_dst_mac_for_arp_vlan(self):
|
def test_delete_dvr_dst_mac_for_arp_vlan(self):
|
||||||
|
@ -520,6 +602,9 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
|
||||||
def test_delete_dvr_dst_mac_for_arp_tunnel(self):
|
def test_delete_dvr_dst_mac_for_arp_tunnel(self):
|
||||||
self._test_delete_dvr_dst_mac_for_arp(network_type='vxlan')
|
self._test_delete_dvr_dst_mac_for_arp(network_type='vxlan')
|
||||||
|
|
||||||
|
def test_delete_dvr_dst_mac_for_flat(self):
|
||||||
|
self._test_delete_dvr_dst_mac_for_arp(network_type='flat')
|
||||||
|
|
||||||
def test_install_dscp_marking_rule(self):
|
def test_install_dscp_marking_rule(self):
|
||||||
test_port = 8888
|
test_port = 8888
|
||||||
test_mark = 38
|
test_mark = 38
|
||||||
|
|
|
@ -27,7 +27,7 @@ call = mock.call # short hand
|
||||||
|
|
||||||
class OVSPhysicalBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase,
|
class OVSPhysicalBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase,
|
||||||
ovs_bridge_test_base.OVSDVRProcessTestMixin):
|
ovs_bridge_test_base.OVSDVRProcessTestMixin):
|
||||||
dvr_process_table_id = ovs_const.DVR_PROCESS_VLAN
|
dvr_process_table_id = ovs_const.DVR_PROCESS_PHYSICAL
|
||||||
dvr_process_next_table_id = ovs_const.LOCAL_VLAN_TRANSLATION
|
dvr_process_next_table_id = ovs_const.LOCAL_VLAN_TRANSLATION
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -125,10 +125,10 @@ class OVSPhysicalBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase,
|
||||||
]
|
]
|
||||||
self.assertEqual(expected, self.mock.mock_calls)
|
self.assertEqual(expected, self.mock.mock_calls)
|
||||||
|
|
||||||
def test_add_dvr_mac_vlan(self):
|
def test_add_dvr_mac_physical(self):
|
||||||
mac = '00:02:b3:13:fe:3d'
|
mac = '00:02:b3:13:fe:3d'
|
||||||
port = 8888
|
port = 8888
|
||||||
self.br.add_dvr_mac_vlan(mac=mac, port=port)
|
self.br.add_dvr_mac_physical(mac=mac, port=port)
|
||||||
(dp, ofp, ofpp) = self._get_dp()
|
(dp, ofp, ofpp) = self._get_dp()
|
||||||
expected = [
|
expected = [
|
||||||
call._send_msg(ofpp.OFPFlowMod(dp,
|
call._send_msg(ofpp.OFPFlowMod(dp,
|
||||||
|
|
|
@ -3078,8 +3078,8 @@ class TestOvsDvrNeutronAgent(object):
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
def _test_port_bound_for_dvr_on_vlan_network(
|
def _test_port_bound_for_dvr_on_physical_network(
|
||||||
self, device_owner, ip_version=n_const.IP_VERSION_4):
|
self, device_owner, network_type, ip_version=n_const.IP_VERSION_4):
|
||||||
self._setup_for_dvr_test()
|
self._setup_for_dvr_test()
|
||||||
if ip_version == n_const.IP_VERSION_4:
|
if ip_version == n_const.IP_VERSION_4:
|
||||||
gateway_ip = '1.1.1.10'
|
gateway_ip = '1.1.1.10'
|
||||||
|
@ -3093,7 +3093,8 @@ class TestOvsDvrNeutronAgent(object):
|
||||||
self._compute_port.vif_mac = '77:88:99:00:11:22'
|
self._compute_port.vif_mac = '77:88:99:00:11:22'
|
||||||
physical_network = self._physical_network
|
physical_network = self._physical_network
|
||||||
segmentation_id = self._segmentation_id
|
segmentation_id = self._segmentation_id
|
||||||
network_type = n_const.TYPE_VLAN
|
if network_type == n_const.TYPE_FLAT:
|
||||||
|
segmentation_id = None
|
||||||
int_br = mock.create_autospec(self.agent.int_br)
|
int_br = mock.create_autospec(self.agent.int_br)
|
||||||
tun_br = mock.create_autospec(self.agent.tun_br)
|
tun_br = mock.create_autospec(self.agent.tun_br)
|
||||||
phys_br = mock.create_autospec(self.br_phys_cls('br-phys'))
|
phys_br = mock.create_autospec(self.br_phys_cls('br-phys'))
|
||||||
|
@ -3256,10 +3257,19 @@ class TestOvsDvrNeutronAgent(object):
|
||||||
phys_br.assert_not_called()
|
phys_br.assert_not_called()
|
||||||
|
|
||||||
def test_port_bound_for_dvr_with_compute_ports(self):
|
def test_port_bound_for_dvr_with_compute_ports(self):
|
||||||
self._test_port_bound_for_dvr_on_vlan_network(
|
self._test_port_bound_for_dvr_on_physical_network(
|
||||||
device_owner=DEVICE_OWNER_COMPUTE)
|
|
||||||
self._test_port_bound_for_dvr_on_vlan_network(
|
|
||||||
device_owner=DEVICE_OWNER_COMPUTE,
|
device_owner=DEVICE_OWNER_COMPUTE,
|
||||||
|
network_type=n_const.TYPE_VLAN)
|
||||||
|
self._test_port_bound_for_dvr_on_physical_network(
|
||||||
|
device_owner=DEVICE_OWNER_COMPUTE,
|
||||||
|
network_type=n_const.TYPE_VLAN,
|
||||||
|
ip_version=n_const.IP_VERSION_6)
|
||||||
|
self._test_port_bound_for_dvr_on_physical_network(
|
||||||
|
device_owner=DEVICE_OWNER_COMPUTE,
|
||||||
|
network_type=n_const.TYPE_FLAT)
|
||||||
|
self._test_port_bound_for_dvr_on_physical_network(
|
||||||
|
device_owner=DEVICE_OWNER_COMPUTE,
|
||||||
|
network_type=n_const.TYPE_FLAT,
|
||||||
ip_version=n_const.IP_VERSION_6)
|
ip_version=n_const.IP_VERSION_6)
|
||||||
self._test_port_bound_for_dvr_on_vxlan_network(
|
self._test_port_bound_for_dvr_on_vxlan_network(
|
||||||
device_owner=DEVICE_OWNER_COMPUTE)
|
device_owner=DEVICE_OWNER_COMPUTE)
|
||||||
|
@ -3268,10 +3278,19 @@ class TestOvsDvrNeutronAgent(object):
|
||||||
ip_version=n_const.IP_VERSION_6)
|
ip_version=n_const.IP_VERSION_6)
|
||||||
|
|
||||||
def test_port_bound_for_dvr_with_dhcp_ports(self):
|
def test_port_bound_for_dvr_with_dhcp_ports(self):
|
||||||
self._test_port_bound_for_dvr_on_vlan_network(
|
self._test_port_bound_for_dvr_on_physical_network(
|
||||||
device_owner=n_const.DEVICE_OWNER_DHCP)
|
|
||||||
self._test_port_bound_for_dvr_on_vlan_network(
|
|
||||||
device_owner=n_const.DEVICE_OWNER_DHCP,
|
device_owner=n_const.DEVICE_OWNER_DHCP,
|
||||||
|
network_type=n_const.TYPE_VLAN)
|
||||||
|
self._test_port_bound_for_dvr_on_physical_network(
|
||||||
|
device_owner=n_const.DEVICE_OWNER_DHCP,
|
||||||
|
network_type=n_const.TYPE_VLAN,
|
||||||
|
ip_version=n_const.IP_VERSION_6)
|
||||||
|
self._test_port_bound_for_dvr_on_physical_network(
|
||||||
|
device_owner=n_const.DEVICE_OWNER_DHCP,
|
||||||
|
network_type=n_const.TYPE_FLAT)
|
||||||
|
self._test_port_bound_for_dvr_on_physical_network(
|
||||||
|
device_owner=n_const.DEVICE_OWNER_DHCP,
|
||||||
|
network_type=n_const.TYPE_FLAT,
|
||||||
ip_version=n_const.IP_VERSION_6)
|
ip_version=n_const.IP_VERSION_6)
|
||||||
self._test_port_bound_for_dvr_on_vxlan_network(
|
self._test_port_bound_for_dvr_on_vxlan_network(
|
||||||
device_owner=n_const.DEVICE_OWNER_DHCP)
|
device_owner=n_const.DEVICE_OWNER_DHCP)
|
||||||
|
@ -3737,8 +3756,9 @@ class TestOvsDvrNeutronAgent(object):
|
||||||
mock.call.setup_canary_table(),
|
mock.call.setup_canary_table(),
|
||||||
mock.call.install_drop(table_id=constants.DVR_TO_SRC_MAC,
|
mock.call.install_drop(table_id=constants.DVR_TO_SRC_MAC,
|
||||||
priority=1),
|
priority=1),
|
||||||
mock.call.install_drop(table_id=constants.DVR_TO_SRC_MAC_VLAN,
|
mock.call.install_drop(
|
||||||
priority=1),
|
table_id=constants.DVR_TO_SRC_MAC_PHYSICAL,
|
||||||
|
priority=1),
|
||||||
mock.call.install_drop(table_id=constants.LOCAL_SWITCHING,
|
mock.call.install_drop(table_id=constants.LOCAL_SWITCHING,
|
||||||
priority=2,
|
priority=2,
|
||||||
in_port=ioport),
|
in_port=ioport),
|
||||||
|
@ -3829,7 +3849,7 @@ class TestOvsDvrNeutronAgent(object):
|
||||||
dvr_macs=[{'host': newhost,
|
dvr_macs=[{'host': newhost,
|
||||||
'mac_address': newmac}])
|
'mac_address': newmac}])
|
||||||
expected_on_int_br = [
|
expected_on_int_br = [
|
||||||
mock.call.add_dvr_mac_vlan(
|
mock.call.add_dvr_mac_physical(
|
||||||
mac=newmac,
|
mac=newmac,
|
||||||
port=self.agent.int_ofports[physical_network]),
|
port=self.agent.int_ofports[physical_network]),
|
||||||
mock.call.add_dvr_mac_tun(
|
mock.call.add_dvr_mac_tun(
|
||||||
|
@ -3842,7 +3862,7 @@ class TestOvsDvrNeutronAgent(object):
|
||||||
port=self.agent.patch_int_ofport),
|
port=self.agent.patch_int_ofport),
|
||||||
]
|
]
|
||||||
expected_on_phys_br = [
|
expected_on_phys_br = [
|
||||||
mock.call.add_dvr_mac_vlan(
|
mock.call.add_dvr_mac_physical(
|
||||||
mac=newmac,
|
mac=newmac,
|
||||||
port=self.agent.phys_ofports[physical_network]),
|
port=self.agent.phys_ofports[physical_network]),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
``DVR`` routers now support ``flat`` networks.
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fixed bug `1876092 <https://bugs.launchpad.net/neutron/+bug/1876092>`_
|
||||||
|
which caused DUP ICMP replies on the ``flat`` networks used with ``DVR``
|
||||||
|
routers.
|
Loading…
Reference in New Issue