OFA agent: use hexadecimal IP address in tunnel port name
The remote IP address is used to form the tunnel port name With some OVS/Linux combinations there is a 15 character limit on port names, so a name like 'gre-192.168.10.10' does not work. This fix uses the shorter hexadecimal representation of the IP address instead. This problem was reported and fixed for OVS agent. Closes-Bug: 1294474 Change-Id: Ieab1eb8a5c430f69aff61a317cc28f23ba95ad2d
This commit is contained in:
parent
d232f5ba28
commit
7cdd3b4d74
@ -19,6 +19,7 @@
|
||||
|
||||
import time
|
||||
|
||||
import netaddr
|
||||
from oslo.config import cfg
|
||||
from ryu.app.ofctl import api as ryu_api
|
||||
from ryu.base import app_manager
|
||||
@ -297,6 +298,14 @@ class OFANeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
|
||||
except Exception:
|
||||
LOG.exception(_("Failed reporting state!"))
|
||||
|
||||
def _create_tunnel_port_name(self, tunnel_type, ip_address):
|
||||
try:
|
||||
ip_hex = '%08x' % netaddr.IPAddress(ip_address, version=4)
|
||||
return '%s-%s' % (tunnel_type, ip_hex)
|
||||
except Exception:
|
||||
LOG.warn(_("Unable to create tunnel port. Invalid remote IP: %s"),
|
||||
ip_address)
|
||||
|
||||
def ryu_send_msg(self, msg):
|
||||
result = ryu_api.send_msg(self.ryuapp, msg)
|
||||
LOG.info(_("ryu send_msg() result: %s"), result)
|
||||
@ -376,7 +385,6 @@ class OFANeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
|
||||
if not self.enable_tunneling:
|
||||
return
|
||||
tunnel_ip = kwargs.get('tunnel_ip')
|
||||
tunnel_id = kwargs.get('tunnel_id', tunnel_ip)
|
||||
tunnel_type = kwargs.get('tunnel_type')
|
||||
if not tunnel_type:
|
||||
LOG.error(_("No tunnel_type specified, cannot create tunnels"))
|
||||
@ -386,7 +394,9 @@ class OFANeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
|
||||
return
|
||||
if tunnel_ip == self.local_ip:
|
||||
return
|
||||
tun_name = '%s-%s' % (tunnel_type, tunnel_id)
|
||||
tun_name = self._create_tunnel_port_name(tunnel_type, tunnel_ip)
|
||||
if not tun_name:
|
||||
return
|
||||
self.setup_tunnel_port(tun_name, tunnel_ip, tunnel_type)
|
||||
|
||||
def create_rpc_dispatcher(self):
|
||||
@ -1050,19 +1060,6 @@ class OFANeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
|
||||
self.ryu_send_msg(msg)
|
||||
return ofport
|
||||
|
||||
def cleanup_tunnel_port(self, tun_ofport, tunnel_type):
|
||||
# Check if this tunnel port is still used
|
||||
for lvm in self.local_vlan_map.values():
|
||||
if tun_ofport in lvm.tun_ofports:
|
||||
break
|
||||
# If not, remove it
|
||||
else:
|
||||
for remote_ip, ofport in self.tun_br_ofports[tunnel_type].items():
|
||||
if ofport == tun_ofport:
|
||||
port_name = '%s-%s' % (tunnel_type, remote_ip)
|
||||
self.tun_br.delete_port(port_name)
|
||||
self.tun_br_ofports[tunnel_type].pop(remote_ip, None)
|
||||
|
||||
def treat_devices_added(self, devices):
|
||||
resync = False
|
||||
self.sg_agent.prepare_devices_filter(devices)
|
||||
@ -1214,8 +1211,10 @@ class OFANeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
|
||||
tunnels = details['tunnels']
|
||||
for tunnel in tunnels:
|
||||
if self.local_ip != tunnel['ip_address']:
|
||||
tunnel_id = tunnel.get('id', tunnel['ip_address'])
|
||||
tun_name = '%s-%s' % (tunnel_type, tunnel_id)
|
||||
tun_name = self._create_tunnel_port_name(
|
||||
tunnel_type, tunnel['ip_address'])
|
||||
if not tun_name:
|
||||
continue
|
||||
self.setup_tunnel_port(tun_name,
|
||||
tunnel['ip_address'],
|
||||
tunnel_type)
|
||||
|
@ -19,6 +19,7 @@
|
||||
import contextlib
|
||||
|
||||
import mock
|
||||
import netaddr
|
||||
from oslo.config import cfg
|
||||
import testtools
|
||||
|
||||
@ -42,11 +43,11 @@ class OFAAgentTestCase(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(OFAAgentTestCase, self).setUp()
|
||||
self.fake_oflib_of = fake_oflib.patch_fake_oflib_of().start()
|
||||
self.mod_agent = importutils.import_module(self._AGENT_NAME)
|
||||
cfg.CONF.set_default('firewall_driver',
|
||||
'neutron.agent.firewall.NoopFirewallDriver',
|
||||
group='SECURITYGROUP')
|
||||
self.fake_oflib_of = fake_oflib.patch_fake_oflib_of().start()
|
||||
self.mod_agent = importutils.import_module(self._AGENT_NAME)
|
||||
self.ryuapp = mock.Mock()
|
||||
cfg.CONF.register_cli_opts([
|
||||
cfg.StrOpt('ofp-listen-host', default='',
|
||||
@ -375,17 +376,14 @@ class TestOFANeutronAgent(OFAAgentTestCase):
|
||||
)
|
||||
|
||||
def test_network_delete(self):
|
||||
with contextlib.nested(
|
||||
mock.patch.object(self.agent, "reclaim_local_vlan"),
|
||||
mock.patch.object(self.agent.tun_br, "cleanup_tunnel_port")
|
||||
) as (recl_fn, clean_tun_fn):
|
||||
with mock.patch.object(self.agent,
|
||||
"reclaim_local_vlan") as recl_fn:
|
||||
self.agent.network_delete("unused_context",
|
||||
network_id="123")
|
||||
self.assertFalse(recl_fn.called)
|
||||
self.agent.local_vlan_map["123"] = "LVM object"
|
||||
self.agent.network_delete("unused_context",
|
||||
network_id="123")
|
||||
self.assertFalse(clean_tun_fn.called)
|
||||
recl_fn.assert_called_with("123")
|
||||
|
||||
def test_port_update(self):
|
||||
@ -616,6 +614,73 @@ class TestOFANeutronAgent(OFAAgentTestCase):
|
||||
{'type': p_const.TYPE_GRE, 'ip': 'remote_ip'})
|
||||
self.assertEqual(ofport, 0)
|
||||
|
||||
def _create_tunnel_port_name(self, tunnel_ip, tunnel_type):
|
||||
tunnel_ip_hex = '%08x' % netaddr.IPAddress(tunnel_ip, version=4)
|
||||
return '%s-%s' % (tunnel_type, tunnel_ip_hex)
|
||||
|
||||
def test_tunnel_sync_with_valid_ip_address_and_gre_type(self):
|
||||
tunnel_ip = '100.101.102.103'
|
||||
self.agent.tunnel_types = ['gre']
|
||||
tun_name = self._create_tunnel_port_name(tunnel_ip,
|
||||
self.agent.tunnel_types[0])
|
||||
fake_tunnel_details = {'tunnels': [{'ip_address': tunnel_ip}]}
|
||||
with contextlib.nested(
|
||||
mock.patch.object(self.agent.plugin_rpc, 'tunnel_sync',
|
||||
return_value=fake_tunnel_details),
|
||||
mock.patch.object(self.agent, 'setup_tunnel_port')
|
||||
) as (tunnel_sync_rpc_fn, setup_tunnel_port_fn):
|
||||
self.agent.tunnel_sync()
|
||||
expected_calls = [mock.call(tun_name, tunnel_ip,
|
||||
self.agent.tunnel_types[0])]
|
||||
setup_tunnel_port_fn.assert_has_calls(expected_calls)
|
||||
|
||||
def test_tunnel_sync_with_valid_ip_address_and_vxlan_type(self):
|
||||
tunnel_ip = '100.101.31.15'
|
||||
self.agent.tunnel_types = ['vxlan']
|
||||
tun_name = self._create_tunnel_port_name(tunnel_ip,
|
||||
self.agent.tunnel_types[0])
|
||||
fake_tunnel_details = {'tunnels': [{'ip_address': tunnel_ip}]}
|
||||
with contextlib.nested(
|
||||
mock.patch.object(self.agent.plugin_rpc, 'tunnel_sync',
|
||||
return_value=fake_tunnel_details),
|
||||
mock.patch.object(self.agent, 'setup_tunnel_port')
|
||||
) as (tunnel_sync_rpc_fn, setup_tunnel_port_fn):
|
||||
self.agent.tunnel_sync()
|
||||
expected_calls = [mock.call(tun_name, tunnel_ip,
|
||||
self.agent.tunnel_types[0])]
|
||||
setup_tunnel_port_fn.assert_has_calls(expected_calls)
|
||||
|
||||
def test_tunnel_sync_invalid_ip_address(self):
|
||||
tunnel_ip = '100.100.100.100'
|
||||
self.agent.tunnel_types = ['vxlan']
|
||||
tun_name = self._create_tunnel_port_name(tunnel_ip,
|
||||
self.agent.tunnel_types[0])
|
||||
fake_tunnel_details = {'tunnels': [{'ip_address': '300.300.300.300'},
|
||||
{'ip_address': tunnel_ip}]}
|
||||
with contextlib.nested(
|
||||
mock.patch.object(self.agent.plugin_rpc, 'tunnel_sync',
|
||||
return_value=fake_tunnel_details),
|
||||
mock.patch.object(self.agent, 'setup_tunnel_port')
|
||||
) as (tunnel_sync_rpc_fn, setup_tunnel_port_fn):
|
||||
self.agent.tunnel_sync()
|
||||
setup_tunnel_port_fn.assert_called_once_with(
|
||||
tun_name, tunnel_ip, self.agent.tunnel_types[0])
|
||||
|
||||
def test_tunnel_update(self):
|
||||
tunnel_ip = '10.10.10.10'
|
||||
self.agent.tunnel_types = ['gre']
|
||||
tun_name = self._create_tunnel_port_name(tunnel_ip,
|
||||
self.agent.tunnel_types[0])
|
||||
kwargs = {'tunnel_ip': tunnel_ip,
|
||||
'tunnel_type': self.agent.tunnel_types[0]}
|
||||
self.agent.setup_tunnel_port = mock.Mock()
|
||||
self.agent.enable_tunneling = True
|
||||
self.agent.l2_pop = False
|
||||
self.agent.tunnel_update(context=None, **kwargs)
|
||||
expected_calls = [mock.call(tun_name, tunnel_ip,
|
||||
self.agent.tunnel_types[0])]
|
||||
self.agent.setup_tunnel_port.assert_has_calls(expected_calls)
|
||||
|
||||
|
||||
class AncillaryBridgesTest(OFAAgentTestCase):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user