Merge "[OpenSwan] Enable usage of the MTU value of an IPSec connection"
This commit is contained in:
commit
d399aa8972
@ -28,6 +28,11 @@ conn {{ipsec_site_connection.id}}
|
||||
# [subnet]
|
||||
leftsubnet={{vpnservice.subnet.cidr}}
|
||||
# leftsubnet=networkA/netmaskA, networkB/netmaskB (IKEv2 only)
|
||||
# [updown]
|
||||
# What "updown" script to run to adjust routing and/or firewalling when
|
||||
# the status of the connection changes (default "ipsec _updown").
|
||||
# "--route yes" allows to specify such routing options as mtu and metric.
|
||||
leftupdown="ipsec _updown --route yes"
|
||||
######################
|
||||
# ipsec_site_connections
|
||||
######################
|
||||
@ -39,8 +44,7 @@ conn {{ipsec_site_connection.id}}
|
||||
rightsubnets={ {{ipsec_site_connection['peer_cidrs']|join(' ')}} }
|
||||
# rightsubnet=networkA/netmaskA, networkB/netmaskB (IKEv2 only)
|
||||
# [mtu]
|
||||
# Note It looks like not supported in the strongswan driver
|
||||
# ignore it now
|
||||
mtu={{ipsec_site_connection.mtu}}
|
||||
# [dpd_action]
|
||||
dpdaction={{ipsec_site_connection.dpd_action}}
|
||||
# [dpd_interval]
|
||||
|
@ -155,14 +155,13 @@ def get_ovs_bridge(br_name):
|
||||
return ovs_lib.OVSBridge(br_name)
|
||||
|
||||
|
||||
class TestIPSecScenario(base.BaseSudoTestCase):
|
||||
|
||||
class TestIPSecBase(base.BaseSudoTestCase):
|
||||
vpn_agent_ini = os.environ.get('VPN_AGENT_INI',
|
||||
'/etc/neutron/vpn_agent.ini')
|
||||
NESTED_NAMESPACE_SEPARATOR = '@'
|
||||
|
||||
def setUp(self):
|
||||
super(TestIPSecScenario, self).setUp()
|
||||
super(TestIPSecBase, self).setUp()
|
||||
mock.patch('neutron.agent.l3.agent.L3PluginApi').start()
|
||||
# avoid report_status running periodically
|
||||
mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall').start()
|
||||
@ -172,7 +171,12 @@ class TestIPSecScenario(base.BaseSudoTestCase):
|
||||
# root_helper_daemon and instead use root_helper
|
||||
# https://bugs.launchpad.net/neutron/+bug/1482622
|
||||
cfg.CONF.set_override('root_helper_daemon', None, group='AGENT')
|
||||
|
||||
self.fake_vpn_service = copy.deepcopy(FAKE_VPN_SERVICE)
|
||||
self.fake_ipsec_connection = copy.deepcopy(FAKE_IPSEC_CONNECTION)
|
||||
|
||||
self.vpn_agent = self._configure_agent('agent1')
|
||||
self.driver = self.vpn_agent.device_drivers[0]
|
||||
|
||||
def connect_agents(self, agent1, agent2):
|
||||
"""Simulate both agents in the same host.
|
||||
@ -301,7 +305,7 @@ class TestIPSecScenario(base.BaseSudoTestCase):
|
||||
return agent.router_info[router['id']]
|
||||
|
||||
def prepare_vpn_service_info(self, router_id, external_ip, subnet_cidr):
|
||||
service = copy.deepcopy(FAKE_VPN_SERVICE)
|
||||
service = copy.deepcopy(self.fake_vpn_service)
|
||||
service.update({
|
||||
'id': _uuid(),
|
||||
'router_id': router_id,
|
||||
@ -310,7 +314,7 @@ class TestIPSecScenario(base.BaseSudoTestCase):
|
||||
return service
|
||||
|
||||
def prepare_ipsec_conn_info(self, vpn_service, peer_vpn_service):
|
||||
ipsec_conn = copy.deepcopy(FAKE_IPSEC_CONNECTION)
|
||||
ipsec_conn = copy.deepcopy(self.fake_ipsec_connection)
|
||||
ipsec_conn.update({
|
||||
'id': _uuid(),
|
||||
'vpnservice_id': vpn_service['id'],
|
||||
@ -402,8 +406,7 @@ class TestIPSecScenario(base.BaseSudoTestCase):
|
||||
break
|
||||
return pm.active
|
||||
|
||||
def test_ipsec_site_connections(self):
|
||||
device = self.vpn_agent.device_drivers[0]
|
||||
def _create_ipsec_site_connection(self, l3ha=False):
|
||||
# Mock the method below because it causes Exception:
|
||||
# RuntimeError: Second simultaneous read on fileno 5 detected.
|
||||
# Unless you really know what you're doing, make sure that only
|
||||
@ -414,32 +417,49 @@ class TestIPSecScenario(base.BaseSudoTestCase):
|
||||
ip_lib.send_ip_addr_adv_notif = mock.Mock()
|
||||
# There are no vpn services yet. get_vpn_services_on_host returns
|
||||
# empty list
|
||||
device.agent_rpc.get_vpn_services_on_host = mock.Mock(
|
||||
self.driver.agent_rpc.get_vpn_services_on_host = mock.Mock(
|
||||
return_value=[])
|
||||
# instantiate network resources "router", "private network"
|
||||
private_nets = list(PRIVATE_NET.subnet(24))
|
||||
site1 = self.site_setup(PUBLIC_NET[4], private_nets[1])
|
||||
site2 = self.site_setup(PUBLIC_NET[5], private_nets[2])
|
||||
if l3ha:
|
||||
site2 = self.setup_ha_routers(PUBLIC_NET[5], private_nets[2])
|
||||
else:
|
||||
site2 = self.site_setup(PUBLIC_NET[5], private_nets[2])
|
||||
# build vpn resources
|
||||
self.prepare_ipsec_conn_info(site1['vpn_service'],
|
||||
site2['vpn_service'])
|
||||
self.prepare_ipsec_conn_info(site2['vpn_service'],
|
||||
site1['vpn_service'])
|
||||
|
||||
device.report_status = mock.Mock()
|
||||
device.agent_rpc.get_vpn_services_on_host = mock.Mock(
|
||||
self.driver.report_status = mock.Mock()
|
||||
self.driver.agent_rpc.get_vpn_services_on_host = mock.Mock(
|
||||
return_value=[site1['vpn_service'],
|
||||
site2['vpn_service']])
|
||||
if l3ha:
|
||||
self.failover_agent_driver.agent_rpc.get_vpn_services_on_host = (
|
||||
mock.Mock(return_value=[]))
|
||||
self.failover_agent_driver.report_status = mock.Mock()
|
||||
self.failover_agent_driver.agent_rpc.get_vpn_services_on_host = (
|
||||
mock.Mock(return_value=[site2['vpn_service']]))
|
||||
|
||||
return site1, site2
|
||||
|
||||
|
||||
class TestIPSecScenario(TestIPSecBase):
|
||||
|
||||
def test_ipsec_site_connections(self):
|
||||
site1, site2 = self._create_ipsec_site_connection()
|
||||
|
||||
net_helpers.assert_no_ping(site1['port_namespace'], site2['port_ip'],
|
||||
timeout=8, count=4)
|
||||
net_helpers.assert_no_ping(site2['port_namespace'], site1['port_ip'],
|
||||
timeout=8, count=4)
|
||||
|
||||
device.sync(mock.Mock(), [{'id': site1['router'].router_id},
|
||||
{'id': site2['router'].router_id}])
|
||||
self.driver.sync(mock.Mock(), [{'id': site1['router'].router_id},
|
||||
{'id': site2['router'].router_id}])
|
||||
self.addCleanup(
|
||||
device._delete_vpn_processes,
|
||||
self.driver._delete_vpn_processes,
|
||||
[site1['router'].router_id, site2['router'].router_id], [])
|
||||
|
||||
net_helpers.assert_ping(site1['port_namespace'], site2['port_ip'],
|
||||
@ -466,39 +486,14 @@ class TestIPSecScenario(base.BaseSudoTestCase):
|
||||
self.connect_agents(self.vpn_agent, self.failover_agent)
|
||||
|
||||
vpn_agent_driver = self.vpn_agent.device_drivers[0]
|
||||
failover_agent_driver = self.failover_agent.device_drivers[0]
|
||||
ip_lib.send_ip_addr_adv_notif = mock.Mock()
|
||||
self.failover_agent_driver = self.failover_agent.device_drivers[0]
|
||||
|
||||
# There are no vpn services yet. get_vpn_services_on_host returns
|
||||
# empty list
|
||||
vpn_agent_driver.agent_rpc.get_vpn_services_on_host = mock.Mock(
|
||||
return_value=[])
|
||||
failover_agent_driver.agent_rpc.get_vpn_services_on_host = mock.Mock(
|
||||
return_value=[])
|
||||
site1, site2 = self._create_ipsec_site_connection(l3ha=True)
|
||||
|
||||
# instantiate network resources "router", "private network"
|
||||
private_nets = list(PRIVATE_NET.subnet(24))
|
||||
site1 = self.site_setup(PUBLIC_NET[4], private_nets[1])
|
||||
site2 = self.setup_ha_routers(PUBLIC_NET[5], private_nets[2])
|
||||
router = site1['router']
|
||||
router1 = site2['router1']
|
||||
router2 = site2['router2']
|
||||
|
||||
# build vpn resources
|
||||
self.prepare_ipsec_conn_info(site1['vpn_service'],
|
||||
site2['vpn_service'])
|
||||
self.prepare_ipsec_conn_info(site2['vpn_service'],
|
||||
site1['vpn_service'])
|
||||
|
||||
vpn_agent_driver.report_status = mock.Mock()
|
||||
failover_agent_driver.report_status = mock.Mock()
|
||||
|
||||
vpn_agent_driver.agent_rpc.get_vpn_services_on_host = mock.Mock(
|
||||
return_value=[site1['vpn_service'],
|
||||
site2['vpn_service']])
|
||||
failover_agent_driver.agent_rpc.get_vpn_services_on_host = mock.Mock(
|
||||
return_value=[site2['vpn_service']])
|
||||
|
||||
# No ipsec connection between legacy router and HA routers
|
||||
net_helpers.assert_no_ping(site1['port_namespace'], site2['port_ip'],
|
||||
timeout=8, count=4)
|
||||
@ -508,7 +503,8 @@ class TestIPSecScenario(base.BaseSudoTestCase):
|
||||
# sync the routers
|
||||
vpn_agent_driver.sync(mock.Mock(), [{'id': router.router_id},
|
||||
{'id': router1.router_id}])
|
||||
failover_agent_driver.sync(mock.Mock(), [{'id': router1.router_id}])
|
||||
self.failover_agent_driver.sync(mock.Mock(),
|
||||
[{'id': router1.router_id}])
|
||||
|
||||
self.addCleanup(
|
||||
vpn_agent_driver._delete_vpn_processes,
|
||||
@ -529,7 +525,8 @@ class TestIPSecScenario(base.BaseSudoTestCase):
|
||||
|
||||
# wait until ipsec process running in failover agent's HA router
|
||||
# check for both strongswan and openswan processes
|
||||
path = failover_agent_driver.processes[router2.router_id].config_dir
|
||||
path = self.failover_agent_driver.processes[
|
||||
router2.router_id].config_dir
|
||||
pid_files = ['%s/var/run/charon.pid' % path,
|
||||
'%s/var/run/pluto.pid' % path]
|
||||
linux_utils.wait_until_true(
|
||||
|
@ -20,16 +20,34 @@
|
||||
# functional test for the OpenSwan reference implementation. For now, just
|
||||
# ignore the test cases herein.
|
||||
|
||||
from neutron.tests.functional import base
|
||||
import mock
|
||||
from neutron.agent.linux import ip_lib
|
||||
from neutron.agent.linux import utils as linux_utils
|
||||
|
||||
from neutron_vpnaas.tests.functional.common import test_scenario
|
||||
|
||||
|
||||
class TestOpenSwanDeviceDriver(base.BaseSudoTestCase):
|
||||
class TestOpenSwanDeviceDriver(test_scenario.TestIPSecBase):
|
||||
|
||||
"""Test the OpenSwan reference implmentation of the device driver."""
|
||||
"""Test the OpenSwan reference implementation of the device driver."""
|
||||
|
||||
# NOTE: Tests may be added/removed/changed, when this is fleshed out
|
||||
# in future commits.
|
||||
|
||||
def _ping_mtu(self, namespace, ip, size):
|
||||
"""Pings ip address using packets of given size and with DF=1.
|
||||
|
||||
In order to ping it uses following cli command:
|
||||
ip netns exec <namespace> ping -c 4 -M do -s <size> <ip>
|
||||
"""
|
||||
try:
|
||||
cmd = ['ping', '-c', 4, '-M', 'do', '-s', size, ip]
|
||||
cmd = ip_lib.add_namespace_to_cmd(cmd, namespace)
|
||||
linux_utils.execute(cmd, run_as_root=True)
|
||||
return True
|
||||
except RuntimeError:
|
||||
return False
|
||||
|
||||
def test_config_files_created_on_ipsec_connection_create(self):
|
||||
"""Verify that directory and config files are correct on create."""
|
||||
pass
|
||||
@ -64,3 +82,30 @@ class TestOpenSwanDeviceDriver(base.BaseSudoTestCase):
|
||||
def test_status_reporting(self):
|
||||
"""Test status reported correctly to agent."""
|
||||
pass
|
||||
|
||||
def test_ipsec_site_connections_mtu_enforcement(self):
|
||||
"""Test that mtu of ipsec site connections is enforced."""
|
||||
|
||||
# Set up non-default mtu value
|
||||
self.fake_ipsec_connection['mtu'] = 1200
|
||||
|
||||
# Establish an ipsec connection between two sites
|
||||
site1, site2 = self._create_ipsec_site_connection()
|
||||
|
||||
self.driver.sync(mock.Mock(), [{'id': site1['router'].router_id},
|
||||
{'id': site2['router'].router_id}])
|
||||
self.addCleanup(
|
||||
self.driver._delete_vpn_processes,
|
||||
[site1['router'].router_id, site2['router'].router_id], [])
|
||||
|
||||
# Validate that ip packets with 1172 (1200) bytes of data pass
|
||||
self.assertTrue(self._ping_mtu(site1['port_namespace'],
|
||||
site2['port_ip'], 1172))
|
||||
self.assertTrue(self._ping_mtu(site2['port_namespace'],
|
||||
site1['port_ip'], 1172))
|
||||
|
||||
# Validate that ip packets with 1173 (1201) bytes of data are dropped
|
||||
self.assertFalse(self._ping_mtu(site1['port_namespace'],
|
||||
site2['port_ip'], 1173))
|
||||
self.assertFalse(self._ping_mtu(site2['port_namespace'],
|
||||
site1['port_ip'], 1173))
|
||||
|
@ -67,6 +67,7 @@ FAKE_VPN_SERVICE = {
|
||||
'id': FAKE_IPSEC_SITE_CONNECTION1_ID,
|
||||
'external_ip': '50.0.0.4',
|
||||
'peer_address': '30.0.0.5',
|
||||
'mtu': 1500,
|
||||
'peer_id': '30.0.0.5',
|
||||
'psk': 'password',
|
||||
'initiator': 'bi-directional',
|
||||
@ -79,6 +80,7 @@ FAKE_VPN_SERVICE = {
|
||||
'external_ip': '50.0.0.4',
|
||||
'peer_address': '50.0.0.5',
|
||||
'peer_id': '50.0.0.5',
|
||||
'mtu': 1500,
|
||||
'psk': 'password',
|
||||
'id': FAKE_IPSEC_SITE_CONNECTION2_ID,
|
||||
'initiator': 'bi-directional',
|
||||
@ -99,8 +101,7 @@ AUTH_AH = '''ah
|
||||
|
||||
OPENSWAN_CONNECTION_DETAILS = '''# rightsubnet=networkA/netmaskA, networkB/netmaskB (IKEv2 only)
|
||||
# [mtu]
|
||||
# Note It looks like not supported in the strongswan driver
|
||||
# ignore it now
|
||||
mtu=1500
|
||||
# [dpd_action]
|
||||
dpdaction=
|
||||
# [dpd_interval]
|
||||
@ -152,6 +153,11 @@ conn %(conn1_id)s
|
||||
# [subnet]
|
||||
leftsubnet=10.0.0.0/24
|
||||
# leftsubnet=networkA/netmaskA, networkB/netmaskB (IKEv2 only)
|
||||
# [updown]
|
||||
# What "updown" script to run to adjust routing and/or firewalling when
|
||||
# the status of the connection changes (default "ipsec _updown").
|
||||
# "--route yes" allows to specify such routing options as mtu and metric.
|
||||
leftupdown="ipsec _updown --route yes"
|
||||
######################
|
||||
# ipsec_site_connections
|
||||
######################
|
||||
@ -172,6 +178,11 @@ conn %(conn1_id)s
|
||||
# [subnet]
|
||||
leftsubnet=10.0.0.0/24
|
||||
# leftsubnet=networkA/netmaskA, networkB/netmaskB (IKEv2 only)
|
||||
# [updown]
|
||||
# What "updown" script to run to adjust routing and/or firewalling when
|
||||
# the status of the connection changes (default "ipsec _updown").
|
||||
# "--route yes" allows to specify such routing options as mtu and metric.
|
||||
leftupdown="ipsec _updown --route yes"
|
||||
######################
|
||||
# ipsec_site_connections
|
||||
######################
|
||||
|
Loading…
Reference in New Issue
Block a user