Merge "Use patch ports to interconnect integration/physical bridges"
This commit is contained in:
commit
da6b1280a7
@ -83,6 +83,11 @@
|
|||||||
# bridge_mappings =
|
# bridge_mappings =
|
||||||
# Example: bridge_mappings = physnet1:br-eth1
|
# Example: bridge_mappings = physnet1:br-eth1
|
||||||
|
|
||||||
|
# (BoolOpt) Use veths instead of patch ports to interconnect the integration
|
||||||
|
# bridge to physical networks. Support kernel without ovs patch port support
|
||||||
|
# so long as it is set to True.
|
||||||
|
# use_veth_interconnection = False
|
||||||
|
|
||||||
[agent]
|
[agent]
|
||||||
# Agent's polling interval in seconds
|
# Agent's polling interval in seconds
|
||||||
# polling_interval = 2
|
# polling_interval = 2
|
||||||
@ -117,6 +122,7 @@
|
|||||||
# (IntOpt) This is the MTU size of veth interfaces.
|
# (IntOpt) This is the MTU size of veth interfaces.
|
||||||
# Do not change unless you have a good reason to.
|
# Do not change unless you have a good reason to.
|
||||||
# The default MTU size of veth interfaces is 1500.
|
# The default MTU size of veth interfaces is 1500.
|
||||||
|
# This option has no effect if use_veth_interconnection is False
|
||||||
# veth_mtu =
|
# veth_mtu =
|
||||||
# Example: veth_mtu = 1504
|
# Example: veth_mtu = 1504
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ from oslo.config import cfg
|
|||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
cfg.CONF.import_group('AGENT', 'neutron.plugins.openvswitch.common.config')
|
cfg.CONF.import_group('AGENT', 'neutron.plugins.openvswitch.common.config')
|
||||||
|
cfg.CONF.import_group('OVS', 'neutron.plugins.openvswitch.common.config')
|
||||||
|
|
||||||
|
|
||||||
class BoolOptCallback(cfg.BoolOpt):
|
class BoolOptCallback(cfg.BoolOpt):
|
||||||
@ -69,6 +70,8 @@ def enable_tests_from_config():
|
|||||||
cfg.CONF.set_override('ovs_vxlan', True)
|
cfg.CONF.set_override('ovs_vxlan', True)
|
||||||
if cfg.CONF.AGENT.tunnel_types:
|
if cfg.CONF.AGENT.tunnel_types:
|
||||||
cfg.CONF.set_override('ovs_patch', True)
|
cfg.CONF.set_override('ovs_patch', True)
|
||||||
|
if not cfg.CONF.OVS.use_veth_interconnection:
|
||||||
|
cfg.CONF.set_override('ovs_patch', True)
|
||||||
|
|
||||||
|
|
||||||
def all_tests_passed():
|
def all_tests_passed():
|
||||||
|
@ -854,8 +854,8 @@ class OFANeutronAgent(n_rpc.RpcCallback,
|
|||||||
|
|
||||||
def _phys_br_patch_physical_bridge_with_integration_bridge(
|
def _phys_br_patch_physical_bridge_with_integration_bridge(
|
||||||
self, br, physical_network, bridge, ip_wrapper):
|
self, br, physical_network, bridge, ip_wrapper):
|
||||||
int_veth_name = constants.VETH_INTEGRATION_PREFIX + bridge
|
int_veth_name = constants.PEER_INTEGRATION_PREFIX + bridge
|
||||||
phys_veth_name = constants.VETH_PHYSICAL_PREFIX + bridge
|
phys_veth_name = constants.PEER_PHYSICAL_PREFIX + bridge
|
||||||
self._phys_br_prepare_create_veth(br, int_veth_name, phys_veth_name)
|
self._phys_br_prepare_create_veth(br, int_veth_name, phys_veth_name)
|
||||||
int_veth, phys_veth = self._phys_br_create_veth(br, int_veth_name,
|
int_veth, phys_veth = self._phys_br_create_veth(br, int_veth_name,
|
||||||
phys_veth_name,
|
phys_veth_name,
|
||||||
|
@ -110,9 +110,9 @@ class OVSNeutronAgent(n_rpc.RpcCallback,
|
|||||||
tunnels on the tunnel bridge.
|
tunnels on the tunnel bridge.
|
||||||
|
|
||||||
For each virtual network realized as a VLAN or flat network, a
|
For each virtual network realized as a VLAN or flat network, a
|
||||||
veth is used to connect the local VLAN on the integration bridge
|
veth or a pair of patch ports is used to connect the local VLAN on
|
||||||
with the physical network bridge, with flow rules adding,
|
the integration bridge with the physical network bridge, with flow
|
||||||
modifying, or stripping VLAN tags as necessary.
|
rules adding, modifying, or stripping VLAN tags as necessary.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# history
|
# history
|
||||||
@ -127,7 +127,8 @@ class OVSNeutronAgent(n_rpc.RpcCallback,
|
|||||||
minimize_polling=False,
|
minimize_polling=False,
|
||||||
ovsdb_monitor_respawn_interval=(
|
ovsdb_monitor_respawn_interval=(
|
||||||
constants.DEFAULT_OVSDBMON_RESPAWN),
|
constants.DEFAULT_OVSDBMON_RESPAWN),
|
||||||
arp_responder=False):
|
arp_responder=False,
|
||||||
|
use_veth_interconnection=False):
|
||||||
'''Constructor.
|
'''Constructor.
|
||||||
|
|
||||||
:param integ_br: name of the integration bridge.
|
:param integ_br: name of the integration bridge.
|
||||||
@ -148,8 +149,11 @@ class OVSNeutronAgent(n_rpc.RpcCallback,
|
|||||||
the ovsdb monitor.
|
the ovsdb monitor.
|
||||||
:param arp_responder: Optional, enable local ARP responder if it is
|
:param arp_responder: Optional, enable local ARP responder if it is
|
||||||
supported.
|
supported.
|
||||||
|
:param use_veth_interconnection: use veths instead of patch ports to
|
||||||
|
interconnect the integration bridge to physical bridges.
|
||||||
'''
|
'''
|
||||||
super(OVSNeutronAgent, self).__init__()
|
super(OVSNeutronAgent, self).__init__()
|
||||||
|
self.use_veth_interconnection = use_veth_interconnection
|
||||||
self.veth_mtu = veth_mtu
|
self.veth_mtu = veth_mtu
|
||||||
self.root_helper = root_helper
|
self.root_helper = root_helper
|
||||||
self.available_local_vlans = set(moves.xrange(q_const.MIN_VLAN_TAG,
|
self.available_local_vlans = set(moves.xrange(q_const.MIN_VLAN_TAG,
|
||||||
@ -858,10 +862,11 @@ class OVSNeutronAgent(n_rpc.RpcCallback,
|
|||||||
priority=0,
|
priority=0,
|
||||||
actions="drop")
|
actions="drop")
|
||||||
|
|
||||||
def get_veth_name(self, prefix, name):
|
def get_peer_name(self, prefix, name):
|
||||||
"""Construct a veth name based on the prefix and name that does not
|
"""Construct a peer name based on the prefix and name.
|
||||||
exceed the maximum length allowed for a linux device. Longer names
|
|
||||||
are hashed to help ensure uniqueness.
|
The peer name can not exceed the maximum length allowed for a linux
|
||||||
|
device. Longer names are hashed to help ensure uniqueness.
|
||||||
"""
|
"""
|
||||||
if len(prefix + name) <= q_const.DEVICE_NAME_MAX_LEN:
|
if len(prefix + name) <= q_const.DEVICE_NAME_MAX_LEN:
|
||||||
return prefix + name
|
return prefix + name
|
||||||
@ -910,40 +915,55 @@ class OVSNeutronAgent(n_rpc.RpcCallback,
|
|||||||
br.add_flow(priority=1, actions="normal")
|
br.add_flow(priority=1, actions="normal")
|
||||||
self.phys_brs[physical_network] = br
|
self.phys_brs[physical_network] = br
|
||||||
|
|
||||||
# create veth to patch physical bridge with integration bridge
|
# interconnect physical and integration bridges using veth/patchs
|
||||||
int_veth_name = self.get_veth_name(
|
int_if_name = self.get_peer_name(constants.PEER_INTEGRATION_PREFIX,
|
||||||
constants.VETH_INTEGRATION_PREFIX, bridge)
|
bridge)
|
||||||
self.int_br.delete_port(int_veth_name)
|
phys_if_name = self.get_peer_name(constants.PEER_PHYSICAL_PREFIX,
|
||||||
phys_veth_name = self.get_veth_name(
|
bridge)
|
||||||
constants.VETH_PHYSICAL_PREFIX, bridge)
|
self.int_br.delete_port(int_if_name)
|
||||||
br.delete_port(phys_veth_name)
|
br.delete_port(phys_if_name)
|
||||||
if ip_lib.device_exists(int_veth_name, self.root_helper):
|
if self.use_veth_interconnection:
|
||||||
ip_lib.IPDevice(int_veth_name, self.root_helper).link.delete()
|
if ip_lib.device_exists(int_if_name, self.root_helper):
|
||||||
|
ip_lib.IPDevice(int_if_name,
|
||||||
|
self.root_helper).link.delete()
|
||||||
# Give udev a chance to process its rules here, to avoid
|
# Give udev a chance to process its rules here, to avoid
|
||||||
# race conditions between commands launched by udev rules
|
# race conditions between commands launched by udev rules
|
||||||
# and the subsequent call to ip_wrapper.add_veth
|
# and the subsequent call to ip_wrapper.add_veth
|
||||||
utils.execute(['/sbin/udevadm', 'settle', '--timeout=10'])
|
utils.execute(['/sbin/udevadm', 'settle', '--timeout=10'])
|
||||||
int_veth, phys_veth = ip_wrapper.add_veth(int_veth_name,
|
int_veth, phys_veth = ip_wrapper.add_veth(int_if_name,
|
||||||
phys_veth_name)
|
phys_if_name)
|
||||||
self.int_ofports[physical_network] = self.int_br.add_port(int_veth)
|
int_ofport = self.int_br.add_port(int_veth)
|
||||||
self.phys_ofports[physical_network] = br.add_port(phys_veth)
|
phys_ofport = br.add_port(phys_veth)
|
||||||
|
else:
|
||||||
|
# Create patch ports without associating them in order to block
|
||||||
|
# untranslated traffic before association
|
||||||
|
int_ofport = self.int_br.add_patch_port(
|
||||||
|
int_if_name, constants.NONEXISTENT_PEER)
|
||||||
|
phys_ofport = br.add_patch_port(
|
||||||
|
phys_if_name, constants.NONEXISTENT_PEER)
|
||||||
|
|
||||||
# block all untranslated traffic over veth between bridges
|
self.int_ofports[physical_network] = int_ofport
|
||||||
self.int_br.add_flow(priority=2,
|
self.phys_ofports[physical_network] = phys_ofport
|
||||||
in_port=self.int_ofports[physical_network],
|
|
||||||
actions="drop")
|
|
||||||
br.add_flow(priority=2,
|
|
||||||
in_port=self.phys_ofports[physical_network],
|
|
||||||
actions="drop")
|
|
||||||
|
|
||||||
|
# block all untranslated traffic between bridges
|
||||||
|
self.int_br.add_flow(priority=2, in_port=int_ofport,
|
||||||
|
actions="drop")
|
||||||
|
br.add_flow(priority=2, in_port=phys_ofport, actions="drop")
|
||||||
|
|
||||||
|
if self.use_veth_interconnection:
|
||||||
# enable veth to pass traffic
|
# enable veth to pass traffic
|
||||||
int_veth.link.set_up()
|
int_veth.link.set_up()
|
||||||
phys_veth.link.set_up()
|
phys_veth.link.set_up()
|
||||||
|
|
||||||
if self.veth_mtu:
|
if self.veth_mtu:
|
||||||
# set up mtu size for veth interfaces
|
# set up mtu size for veth interfaces
|
||||||
int_veth.link.set_mtu(self.veth_mtu)
|
int_veth.link.set_mtu(self.veth_mtu)
|
||||||
phys_veth.link.set_mtu(self.veth_mtu)
|
phys_veth.link.set_mtu(self.veth_mtu)
|
||||||
|
else:
|
||||||
|
# associate patch ports to pass traffic
|
||||||
|
self.int_br.set_db_attribute('Interface', int_if_name,
|
||||||
|
'options:peer', phys_if_name)
|
||||||
|
br.set_db_attribute('Interface', phys_if_name,
|
||||||
|
'options:peer', int_if_name)
|
||||||
|
|
||||||
def scan_ports(self, registered_ports, updated_ports=None):
|
def scan_ports(self, registered_ports, updated_ports=None):
|
||||||
cur_ports = self.int_br.get_vif_port_set()
|
cur_ports = self.int_br.get_vif_port_set()
|
||||||
@ -1475,6 +1495,7 @@ def create_agent_config_map(config):
|
|||||||
veth_mtu=config.AGENT.veth_mtu,
|
veth_mtu=config.AGENT.veth_mtu,
|
||||||
l2_population=config.AGENT.l2_population,
|
l2_population=config.AGENT.l2_population,
|
||||||
arp_responder=config.AGENT.arp_responder,
|
arp_responder=config.AGENT.arp_responder,
|
||||||
|
use_veth_interconnection=config.OVS.use_veth_interconnection,
|
||||||
)
|
)
|
||||||
|
|
||||||
# If enable_tunneling is TRUE, set tunnel_type to default to GRE
|
# If enable_tunneling is TRUE, set tunnel_type to default to GRE
|
||||||
|
@ -54,6 +54,9 @@ ovs_opts = [
|
|||||||
cfg.StrOpt('tunnel_type', default='',
|
cfg.StrOpt('tunnel_type', default='',
|
||||||
help=_("The type of tunnels to use when utilizing tunnels, "
|
help=_("The type of tunnels to use when utilizing tunnels, "
|
||||||
"either 'gre' or 'vxlan'")),
|
"either 'gre' or 'vxlan'")),
|
||||||
|
cfg.BoolOpt('use_veth_interconnection', default=False,
|
||||||
|
help=_("Use veths instead of patch ports to interconnect the "
|
||||||
|
"integration bridge to physical bridges")),
|
||||||
]
|
]
|
||||||
|
|
||||||
agent_opts = [
|
agent_opts = [
|
||||||
|
@ -25,10 +25,14 @@ TUNNEL = 'tunnel'
|
|||||||
# Values for network_type
|
# Values for network_type
|
||||||
VXLAN_UDP_PORT = 4789
|
VXLAN_UDP_PORT = 4789
|
||||||
|
|
||||||
# Name prefixes for veth device pair linking the integration bridge
|
# Name prefixes for veth device or patch port pair linking the integration
|
||||||
# with the physical bridge for a physical network
|
# bridge with the physical bridge for a physical network
|
||||||
VETH_INTEGRATION_PREFIX = 'int-'
|
PEER_INTEGRATION_PREFIX = 'int-'
|
||||||
VETH_PHYSICAL_PREFIX = 'phy-'
|
PEER_PHYSICAL_PREFIX = 'phy-'
|
||||||
|
|
||||||
|
# Nonexistent peer used to create patch ports without associating them, it
|
||||||
|
# allows to define flows before association
|
||||||
|
NONEXISTENT_PEER = 'nonexistent-peer'
|
||||||
|
|
||||||
# The different types of tunnels
|
# The different types of tunnels
|
||||||
TUNNEL_NETWORK_TYPES = [p_const.TYPE_GRE, p_const.TYPE_VXLAN]
|
TUNNEL_NETWORK_TYPES = [p_const.TYPE_GRE, p_const.TYPE_VXLAN]
|
||||||
|
@ -450,6 +450,59 @@ class TestOvsNeutronAgent(base.BaseTestCase):
|
|||||||
self.assertEqual(set(['123']), self.agent.updated_ports)
|
self.assertEqual(set(['123']), self.agent.updated_ports)
|
||||||
|
|
||||||
def test_setup_physical_bridges(self):
|
def test_setup_physical_bridges(self):
|
||||||
|
with contextlib.nested(
|
||||||
|
mock.patch.object(ip_lib, "device_exists"),
|
||||||
|
mock.patch.object(sys, "exit"),
|
||||||
|
mock.patch.object(utils, "execute"),
|
||||||
|
mock.patch.object(ovs_lib.OVSBridge, "remove_all_flows"),
|
||||||
|
mock.patch.object(ovs_lib.OVSBridge, "add_flow"),
|
||||||
|
mock.patch.object(ovs_lib.OVSBridge, "add_patch_port"),
|
||||||
|
mock.patch.object(ovs_lib.OVSBridge, "delete_port"),
|
||||||
|
mock.patch.object(ovs_lib.OVSBridge, "set_db_attribute"),
|
||||||
|
mock.patch.object(self.agent.int_br, "add_flow"),
|
||||||
|
mock.patch.object(self.agent.int_br, "add_patch_port"),
|
||||||
|
mock.patch.object(self.agent.int_br, "delete_port"),
|
||||||
|
mock.patch.object(self.agent.int_br, "set_db_attribute"),
|
||||||
|
) as (devex_fn, sysexit_fn, utilsexec_fn, remflows_fn, ovs_add_flow_fn,
|
||||||
|
ovs_addpatch_port_fn, ovs_delport_fn, ovs_set_attr_fn,
|
||||||
|
br_add_flow_fn, br_addpatch_port_fn, br_delport_fn,
|
||||||
|
br_set_attr_fn):
|
||||||
|
devex_fn.return_value = True
|
||||||
|
parent = mock.MagicMock()
|
||||||
|
parent.attach_mock(ovs_addpatch_port_fn, 'phy_add_patch_port')
|
||||||
|
parent.attach_mock(ovs_add_flow_fn, 'phy_add_flow')
|
||||||
|
parent.attach_mock(ovs_set_attr_fn, 'phy_set_attr')
|
||||||
|
parent.attach_mock(br_addpatch_port_fn, 'int_add_patch_port')
|
||||||
|
parent.attach_mock(br_add_flow_fn, 'int_add_flow')
|
||||||
|
parent.attach_mock(br_set_attr_fn, 'int_set_attr')
|
||||||
|
|
||||||
|
ovs_addpatch_port_fn.return_value = "phy_ofport"
|
||||||
|
br_addpatch_port_fn.return_value = "int_ofport"
|
||||||
|
self.agent.setup_physical_bridges({"physnet1": "br-eth"})
|
||||||
|
expected_calls = [
|
||||||
|
mock.call.phy_add_flow(priority=1, actions='normal'),
|
||||||
|
mock.call.int_add_patch_port('int-br-eth',
|
||||||
|
constants.NONEXISTENT_PEER),
|
||||||
|
mock.call.phy_add_patch_port('phy-br-eth',
|
||||||
|
constants.NONEXISTENT_PEER),
|
||||||
|
mock.call.int_add_flow(priority=2, in_port='int_ofport',
|
||||||
|
actions='drop'),
|
||||||
|
mock.call.phy_add_flow(priority=2, in_port='phy_ofport',
|
||||||
|
actions='drop'),
|
||||||
|
mock.call.int_set_attr('Interface', 'int-br-eth',
|
||||||
|
'options:peer', 'phy-br-eth'),
|
||||||
|
mock.call.phy_set_attr('Interface', 'phy-br-eth',
|
||||||
|
'options:peer', 'int-br-eth'),
|
||||||
|
|
||||||
|
]
|
||||||
|
parent.assert_has_calls(expected_calls)
|
||||||
|
self.assertEqual(self.agent.int_ofports["physnet1"],
|
||||||
|
"int_ofport")
|
||||||
|
self.assertEqual(self.agent.phys_ofports["physnet1"],
|
||||||
|
"phy_ofport")
|
||||||
|
|
||||||
|
def test_setup_physical_bridges_using_veth_interconnection(self):
|
||||||
|
self.agent.use_veth_interconnection = True
|
||||||
with contextlib.nested(
|
with contextlib.nested(
|
||||||
mock.patch.object(ip_lib, "device_exists"),
|
mock.patch.object(ip_lib, "device_exists"),
|
||||||
mock.patch.object(sys, "exit"),
|
mock.patch.object(sys, "exit"),
|
||||||
@ -489,15 +542,16 @@ class TestOvsNeutronAgent(base.BaseTestCase):
|
|||||||
self.assertEqual(self.agent.phys_ofports["physnet1"],
|
self.assertEqual(self.agent.phys_ofports["physnet1"],
|
||||||
"int_ofport")
|
"int_ofport")
|
||||||
|
|
||||||
def test_get_veth_name(self):
|
def test_get_peer_name(self):
|
||||||
bridge1 = "A_REALLY_LONG_BRIDGE_NAME1"
|
bridge1 = "A_REALLY_LONG_BRIDGE_NAME1"
|
||||||
bridge2 = "A_REALLY_LONG_BRIDGE_NAME2"
|
bridge2 = "A_REALLY_LONG_BRIDGE_NAME2"
|
||||||
self.assertEqual(len(self.agent.get_veth_name('int-', bridge1)),
|
self.agent.use_veth_interconnection = True
|
||||||
|
self.assertEqual(len(self.agent.get_peer_name('int-', bridge1)),
|
||||||
n_const.DEVICE_NAME_MAX_LEN)
|
n_const.DEVICE_NAME_MAX_LEN)
|
||||||
self.assertEqual(len(self.agent.get_veth_name('int-', bridge2)),
|
self.assertEqual(len(self.agent.get_peer_name('int-', bridge2)),
|
||||||
n_const.DEVICE_NAME_MAX_LEN)
|
n_const.DEVICE_NAME_MAX_LEN)
|
||||||
self.assertNotEqual(self.agent.get_veth_name('int-', bridge1),
|
self.assertNotEqual(self.agent.get_peer_name('int-', bridge1),
|
||||||
self.agent.get_veth_name('int-', bridge2))
|
self.agent.get_peer_name('int-', bridge2))
|
||||||
|
|
||||||
def test_port_unbound(self):
|
def test_port_unbound(self):
|
||||||
with mock.patch.object(self.agent, "reclaim_local_vlan") as reclvl_fn:
|
with mock.patch.object(self.agent, "reclaim_local_vlan") as reclvl_fn:
|
||||||
|
@ -63,6 +63,8 @@ class DummyVlanBinding:
|
|||||||
|
|
||||||
|
|
||||||
class TunnelTest(base.BaseTestCase):
|
class TunnelTest(base.BaseTestCase):
|
||||||
|
USE_VETH_INTERCONNECTION = False
|
||||||
|
VETH_MTU = None
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TunnelTest, self).setUp()
|
super(TunnelTest, self).setUp()
|
||||||
@ -85,8 +87,9 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
self.NET_MAPPING = {'net1': self.MAP_TUN_BRIDGE}
|
self.NET_MAPPING = {'net1': self.MAP_TUN_BRIDGE}
|
||||||
self.INT_OFPORT = 11111
|
self.INT_OFPORT = 11111
|
||||||
self.TUN_OFPORT = 22222
|
self.TUN_OFPORT = 22222
|
||||||
self.MAP_TUN_OFPORT = 33333
|
self.MAP_TUN_INT_OFPORT = 33333
|
||||||
self.VETH_MTU = None
|
self.MAP_TUN_PHY_OFPORT = 44444
|
||||||
|
|
||||||
self.inta = mock.Mock()
|
self.inta = mock.Mock()
|
||||||
self.intb = mock.Mock()
|
self.intb = mock.Mock()
|
||||||
|
|
||||||
@ -94,10 +97,50 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
self.TUN_BRIDGE: mock.Mock(),
|
self.TUN_BRIDGE: mock.Mock(),
|
||||||
self.MAP_TUN_BRIDGE: mock.Mock(),
|
self.MAP_TUN_BRIDGE: mock.Mock(),
|
||||||
}
|
}
|
||||||
|
self.ovs_int_ofports = {
|
||||||
|
'patch-tun': self.TUN_OFPORT,
|
||||||
|
'int-%s' % self.MAP_TUN_BRIDGE: self.MAP_TUN_INT_OFPORT
|
||||||
|
}
|
||||||
|
|
||||||
self.mock_bridge = mock.patch.object(ovs_lib, 'OVSBridge').start()
|
self.mock_bridge = mock.patch.object(ovs_lib, 'OVSBridge').start()
|
||||||
self.mock_bridge.side_effect = (lambda br_name, root_helper:
|
self.mock_bridge.side_effect = (lambda br_name, root_helper:
|
||||||
self.ovs_bridges[br_name])
|
self.ovs_bridges[br_name])
|
||||||
|
|
||||||
|
self.mock_int_bridge = self.ovs_bridges[self.INT_BRIDGE]
|
||||||
|
self.mock_int_bridge.add_port.return_value = self.MAP_TUN_INT_OFPORT
|
||||||
|
self.mock_int_bridge.add_patch_port.side_effect = (
|
||||||
|
lambda tap, peer: self.ovs_int_ofports[tap])
|
||||||
|
|
||||||
|
self.mock_map_tun_bridge = self.ovs_bridges[self.MAP_TUN_BRIDGE]
|
||||||
|
self.mock_map_tun_bridge.br_name = self.MAP_TUN_BRIDGE
|
||||||
|
self.mock_map_tun_bridge.add_port.return_value = (
|
||||||
|
self.MAP_TUN_PHY_OFPORT)
|
||||||
|
self.mock_map_tun_bridge.add_patch_port.return_value = (
|
||||||
|
self.MAP_TUN_PHY_OFPORT)
|
||||||
|
|
||||||
|
self.mock_tun_bridge = self.ovs_bridges[self.TUN_BRIDGE]
|
||||||
|
self.mock_tun_bridge.add_port.return_value = self.INT_OFPORT
|
||||||
|
self.mock_tun_bridge.add_patch_port.return_value = self.INT_OFPORT
|
||||||
|
|
||||||
|
self.device_exists = mock.patch.object(ip_lib, 'device_exists').start()
|
||||||
|
self.device_exists.return_value = True
|
||||||
|
|
||||||
|
self.ipdevice = mock.patch.object(ip_lib, 'IPDevice').start()
|
||||||
|
|
||||||
|
self.ipwrapper = mock.patch.object(ip_lib, 'IPWrapper').start()
|
||||||
|
add_veth = self.ipwrapper.return_value.add_veth
|
||||||
|
add_veth.return_value = [self.inta, self.intb]
|
||||||
|
|
||||||
|
self.get_bridges = mock.patch.object(ovs_lib, 'get_bridges').start()
|
||||||
|
self.get_bridges.return_value = [self.INT_BRIDGE,
|
||||||
|
self.TUN_BRIDGE,
|
||||||
|
self.MAP_TUN_BRIDGE]
|
||||||
|
|
||||||
|
self.execute = mock.patch('neutron.agent.linux.utils.execute').start()
|
||||||
|
|
||||||
|
self._define_expected_calls()
|
||||||
|
|
||||||
|
def _define_expected_calls(self):
|
||||||
self.mock_bridge_expected = [
|
self.mock_bridge_expected = [
|
||||||
mock.call(self.INT_BRIDGE, 'sudo'),
|
mock.call(self.INT_BRIDGE, 'sudo'),
|
||||||
mock.call(self.MAP_TUN_BRIDGE, 'sudo'),
|
mock.call(self.MAP_TUN_BRIDGE, 'sudo'),
|
||||||
@ -115,31 +158,36 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
actions='drop'),
|
actions='drop'),
|
||||||
]
|
]
|
||||||
|
|
||||||
self.mock_map_tun_bridge = self.ovs_bridges[self.MAP_TUN_BRIDGE]
|
|
||||||
self.mock_map_tun_bridge.br_name = self.MAP_TUN_BRIDGE
|
|
||||||
self.mock_map_tun_bridge.add_port.return_value = None
|
|
||||||
self.mock_map_tun_bridge_expected = [
|
self.mock_map_tun_bridge_expected = [
|
||||||
mock.call.remove_all_flows(),
|
mock.call.remove_all_flows(),
|
||||||
mock.call.add_flow(priority=1, actions='normal'),
|
mock.call.add_flow(priority=1, actions='normal'),
|
||||||
mock.call.delete_port('phy-%s' % self.MAP_TUN_BRIDGE),
|
mock.call.delete_port('phy-%s' % self.MAP_TUN_BRIDGE),
|
||||||
mock.call.add_port(self.intb),
|
mock.call.add_patch_port('phy-%s' % self.MAP_TUN_BRIDGE,
|
||||||
|
constants.NONEXISTENT_PEER),
|
||||||
]
|
]
|
||||||
self.mock_int_bridge.add_port.return_value = None
|
|
||||||
self.mock_int_bridge_expected += [
|
self.mock_int_bridge_expected += [
|
||||||
mock.call.delete_port('int-%s' % self.MAP_TUN_BRIDGE),
|
mock.call.delete_port('int-%s' % self.MAP_TUN_BRIDGE),
|
||||||
mock.call.add_port(self.inta)
|
mock.call.add_patch_port('int-%s' % self.MAP_TUN_BRIDGE,
|
||||||
|
constants.NONEXISTENT_PEER),
|
||||||
]
|
]
|
||||||
self.inta_expected = [mock.call.link.set_up()]
|
|
||||||
self.intb_expected = [mock.call.link.set_up()]
|
|
||||||
|
|
||||||
self.mock_int_bridge_expected += [
|
self.mock_int_bridge_expected += [
|
||||||
mock.call.add_flow(priority=2, in_port=None, actions='drop')
|
mock.call.add_flow(priority=2,
|
||||||
|
in_port=self.MAP_TUN_INT_OFPORT,
|
||||||
|
actions='drop'),
|
||||||
|
mock.call.set_db_attribute(
|
||||||
|
'Interface', 'int-%s' % self.MAP_TUN_BRIDGE,
|
||||||
|
'options:peer', 'phy-%s' % self.MAP_TUN_BRIDGE),
|
||||||
]
|
]
|
||||||
self.mock_map_tun_bridge_expected += [
|
self.mock_map_tun_bridge_expected += [
|
||||||
mock.call.add_flow(priority=2, in_port=None, actions='drop')
|
mock.call.add_flow(priority=2,
|
||||||
|
in_port=self.MAP_TUN_PHY_OFPORT,
|
||||||
|
actions='drop'),
|
||||||
|
mock.call.set_db_attribute(
|
||||||
|
'Interface', 'phy-%s' % self.MAP_TUN_BRIDGE,
|
||||||
|
'options:peer', 'int-%s' % self.MAP_TUN_BRIDGE),
|
||||||
]
|
]
|
||||||
|
|
||||||
self.mock_tun_bridge = self.ovs_bridges[self.TUN_BRIDGE]
|
|
||||||
self.mock_tun_bridge_expected = [
|
self.mock_tun_bridge_expected = [
|
||||||
mock.call.reset_bridge(),
|
mock.call.reset_bridge(),
|
||||||
mock.call.add_patch_port('patch-int', 'patch-tun'),
|
mock.call.add_patch_port('patch-int', 'patch-tun'),
|
||||||
@ -147,8 +195,6 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
self.mock_int_bridge_expected += [
|
self.mock_int_bridge_expected += [
|
||||||
mock.call.add_patch_port('patch-tun', 'patch-int')
|
mock.call.add_patch_port('patch-tun', 'patch-int')
|
||||||
]
|
]
|
||||||
self.mock_int_bridge.add_patch_port.return_value = self.TUN_OFPORT
|
|
||||||
self.mock_tun_bridge.add_patch_port.return_value = self.INT_OFPORT
|
|
||||||
|
|
||||||
self.mock_tun_bridge_expected += [
|
self.mock_tun_bridge_expected += [
|
||||||
mock.call.remove_all_flows(),
|
mock.call.remove_all_flows(),
|
||||||
@ -195,37 +241,31 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
actions="drop")
|
actions="drop")
|
||||||
]
|
]
|
||||||
|
|
||||||
self.device_exists = mock.patch.object(ip_lib, 'device_exists').start()
|
|
||||||
self.device_exists.return_value = True
|
|
||||||
self.device_exists_expected = [
|
self.device_exists_expected = [
|
||||||
mock.call(self.MAP_TUN_BRIDGE, 'sudo'),
|
mock.call(self.MAP_TUN_BRIDGE, 'sudo'),
|
||||||
mock.call('int-%s' % self.MAP_TUN_BRIDGE, 'sudo'),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
self.ipdevice = mock.patch.object(ip_lib, 'IPDevice').start()
|
self.ipdevice_expected = []
|
||||||
self.ipdevice_expected = [
|
self.ipwrapper_expected = [mock.call('sudo')]
|
||||||
mock.call('int-%s' % self.MAP_TUN_BRIDGE, 'sudo'),
|
|
||||||
mock.call().link.delete()
|
|
||||||
]
|
|
||||||
self.ipwrapper = mock.patch.object(ip_lib, 'IPWrapper').start()
|
|
||||||
add_veth = self.ipwrapper.return_value.add_veth
|
|
||||||
add_veth.return_value = [self.inta, self.intb]
|
|
||||||
self.ipwrapper_expected = [
|
|
||||||
mock.call('sudo'),
|
|
||||||
mock.call().add_veth('int-%s' % self.MAP_TUN_BRIDGE,
|
|
||||||
'phy-%s' % self.MAP_TUN_BRIDGE)
|
|
||||||
]
|
|
||||||
|
|
||||||
self.get_bridges = mock.patch.object(ovs_lib, 'get_bridges').start()
|
self.get_bridges_expected = [mock.call('sudo')]
|
||||||
self.get_bridges.return_value = [self.INT_BRIDGE,
|
|
||||||
self.TUN_BRIDGE,
|
self.inta_expected = []
|
||||||
self.MAP_TUN_BRIDGE]
|
self.intb_expected = []
|
||||||
self.get_bridges_expected = [
|
self.execute_expected = []
|
||||||
mock.call('sudo')
|
|
||||||
]
|
def _build_agent(self, **kwargs):
|
||||||
self.execute = mock.patch('neutron.agent.linux.utils.execute').start()
|
kwargs.setdefault('integ_br', self.INT_BRIDGE)
|
||||||
self.execute_expected = [mock.call(['/sbin/udevadm', 'settle',
|
kwargs.setdefault('tun_br', self.TUN_BRIDGE)
|
||||||
'--timeout=10'])]
|
kwargs.setdefault('local_ip', '10.0.0.1')
|
||||||
|
kwargs.setdefault('bridge_mappings', self.NET_MAPPING)
|
||||||
|
kwargs.setdefault('root_helper', 'sudo')
|
||||||
|
kwargs.setdefault('polling_interval', 2)
|
||||||
|
kwargs.setdefault('tunnel_types', ['gre'])
|
||||||
|
kwargs.setdefault('veth_mtu', self.VETH_MTU)
|
||||||
|
kwargs.setdefault('use_veth_interconnection',
|
||||||
|
self.USE_VETH_INTERCONNECTION)
|
||||||
|
return ovs_neutron_agent.OVSNeutronAgent(**kwargs)
|
||||||
|
|
||||||
def _verify_mock_call(self, mock_obj, expected):
|
def _verify_mock_call(self, mock_obj, expected):
|
||||||
mock_obj.assert_has_calls(expected)
|
mock_obj.assert_has_calls(expected)
|
||||||
@ -248,11 +288,7 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
self._verify_mock_call(self.execute, self.execute_expected)
|
self._verify_mock_call(self.execute, self.execute_expected)
|
||||||
|
|
||||||
def test_construct(self):
|
def test_construct(self):
|
||||||
agent = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
agent = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
self.assertEqual(agent.agent_id, 'ovs-agent-%s' % cfg.CONF.host)
|
self.assertEqual(agent.agent_id, 'ovs-agent-%s' % cfg.CONF.host)
|
||||||
self._verify_mock_calls()
|
self._verify_mock_calls()
|
||||||
|
|
||||||
@ -260,12 +296,7 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
# ML2 l2 population mechanism driver.
|
# ML2 l2 population mechanism driver.
|
||||||
# The next two tests use l2_pop flag to test ARP responder
|
# The next two tests use l2_pop flag to test ARP responder
|
||||||
def test_construct_with_arp_responder(self):
|
def test_construct_with_arp_responder(self):
|
||||||
ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
self._build_agent(l2_population=True, arp_responder=True)
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU, l2_population=True,
|
|
||||||
arp_responder=True)
|
|
||||||
self.mock_tun_bridge_expected.insert(
|
self.mock_tun_bridge_expected.insert(
|
||||||
5, mock.call.add_flow(table=constants.PATCH_LV_TO_TUN,
|
5, mock.call.add_flow(table=constants.PATCH_LV_TO_TUN,
|
||||||
priority=1,
|
priority=1,
|
||||||
@ -283,21 +314,11 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
self._verify_mock_calls()
|
self._verify_mock_calls()
|
||||||
|
|
||||||
def test_construct_without_arp_responder(self):
|
def test_construct_without_arp_responder(self):
|
||||||
ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
self._build_agent(l2_population=False, arp_responder=True)
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU, l2_population=False,
|
|
||||||
arp_responder=True)
|
|
||||||
self._verify_mock_calls()
|
self._verify_mock_calls()
|
||||||
|
|
||||||
def test_construct_vxlan(self):
|
def test_construct_vxlan(self):
|
||||||
ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
self._build_agent(tunnel_types=['vxlan'])
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1',
|
|
||||||
self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['vxlan'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
self._verify_mock_calls()
|
self._verify_mock_calls()
|
||||||
|
|
||||||
def test_provision_local_vlan(self):
|
def test_provision_local_vlan(self):
|
||||||
@ -315,11 +336,7 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
(LV_ID, constants.LEARN_FROM_TUN)),
|
(LV_ID, constants.LEARN_FROM_TUN)),
|
||||||
]
|
]
|
||||||
|
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.available_local_vlans = set([LV_ID])
|
a.available_local_vlans = set([LV_ID])
|
||||||
a.tun_br_ofports = TUN_OFPORTS
|
a.tun_br_ofports = TUN_OFPORTS
|
||||||
a.provision_local_vlan(NET_UUID, p_const.TYPE_GRE, None, LS_ID)
|
a.provision_local_vlan(NET_UUID, p_const.TYPE_GRE, None, LS_ID)
|
||||||
@ -328,7 +345,7 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
def test_provision_local_vlan_flat(self):
|
def test_provision_local_vlan_flat(self):
|
||||||
action_string = 'strip_vlan,normal'
|
action_string = 'strip_vlan,normal'
|
||||||
self.mock_map_tun_bridge_expected.append(
|
self.mock_map_tun_bridge_expected.append(
|
||||||
mock.call.add_flow(priority=4, in_port=self.MAP_TUN_OFPORT,
|
mock.call.add_flow(priority=4, in_port=self.MAP_TUN_PHY_OFPORT,
|
||||||
dl_vlan=LV_ID, actions=action_string))
|
dl_vlan=LV_ID, actions=action_string))
|
||||||
|
|
||||||
action_string = 'mod_vlan_vid:%s,normal' % LV_ID
|
action_string = 'mod_vlan_vid:%s,normal' % LV_ID
|
||||||
@ -336,31 +353,23 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
mock.call.add_flow(priority=3, in_port=self.INT_OFPORT,
|
mock.call.add_flow(priority=3, in_port=self.INT_OFPORT,
|
||||||
dl_vlan=65535, actions=action_string))
|
dl_vlan=65535, actions=action_string))
|
||||||
|
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.available_local_vlans = set([LV_ID])
|
a.available_local_vlans = set([LV_ID])
|
||||||
a.phys_brs['net1'] = self.mock_map_tun_bridge
|
a.phys_brs['net1'] = self.mock_map_tun_bridge
|
||||||
a.phys_ofports['net1'] = self.MAP_TUN_OFPORT
|
a.phys_ofports['net1'] = self.MAP_TUN_PHY_OFPORT
|
||||||
a.int_ofports['net1'] = self.INT_OFPORT
|
a.int_ofports['net1'] = self.INT_OFPORT
|
||||||
a.provision_local_vlan(NET_UUID, p_const.TYPE_FLAT, 'net1', LS_ID)
|
a.provision_local_vlan(NET_UUID, p_const.TYPE_FLAT, 'net1', LS_ID)
|
||||||
self._verify_mock_calls()
|
self._verify_mock_calls()
|
||||||
|
|
||||||
def test_provision_local_vlan_flat_fail(self):
|
def test_provision_local_vlan_flat_fail(self):
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.provision_local_vlan(NET_UUID, p_const.TYPE_FLAT, 'net2', LS_ID)
|
a.provision_local_vlan(NET_UUID, p_const.TYPE_FLAT, 'net2', LS_ID)
|
||||||
self._verify_mock_calls()
|
self._verify_mock_calls()
|
||||||
|
|
||||||
def test_provision_local_vlan_vlan(self):
|
def test_provision_local_vlan_vlan(self):
|
||||||
action_string = 'mod_vlan_vid:%s,normal' % LS_ID
|
action_string = 'mod_vlan_vid:%s,normal' % LS_ID
|
||||||
self.mock_map_tun_bridge_expected.append(
|
self.mock_map_tun_bridge_expected.append(
|
||||||
mock.call.add_flow(priority=4, in_port=self.MAP_TUN_OFPORT,
|
mock.call.add_flow(priority=4, in_port=self.MAP_TUN_PHY_OFPORT,
|
||||||
dl_vlan=LV_ID, actions=action_string))
|
dl_vlan=LV_ID, actions=action_string))
|
||||||
|
|
||||||
action_string = 'mod_vlan_vid:%s,normal' % LS_ID
|
action_string = 'mod_vlan_vid:%s,normal' % LS_ID
|
||||||
@ -368,24 +377,16 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
mock.call.add_flow(priority=3, in_port=self.INT_OFPORT,
|
mock.call.add_flow(priority=3, in_port=self.INT_OFPORT,
|
||||||
dl_vlan=LV_ID, actions=action_string))
|
dl_vlan=LV_ID, actions=action_string))
|
||||||
|
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.available_local_vlans = set([LV_ID])
|
a.available_local_vlans = set([LV_ID])
|
||||||
a.phys_brs['net1'] = self.mock_map_tun_bridge
|
a.phys_brs['net1'] = self.mock_map_tun_bridge
|
||||||
a.phys_ofports['net1'] = self.MAP_TUN_OFPORT
|
a.phys_ofports['net1'] = self.MAP_TUN_PHY_OFPORT
|
||||||
a.int_ofports['net1'] = self.INT_OFPORT
|
a.int_ofports['net1'] = self.INT_OFPORT
|
||||||
a.provision_local_vlan(NET_UUID, p_const.TYPE_VLAN, 'net1', LS_ID)
|
a.provision_local_vlan(NET_UUID, p_const.TYPE_VLAN, 'net1', LS_ID)
|
||||||
self._verify_mock_calls()
|
self._verify_mock_calls()
|
||||||
|
|
||||||
def test_provision_local_vlan_vlan_fail(self):
|
def test_provision_local_vlan_vlan_fail(self):
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.provision_local_vlan(NET_UUID, p_const.TYPE_VLAN, 'net2', LS_ID)
|
a.provision_local_vlan(NET_UUID, p_const.TYPE_VLAN, 'net2', LS_ID)
|
||||||
self._verify_mock_calls()
|
self._verify_mock_calls()
|
||||||
|
|
||||||
@ -396,11 +397,7 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
mock.call.delete_flows(dl_vlan=LVM.vlan)
|
mock.call.delete_flows(dl_vlan=LVM.vlan)
|
||||||
]
|
]
|
||||||
|
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.available_local_vlans = set()
|
a.available_local_vlans = set()
|
||||||
a.local_vlan_map[NET_UUID] = LVM
|
a.local_vlan_map[NET_UUID] = LVM
|
||||||
a.reclaim_local_vlan(NET_UUID)
|
a.reclaim_local_vlan(NET_UUID)
|
||||||
@ -410,18 +407,14 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
def test_reclaim_local_vlan_flat(self):
|
def test_reclaim_local_vlan_flat(self):
|
||||||
self.mock_map_tun_bridge_expected.append(
|
self.mock_map_tun_bridge_expected.append(
|
||||||
mock.call.delete_flows(
|
mock.call.delete_flows(
|
||||||
in_port=self.MAP_TUN_OFPORT, dl_vlan=LVM_FLAT.vlan))
|
in_port=self.MAP_TUN_PHY_OFPORT, dl_vlan=LVM_FLAT.vlan))
|
||||||
self.mock_int_bridge_expected.append(
|
self.mock_int_bridge_expected.append(
|
||||||
mock.call.delete_flows(
|
mock.call.delete_flows(
|
||||||
dl_vlan=65535, in_port=self.INT_OFPORT))
|
dl_vlan=65535, in_port=self.INT_OFPORT))
|
||||||
|
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.phys_brs['net1'] = self.mock_map_tun_bridge
|
a.phys_brs['net1'] = self.mock_map_tun_bridge
|
||||||
a.phys_ofports['net1'] = self.MAP_TUN_OFPORT
|
a.phys_ofports['net1'] = self.MAP_TUN_PHY_OFPORT
|
||||||
a.int_ofports['net1'] = self.INT_OFPORT
|
a.int_ofports['net1'] = self.INT_OFPORT
|
||||||
|
|
||||||
a.available_local_vlans = set()
|
a.available_local_vlans = set()
|
||||||
@ -433,18 +426,14 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
def test_reclaim_local_vlan_vlan(self):
|
def test_reclaim_local_vlan_vlan(self):
|
||||||
self.mock_map_tun_bridge_expected.append(
|
self.mock_map_tun_bridge_expected.append(
|
||||||
mock.call.delete_flows(
|
mock.call.delete_flows(
|
||||||
in_port=self.MAP_TUN_OFPORT, dl_vlan=LVM_VLAN.vlan))
|
in_port=self.MAP_TUN_PHY_OFPORT, dl_vlan=LVM_VLAN.vlan))
|
||||||
self.mock_int_bridge_expected.append(
|
self.mock_int_bridge_expected.append(
|
||||||
mock.call.delete_flows(
|
mock.call.delete_flows(
|
||||||
dl_vlan=LV_ID, in_port=self.INT_OFPORT))
|
dl_vlan=LV_ID, in_port=self.INT_OFPORT))
|
||||||
|
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.phys_brs['net1'] = self.mock_map_tun_bridge
|
a.phys_brs['net1'] = self.mock_map_tun_bridge
|
||||||
a.phys_ofports['net1'] = self.MAP_TUN_OFPORT
|
a.phys_ofports['net1'] = self.MAP_TUN_PHY_OFPORT
|
||||||
a.int_ofports['net1'] = self.INT_OFPORT
|
a.int_ofports['net1'] = self.INT_OFPORT
|
||||||
|
|
||||||
a.available_local_vlans = set()
|
a.available_local_vlans = set()
|
||||||
@ -461,11 +450,7 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
mock.call.delete_flows(in_port=VIF_PORT.ofport)
|
mock.call.delete_flows(in_port=VIF_PORT.ofport)
|
||||||
]
|
]
|
||||||
|
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.local_vlan_map[NET_UUID] = LVM
|
a.local_vlan_map[NET_UUID] = LVM
|
||||||
a.port_bound(VIF_PORT, NET_UUID, 'gre', None, LS_ID, False)
|
a.port_bound(VIF_PORT, NET_UUID, 'gre', None, LS_ID, False)
|
||||||
self._verify_mock_calls()
|
self._verify_mock_calls()
|
||||||
@ -473,11 +458,7 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
def test_port_unbound(self):
|
def test_port_unbound(self):
|
||||||
with mock.patch.object(ovs_neutron_agent.OVSNeutronAgent,
|
with mock.patch.object(ovs_neutron_agent.OVSNeutronAgent,
|
||||||
'reclaim_local_vlan') as reclaim_local_vlan:
|
'reclaim_local_vlan') as reclaim_local_vlan:
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.local_vlan_map[NET_UUID] = LVM
|
a.local_vlan_map[NET_UUID] = LVM
|
||||||
a.port_unbound(VIF_ID, NET_UUID)
|
a.port_unbound(VIF_ID, NET_UUID)
|
||||||
|
|
||||||
@ -494,11 +475,7 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
actions='drop')
|
actions='drop')
|
||||||
]
|
]
|
||||||
|
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.available_local_vlans = set([LV_ID])
|
a.available_local_vlans = set([LV_ID])
|
||||||
a.local_vlan_map[NET_UUID] = LVM
|
a.local_vlan_map[NET_UUID] = LVM
|
||||||
a.port_dead(VIF_PORT)
|
a.port_dead(VIF_PORT)
|
||||||
@ -514,22 +491,14 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
actions='resubmit(,2)')
|
actions='resubmit(,2)')
|
||||||
]
|
]
|
||||||
|
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.tunnel_update(
|
a.tunnel_update(
|
||||||
mock.sentinel.ctx, tunnel_id='1', tunnel_ip='10.0.10.1',
|
mock.sentinel.ctx, tunnel_id='1', tunnel_ip='10.0.10.1',
|
||||||
tunnel_type=p_const.TYPE_GRE)
|
tunnel_type=p_const.TYPE_GRE)
|
||||||
self._verify_mock_calls()
|
self._verify_mock_calls()
|
||||||
|
|
||||||
def test_tunnel_update_self(self):
|
def test_tunnel_update_self(self):
|
||||||
a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
a = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1', self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
a.tunnel_update(
|
a.tunnel_update(
|
||||||
mock.sentinel.ctx, tunnel_id='1', tunnel_ip='10.0.0.1')
|
mock.sentinel.ctx, tunnel_id='1', tunnel_ip='10.0.0.1')
|
||||||
self._verify_mock_calls()
|
self._verify_mock_calls()
|
||||||
@ -561,12 +530,7 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
process_network_ports.side_effect = [
|
process_network_ports.side_effect = [
|
||||||
False, Exception('Fake exception to get out of the loop')]
|
False, Exception('Fake exception to get out of the loop')]
|
||||||
|
|
||||||
q_agent = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
|
q_agent = self._build_agent()
|
||||||
self.TUN_BRIDGE,
|
|
||||||
'10.0.0.1',
|
|
||||||
self.NET_MAPPING,
|
|
||||||
'sudo', 2, ['gre'],
|
|
||||||
self.VETH_MTU)
|
|
||||||
|
|
||||||
# Hack to test loop
|
# Hack to test loop
|
||||||
# We start method and expect it will raise after 2nd loop
|
# We start method and expect it will raise after 2nd loop
|
||||||
@ -594,10 +558,130 @@ class TunnelTest(base.BaseTestCase):
|
|||||||
self._verify_mock_calls()
|
self._verify_mock_calls()
|
||||||
|
|
||||||
|
|
||||||
class TunnelTestWithMTU(TunnelTest):
|
class TunnelTestUseVethInterco(TunnelTest):
|
||||||
|
USE_VETH_INTERCONNECTION = True
|
||||||
|
|
||||||
def setUp(self):
|
def _define_expected_calls(self):
|
||||||
super(TunnelTestWithMTU, self).setUp()
|
self.mock_bridge_expected = [
|
||||||
self.VETH_MTU = 1500
|
mock.call(self.INT_BRIDGE, 'sudo'),
|
||||||
|
mock.call(self.MAP_TUN_BRIDGE, 'sudo'),
|
||||||
|
mock.call(self.TUN_BRIDGE, 'sudo'),
|
||||||
|
]
|
||||||
|
|
||||||
|
self.mock_int_bridge_expected = [
|
||||||
|
mock.call.create(),
|
||||||
|
mock.call.set_secure_mode(),
|
||||||
|
mock.call.delete_port('patch-tun'),
|
||||||
|
mock.call.remove_all_flows(),
|
||||||
|
mock.call.add_flow(priority=1, actions='normal'),
|
||||||
|
mock.call.add_flow(table=constants.CANARY_TABLE, priority=0,
|
||||||
|
actions="drop")
|
||||||
|
]
|
||||||
|
|
||||||
|
self.mock_map_tun_bridge_expected = [
|
||||||
|
mock.call.remove_all_flows(),
|
||||||
|
mock.call.add_flow(priority=1, actions='normal'),
|
||||||
|
mock.call.delete_port('phy-%s' % self.MAP_TUN_BRIDGE),
|
||||||
|
mock.call.add_port(self.intb),
|
||||||
|
]
|
||||||
|
self.mock_int_bridge_expected += [
|
||||||
|
mock.call.delete_port('int-%s' % self.MAP_TUN_BRIDGE),
|
||||||
|
mock.call.add_port(self.inta)
|
||||||
|
]
|
||||||
|
|
||||||
|
self.mock_int_bridge_expected += [
|
||||||
|
mock.call.add_flow(priority=2,
|
||||||
|
in_port=self.MAP_TUN_INT_OFPORT,
|
||||||
|
actions='drop')
|
||||||
|
]
|
||||||
|
self.mock_map_tun_bridge_expected += [
|
||||||
|
mock.call.add_flow(priority=2,
|
||||||
|
in_port=self.MAP_TUN_PHY_OFPORT,
|
||||||
|
actions='drop')
|
||||||
|
]
|
||||||
|
|
||||||
|
self.mock_tun_bridge_expected = [
|
||||||
|
mock.call.reset_bridge(),
|
||||||
|
mock.call.add_patch_port('patch-int', 'patch-tun'),
|
||||||
|
]
|
||||||
|
self.mock_int_bridge_expected += [
|
||||||
|
mock.call.add_patch_port('patch-tun', 'patch-int')
|
||||||
|
]
|
||||||
|
|
||||||
|
self.mock_tun_bridge_expected += [
|
||||||
|
mock.call.remove_all_flows(),
|
||||||
|
mock.call.add_flow(priority=1,
|
||||||
|
in_port=self.INT_OFPORT,
|
||||||
|
actions="resubmit(,%s)" %
|
||||||
|
constants.PATCH_LV_TO_TUN),
|
||||||
|
mock.call.add_flow(priority=0, actions='drop'),
|
||||||
|
mock.call.add_flow(priority=0,
|
||||||
|
table=constants.PATCH_LV_TO_TUN,
|
||||||
|
dl_dst=UCAST_MAC,
|
||||||
|
actions="resubmit(,%s)" %
|
||||||
|
constants.UCAST_TO_TUN),
|
||||||
|
mock.call.add_flow(priority=0,
|
||||||
|
table=constants.PATCH_LV_TO_TUN,
|
||||||
|
dl_dst=BCAST_MAC,
|
||||||
|
actions="resubmit(,%s)" %
|
||||||
|
constants.FLOOD_TO_TUN),
|
||||||
|
]
|
||||||
|
for tunnel_type in constants.TUNNEL_NETWORK_TYPES:
|
||||||
|
self.mock_tun_bridge_expected.append(
|
||||||
|
mock.call.add_flow(
|
||||||
|
table=constants.TUN_TABLE[tunnel_type],
|
||||||
|
priority=0,
|
||||||
|
actions="drop"))
|
||||||
|
learned_flow = ("table=%s,"
|
||||||
|
"priority=1,"
|
||||||
|
"hard_timeout=300,"
|
||||||
|
"NXM_OF_VLAN_TCI[0..11],"
|
||||||
|
"NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],"
|
||||||
|
"load:0->NXM_OF_VLAN_TCI[],"
|
||||||
|
"load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],"
|
||||||
|
"output:NXM_OF_IN_PORT[]" %
|
||||||
|
constants.UCAST_TO_TUN)
|
||||||
|
self.mock_tun_bridge_expected += [
|
||||||
|
mock.call.add_flow(table=constants.LEARN_FROM_TUN,
|
||||||
|
priority=1,
|
||||||
|
actions="learn(%s),output:%s" %
|
||||||
|
(learned_flow, self.INT_OFPORT)),
|
||||||
|
mock.call.add_flow(table=constants.UCAST_TO_TUN,
|
||||||
|
priority=0,
|
||||||
|
actions="resubmit(,%s)" %
|
||||||
|
constants.FLOOD_TO_TUN),
|
||||||
|
mock.call.add_flow(table=constants.FLOOD_TO_TUN,
|
||||||
|
priority=0,
|
||||||
|
actions="drop")
|
||||||
|
]
|
||||||
|
|
||||||
|
self.device_exists_expected = [
|
||||||
|
mock.call(self.MAP_TUN_BRIDGE, 'sudo'),
|
||||||
|
mock.call('int-%s' % self.MAP_TUN_BRIDGE, 'sudo'),
|
||||||
|
]
|
||||||
|
|
||||||
|
self.ipdevice_expected = [
|
||||||
|
mock.call('int-%s' % self.MAP_TUN_BRIDGE, 'sudo'),
|
||||||
|
mock.call().link.delete()
|
||||||
|
]
|
||||||
|
self.ipwrapper_expected = [
|
||||||
|
mock.call('sudo'),
|
||||||
|
mock.call().add_veth('int-%s' % self.MAP_TUN_BRIDGE,
|
||||||
|
'phy-%s' % self.MAP_TUN_BRIDGE)
|
||||||
|
]
|
||||||
|
|
||||||
|
self.get_bridges_expected = [mock.call('sudo')]
|
||||||
|
|
||||||
|
self.inta_expected = [mock.call.link.set_up()]
|
||||||
|
self.intb_expected = [mock.call.link.set_up()]
|
||||||
|
self.execute_expected = [mock.call(['/sbin/udevadm', 'settle',
|
||||||
|
'--timeout=10'])]
|
||||||
|
|
||||||
|
|
||||||
|
class TunnelTestWithMTU(TunnelTestUseVethInterco):
|
||||||
|
VETH_MTU = 1500
|
||||||
|
|
||||||
|
def _define_expected_calls(self):
|
||||||
|
super(TunnelTestWithMTU, self)._define_expected_calls()
|
||||||
self.inta_expected.append(mock.call.link.set_mtu(self.VETH_MTU))
|
self.inta_expected.append(mock.call.link.set_mtu(self.VETH_MTU))
|
||||||
self.intb_expected.append(mock.call.link.set_mtu(self.VETH_MTU))
|
self.intb_expected.append(mock.call.link.set_mtu(self.VETH_MTU))
|
||||||
|
Loading…
Reference in New Issue
Block a user