[GRE] Add possibility to create GRE tunnels over IPv6

In case when IPv6 addresses are used for GRE tunnels, tunnel
type set for the openvswitch interface should be "ip6gre" instead of
"gre" which was set so far.
This patch changes that so now Neutron configures correct GRE tunnel
types.

Conflicts:
    neutron/tests/functional/agent/common/test_ovs_lib.py

Change-Id: I557af0bcafac4583ad9726c9bf707cf1fb92ffc5
Closes-Bug: #1904564
(cherry picked from commit 80e6781bc2)
This commit is contained in:
Slawek Kaplonski 2020-11-18 16:30:33 +01:00
parent 0f77298775
commit 80abfca487
3 changed files with 49 additions and 3 deletions

View File

@ -71,6 +71,9 @@ _SENTINEL = object()
CTRL_RATE_LIMIT_MIN = 100
CTRL_BURST_LIMIT_MIN = 25
# TODO(slaweq): move this to neutron_lib.constants
TYPE_GRE_IP6 = 'ip6gre'
def _ovsdb_result_pending(result):
"""Return True if ovsdb indicates the result is still pending."""
@ -97,6 +100,13 @@ def _ovsdb_retry(fn):
return wrapped
def get_gre_tunnel_port_type(remote_ip, local_ip):
if (common_utils.get_ip_version(remote_ip) == p_const.IP_VERSION_6 or
common_utils.get_ip_version(local_ip) == p_const.IP_VERSION_6):
return TYPE_GRE_IP6
return p_const.TYPE_GRE
class VifPort(object):
def __init__(self, port_name, ofport, vif_id, vif_mac, switch):
self.port_name = port_name
@ -504,6 +514,8 @@ class OVSBridge(BaseOVS):
dont_fragment=True,
tunnel_csum=False,
tos=None):
if tunnel_type == p_const.TYPE_GRE:
tunnel_type = get_gre_tunnel_port_type(remote_ip, local_ip)
attrs = [('type', tunnel_type)]
# TODO(twilson) This is an OrderedDict solely to make a test happy
options = collections.OrderedDict()
@ -527,6 +539,10 @@ class OVSBridge(BaseOVS):
options['csum'] = str(tunnel_csum).lower()
if tos:
options['tos'] = str(tos)
if tunnel_type == TYPE_GRE_IP6:
# NOTE(slaweq) According to the OVS documentation L3 GRE tunnels
# over IPv6 are not supported.
options['packet_type'] = 'legacy'
attrs.append(('options', options))
return self.add_port(port_name, *attrs)

View File

@ -16,6 +16,7 @@
import functools
import mock
from neutron_lib import constants as p_const
from neutron_lib.services.qos import constants as qos_constants
from oslo_utils import uuidutils
import six
@ -437,3 +438,30 @@ class BaseOVSTestCase(base.BaseSudoTestCase):
self.assertEqual(8000,
self.ovs.db_get_val('Controller', self.br_name,
'inactivity_probe'))
def test_add_gre_tunnel_port(self):
ipv4_tunnel_port = "test-ipv4-port"
ipv6_tunnel_port = "test-ipv6-port"
self._create_bridge()
self.ovs.add_tunnel_port(
ipv4_tunnel_port, "10.0.0.1", "10.0.0.2",
tunnel_type=p_const.TYPE_GRE)
self.ovs.add_tunnel_port(
ipv6_tunnel_port, "2001:db8::1", "2001:db8:2",
tunnel_type=p_const.TYPE_GRE)
interfaces = self.ovs.get_ports_attributes(
"Interface", columns=["name", "type", "options"],
if_exists=True)
ipv4_port_type = None
ipv6_port_type = None
ipv6_port_options = {}
for interface in interfaces:
if interface['name'] == ipv4_tunnel_port:
ipv4_port_type = interface['type']
elif interface['name'] == ipv6_tunnel_port:
ipv6_port_type = interface['type']
ipv6_port_options = interface['options']
self.assertEqual(p_const.TYPE_GRE, ipv4_port_type)
self.assertEqual(ovs_lib.TYPE_GRE_IP6, ipv6_port_type)
self.assertEqual('legacy', ipv6_port_options.get('packet_type'))

View File

@ -212,11 +212,12 @@ class OVSBridgeTestCase(OVSBridgeTestBase):
self.br.br_name, 'datapath_id', dpid)
self.assertIn(dpid, self.br.get_datapath_id())
def _test_add_tunnel_port(self, attrs):
def _test_add_tunnel_port(self, attrs,
expected_tunnel_type=const.TYPE_GRE):
port_name = utils.get_rand_device_name(net_helpers.PORT_PREFIX)
self.br.add_tunnel_port(port_name, attrs['remote_ip'],
attrs['local_ip'])
self.assertEqual('gre',
self.assertEqual(expected_tunnel_type,
self.ovs.db_get_val('Interface', port_name, 'type'))
options = self.ovs.db_get_val('Interface', port_name, 'options')
for attr, val in attrs.items():
@ -234,7 +235,8 @@ class OVSBridgeTestCase(OVSBridgeTestBase):
'remote_ip': '2001:db8:200::1',
'local_ip': '2001:db8:100::1',
}
self._test_add_tunnel_port(attrs)
self._test_add_tunnel_port(
attrs, expected_tunnel_type=ovs_lib.TYPE_GRE_IP6)
def test_add_tunnel_port_custom_port(self):
port_name = utils.get_rand_device_name(net_helpers.PORT_PREFIX)