Add support for IPv6 tunnel endpoints

Currently, neutron tunnel endpoints must be IPv4 addresses,
i.e. $HOST_IP, although IPv6 endpoints are supported by most
drivers.

Create a TUNNEL_IP_VERSION variable to choose which host IP
to use, either HOST_IP or HOST_IPV6, and configure it in the
OVS and Linuxbridge agent driver files. The default is still
IPv4, but it can be over-ridden by specifying TUNNEL_ENDPOINT_IP
accordingly.

This behaves similar to the SERVICE_IP_VERSION option, which
can either be set to 4 or 6, but not 4+6 - the tunnel overhead
should be consistent on all systems in order not to have MTU
issues.

Must set the ML2 overlay_ip_version config option to match
else agent tunnel sync RPC will not work.

Must set the OVN external_ids:ovn-encap-ip config option to
the correct address.

Updated 'devstack-ipv6-only' job definition and verification role
that will set all services and tunnels to use IPv6 addresses.

Closes-bug: #1619476

Change-Id: I6034278dfc17b55d7863bc4db541bbdaa983a686
This commit is contained in:
Brian Haley 2020-02-28 14:55:08 -05:00 committed by Brian Haley
parent e661cae7e8
commit c869d59857
10 changed files with 84 additions and 27 deletions

View File

@ -625,11 +625,13 @@
name: devstack-ipv6 name: devstack-ipv6
parent: devstack parent: devstack
description: | description: |
Devstack single node job for integration gate with IPv6. Devstack single node job for integration gate with IPv6,
all services and tunnels using IPv6 addresses.
vars: vars:
devstack_localrc: devstack_localrc:
SERVICE_IP_VERSION: 6 SERVICE_IP_VERSION: 6
SERVICE_HOST: "" SERVICE_HOST: ""
TUNNEL_IP_VERSION: 6
- job: - job:
name: devstack-enforce-scope name: devstack-enforce-scope

View File

@ -521,8 +521,8 @@ behavior:
can be configured with any valid IPv6 prefix. The default values make can be configured with any valid IPv6 prefix. The default values make
use of an auto-generated ``IPV6_GLOBAL_ID`` to comply with RFC4193. use of an auto-generated ``IPV6_GLOBAL_ID`` to comply with RFC4193.
Service Version Service IP Version
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
DevStack can enable service operation over either IPv4 or IPv6 by DevStack can enable service operation over either IPv4 or IPv6 by
setting ``SERVICE_IP_VERSION`` to either ``SERVICE_IP_VERSION=4`` or setting ``SERVICE_IP_VERSION`` to either ``SERVICE_IP_VERSION=4`` or
@ -542,6 +542,27 @@ optionally be used to alter the default IPv6 address::
HOST_IPV6=${some_local_ipv6_address} HOST_IPV6=${some_local_ipv6_address}
Tunnel IP Version
~~~~~~~~~~~~~~~~~
DevStack can enable tunnel operation over either IPv4 or IPv6 by
setting ``TUNNEL_IP_VERSION`` to either ``TUNNEL_IP_VERSION=4`` or
``TUNNEL_IP_VERSION=6`` respectively.
When set to ``4`` Neutron will use an IPv4 address for tunnel endpoints,
for example, ``HOST_IP``.
When set to ``6`` Neutron will use an IPv6 address for tunnel endpoints,
for example, ``HOST_IPV6``.
The default value for this setting is ``4``. Dual-mode support, for
example ``4+6`` is not supported, as this value must match the address
family of the local tunnel endpoint IP(v6) address.
The value of ``TUNNEL_IP_VERSION`` has a direct relationship to the
setting of ``TUNNEL_ENDPOINT_IP``, which will default to ``HOST_IP``
when set to ``4``, and ``HOST_IPV6`` when set to ``6``.
Multi-node setup Multi-node setup
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~

View File

@ -49,7 +49,7 @@ KILL_PATH="$(which kill)"
STACK_ENV_VARS="BASE_SQL_CONN DATA_DIR DEST ENABLED_SERVICES HOST_IP \ STACK_ENV_VARS="BASE_SQL_CONN DATA_DIR DEST ENABLED_SERVICES HOST_IP \
KEYSTONE_SERVICE_URI \ KEYSTONE_SERVICE_URI \
LOGFILE OS_CACERT SERVICE_HOST STACK_USER TLS_IP \ LOGFILE OS_CACERT SERVICE_HOST STACK_USER TLS_IP \
HOST_IPV6 SERVICE_IP_VERSION" HOST_IPV6 SERVICE_IP_VERSION TUNNEL_ENDPOINT_IP TUNNEL_IP_VERSION"
# Saves significant environment variables to .stackenv for later use # Saves significant environment variables to .stackenv for later use

View File

@ -230,6 +230,7 @@ function configure_neutron_new {
mech_drivers+=",linuxbridge" mech_drivers+=",linuxbridge"
fi fi
iniset $NEUTRON_CORE_PLUGIN_CONF ml2 mechanism_drivers $mech_drivers iniset $NEUTRON_CORE_PLUGIN_CONF ml2 mechanism_drivers $mech_drivers
iniset $NEUTRON_CORE_PLUGIN_CONF ml2 overlay_ip_version $TUNNEL_IP_VERSION
iniset $NEUTRON_CORE_PLUGIN_CONF ml2_type_vxlan vni_ranges 1001:2000 iniset $NEUTRON_CORE_PLUGIN_CONF ml2_type_vxlan vni_ranges 1001:2000
iniset $NEUTRON_CORE_PLUGIN_CONF ml2_type_flat flat_networks $PUBLIC_NETWORK_NAME iniset $NEUTRON_CORE_PLUGIN_CONF ml2_type_flat flat_networks $PUBLIC_NETWORK_NAME
@ -251,10 +252,10 @@ function configure_neutron_new {
# Configure the neutron agent # Configure the neutron agent
if [[ $NEUTRON_AGENT == "linuxbridge" ]]; then if [[ $NEUTRON_AGENT == "linuxbridge" ]]; then
iniset $NEUTRON_CORE_PLUGIN_CONF securitygroup firewall_driver iptables iniset $NEUTRON_CORE_PLUGIN_CONF securitygroup firewall_driver iptables
iniset $NEUTRON_CORE_PLUGIN_CONF vxlan local_ip $HOST_IP iniset $NEUTRON_CORE_PLUGIN_CONF vxlan local_ip $TUNNEL_ENDPOINT_IP
elif [[ $NEUTRON_AGENT == "openvswitch" ]]; then elif [[ $NEUTRON_AGENT == "openvswitch" ]]; then
iniset $NEUTRON_CORE_PLUGIN_CONF securitygroup firewall_driver openvswitch iniset $NEUTRON_CORE_PLUGIN_CONF securitygroup firewall_driver openvswitch
iniset $NEUTRON_CORE_PLUGIN_CONF ovs local_ip $HOST_IP iniset $NEUTRON_CORE_PLUGIN_CONF ovs local_ip $TUNNEL_ENDPOINT_IP
if [[ "$NEUTRON_DISTRIBUTED_ROUTING" = "True" ]]; then if [[ "$NEUTRON_DISTRIBUTED_ROUTING" = "True" ]]; then
iniset $NEUTRON_CORE_PLUGIN_CONF agent l2_population True iniset $NEUTRON_CORE_PLUGIN_CONF agent l2_population True

View File

@ -246,13 +246,6 @@ if [[ $Q_AGENT == "linuxbridge" && -z ${LB_PHYSICAL_INTERFACE} ]]; then
LB_PHYSICAL_INTERFACE=$default_route_dev LB_PHYSICAL_INTERFACE=$default_route_dev
fi fi
# When Neutron tunnels are enabled it is needed to specify the
# IP address of the end point in the local server. This IP is set
# by default to the same IP address that the HOST IP.
# This variable can be used to specify a different end point IP address
# Example: ``TUNNEL_ENDPOINT_IP=1.1.1.1``
TUNNEL_ENDPOINT_IP=${TUNNEL_ENDPOINT_IP:-$HOST_IP}
# With the openvswitch plugin, set to True in ``localrc`` to enable # With the openvswitch plugin, set to True in ``localrc`` to enable
# provider GRE tunnels when ``ENABLE_TENANT_TUNNELS`` is False. # provider GRE tunnels when ``ENABLE_TENANT_TUNNELS`` is False.
# #

View File

@ -125,6 +125,7 @@ function neutron_plugin_configure_service {
fi fi
populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2 mechanism_drivers=$Q_ML2_PLUGIN_MECHANISM_DRIVERS populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2 mechanism_drivers=$Q_ML2_PLUGIN_MECHANISM_DRIVERS
populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2 overlay_ip_version=$TUNNEL_IP_VERSION
if [[ -n "$Q_ML2_PLUGIN_TYPE_DRIVERS" ]]; then if [[ -n "$Q_ML2_PLUGIN_TYPE_DRIVERS" ]]; then
populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2 type_drivers=$Q_ML2_PLUGIN_TYPE_DRIVERS populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2 type_drivers=$Q_ML2_PLUGIN_TYPE_DRIVERS

View File

@ -99,8 +99,10 @@ ENABLE_CHASSIS_AS_GW=$(trueorfalse True ENABLE_CHASSIS_AS_GW)
OVN_L3_CREATE_PUBLIC_NETWORK=$(trueorfalse True OVN_L3_CREATE_PUBLIC_NETWORK) OVN_L3_CREATE_PUBLIC_NETWORK=$(trueorfalse True OVN_L3_CREATE_PUBLIC_NETWORK)
export OVSDB_SERVER_LOCAL_HOST=$SERVICE_LOCAL_HOST export OVSDB_SERVER_LOCAL_HOST=$SERVICE_LOCAL_HOST
TUNNEL_IP=$TUNNEL_ENDPOINT_IP
if [[ "$SERVICE_IP_VERSION" == 6 ]]; then if [[ "$SERVICE_IP_VERSION" == 6 ]]; then
OVSDB_SERVER_LOCAL_HOST=[$OVSDB_SERVER_LOCAL_HOST] OVSDB_SERVER_LOCAL_HOST=[$OVSDB_SERVER_LOCAL_HOST]
TUNNEL_IP=[$TUNNEL_IP]
fi fi
OVN_IGMP_SNOOPING_ENABLE=$(trueorfalse False OVN_IGMP_SNOOPING_ENABLE) OVN_IGMP_SNOOPING_ENABLE=$(trueorfalse False OVN_IGMP_SNOOPING_ENABLE)
@ -639,7 +641,7 @@ function _start_ovs {
sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-remote="$OVN_SB_REMOTE" sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-remote="$OVN_SB_REMOTE"
sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-bridge="br-int" sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-bridge="br-int"
sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-encap-type="geneve" sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-encap-type="geneve"
sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-encap-ip="$HOST_IP" sudo ovs-vsctl --no-wait set open_vswitch . external-ids:ovn-encap-ip="$TUNNEL_IP"
sudo ovs-vsctl --no-wait set open_vswitch . external-ids:hostname="$LOCAL_HOSTNAME" sudo ovs-vsctl --no-wait set open_vswitch . external-ids:hostname="$LOCAL_HOSTNAME"
# Select this chassis to host gateway routers # Select this chassis to host gateway routers
if [[ "$ENABLE_CHASSIS_AS_GW" == "True" ]]; then if [[ "$ENABLE_CHASSIS_AS_GW" == "True" ]]; then
@ -654,7 +656,7 @@ function _start_ovs {
if is_service_enabled ovn-controller-vtep ; then if is_service_enabled ovn-controller-vtep ; then
ovn_base_setup_bridge br-v ovn_base_setup_bridge br-v
vtep-ctl add-ps br-v vtep-ctl add-ps br-v
vtep-ctl set Physical_Switch br-v tunnel_ips=$HOST_IP vtep-ctl set Physical_Switch br-v tunnel_ips=$TUNNEL_IP
enable_service ovs-vtep enable_service ovs-vtep
local vtepcmd="$OVS_SCRIPTDIR/ovs-vtep --log-file --pidfile --detach br-v" local vtepcmd="$OVS_SCRIPTDIR/ovs-vtep --log-file --pidfile --detach br-v"

View File

@ -1,10 +1,10 @@
Verify the IPv6-only deployments Verify all addresses in IPv6-only deployments
This role needs to be invoked from a playbook that This role needs to be invoked from a playbook that
run tests. This role verifies the IPv6 setting on runs tests. This role verifies the IPv6 settings on the
devstack side and devstack deploy services on IPv6. devstack side and that devstack deploys with all addresses
This role is invoked before tests are run so that being IPv6. This role is invoked before tests are run so that
if any missing IPv6 setting or deployments can fail if there is any missing IPv6 setting, deployments can fail
the job early. the job early.

26
stackrc
View File

@ -877,6 +877,32 @@ SERVICE_HOST=${SERVICE_HOST:-${DEF_SERVICE_HOST}}
# This is either 127.0.0.1 for IPv4 or ::1 for IPv6 # This is either 127.0.0.1 for IPv4 or ::1 for IPv6
SERVICE_LOCAL_HOST=${SERVICE_LOCAL_HOST:-${DEF_SERVICE_LOCAL_HOST}} SERVICE_LOCAL_HOST=${SERVICE_LOCAL_HOST:-${DEF_SERVICE_LOCAL_HOST}}
# TUNNEL IP version
# This is the IP version to use for tunnel endpoints
TUNNEL_IP_VERSION=${TUNNEL_IP_VERSION:-4}
# Validate TUNNEL_IP_VERSION
if [[ $TUNNEL_IP_VERSION != "4" ]] && [[ $TUNNEL_IP_VERSION != "6" ]]; then
die $LINENO "TUNNEL_IP_VERSION must be either 4 or 6"
fi
if [[ "$TUNNEL_IP_VERSION" == 4 ]]; then
DEF_TUNNEL_ENDPOINT_IP=$HOST_IP
fi
if [[ "$TUNNEL_IP_VERSION" == 6 ]]; then
# Only die if the user has not over-ridden the endpoint IP
if [[ "$HOST_IPV6" == "" ]] && [[ "$TUNNEL_ENDPOINT_IP" == "" ]]; then
die $LINENO "Could not determine host IPv6 address. See local.conf for suggestions on setting HOST_IPV6."
fi
DEF_TUNNEL_ENDPOINT_IP=$HOST_IPV6
fi
# Allow the use of an alternate address for tunnel endpoints.
# Default is dependent on TUNNEL_IP_VERSION above.
TUNNEL_ENDPOINT_IP=${TUNNEL_ENDPOINT_IP:-${DEF_TUNNEL_ENDPOINT_IP}}
REGION_NAME=${REGION_NAME:-RegionOne} REGION_NAME=${REGION_NAME:-RegionOne}
# Configure services to use syslog instead of writing to individual log files # Configure services to use syslog instead of writing to individual log files

View File

@ -23,32 +23,43 @@ function verify_devstack_ipv6_setting {
_service_listen_address=$(echo $SERVICE_LISTEN_ADDRESS | tr -d []) _service_listen_address=$(echo $SERVICE_LISTEN_ADDRESS | tr -d [])
local _service_local_host='' local _service_local_host=''
_service_local_host=$(echo $SERVICE_LOCAL_HOST | tr -d []) _service_local_host=$(echo $SERVICE_LOCAL_HOST | tr -d [])
local _tunnel_endpoint_ip=''
_tunnel_endpoint_ip=$(echo $TUNNEL_ENDPOINT_IP | tr -d [])
if [[ "$SERVICE_IP_VERSION" != 6 ]]; then if [[ "$SERVICE_IP_VERSION" != 6 ]]; then
echo $SERVICE_IP_VERSION "SERVICE_IP_VERSION is not set to 6 which is must for devstack to deploy services with IPv6 address." echo $SERVICE_IP_VERSION "SERVICE_IP_VERSION is not set to 6 which is must for devstack to deploy services with IPv6 address."
exit 1 exit 1
fi fi
if [[ "$TUNNEL_IP_VERSION" != 6 ]]; then
echo $TUNNEL_IP_VERSION "TUNNEL_IP_VERSION is not set to 6 so TUNNEL_ENDPOINT_IP cannot be an IPv6 address."
exit 1
fi
is_service_host_ipv6=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_service_host'"))') is_service_host_ipv6=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_service_host'"))')
if [[ "$is_service_host_ipv6" != "True" ]]; then if [[ "$is_service_host_ipv6" != "True" ]]; then
echo $SERVICE_HOST "SERVICE_HOST is not ipv6 which means devstack cannot deploy services on IPv6 address." echo $SERVICE_HOST "SERVICE_HOST is not IPv6 which means devstack cannot deploy services on IPv6 addresses."
exit 1 exit 1
fi fi
is_host_ipv6=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_host_ipv6'"))') is_host_ipv6=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_host_ipv6'"))')
if [[ "$is_host_ipv6" != "True" ]]; then if [[ "$is_host_ipv6" != "True" ]]; then
echo $HOST_IPV6 "HOST_IPV6 is not ipv6 which means devstack cannot deploy services on IPv6 address." echo $HOST_IPV6 "HOST_IPV6 is not IPv6 which means devstack cannot deploy services on IPv6 addresses."
exit 1 exit 1
fi fi
is_service_listen_address=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_service_listen_address'"))') is_service_listen_address=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_service_listen_address'"))')
if [[ "$is_service_listen_address" != "True" ]]; then if [[ "$is_service_listen_address" != "True" ]]; then
echo $SERVICE_LISTEN_ADDRESS "SERVICE_LISTEN_ADDRESS is not ipv6 which means devstack cannot deploy services on IPv6 address." echo $SERVICE_LISTEN_ADDRESS "SERVICE_LISTEN_ADDRESS is not IPv6 which means devstack cannot deploy services on IPv6 addresses."
exit 1 exit 1
fi fi
is_service_local_host=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_service_local_host'"))') is_service_local_host=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_service_local_host'"))')
if [[ "$is_service_local_host" != "True" ]]; then if [[ "$is_service_local_host" != "True" ]]; then
echo $SERVICE_LOCAL_HOST "SERVICE_LOCAL_HOST is not ipv6 which means devstack cannot deploy services on IPv6 address." echo $SERVICE_LOCAL_HOST "SERVICE_LOCAL_HOST is not IPv6 which means devstack cannot deploy services on IPv6 addresses."
exit 1
fi
is_tunnel_endpoint_ip=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$_tunnel_endpoint_ip'"))')
if [[ "$is_tunnel_endpoint_ip" != "True" ]]; then
echo $TUNNEL_ENDPOINT_IP "TUNNEL_ENDPOINT_IP is not IPv6 which means devstack will not deploy with an IPv6 endpoint address."
exit 1 exit 1
fi fi
echo "Devstack is properly configured with IPv6" echo "Devstack is properly configured with IPv6"
echo "SERVICE_IP_VERSION: " $SERVICE_IP_VERSION "HOST_IPV6: " $HOST_IPV6 "SERVICE_HOST: " $SERVICE_HOST "SERVICE_LISTEN_ADDRESS: " $SERVICE_LISTEN_ADDRESS "SERVICE_LOCAL_HOST: " $SERVICE_LOCAL_HOST echo "SERVICE_IP_VERSION:" $SERVICE_IP_VERSION "HOST_IPV6:" $HOST_IPV6 "SERVICE_HOST:" $SERVICE_HOST "SERVICE_LISTEN_ADDRESS:" $SERVICE_LISTEN_ADDRESS "SERVICE_LOCAL_HOST:" $SERVICE_LOCAL_HOST "TUNNEL_IP_VERSION:" $TUNNEL_IP_VERSION "TUNNEL_ENDPOINT_IP:" $TUNNEL_ENDPOINT_IP
} }
function sanity_check_system_ipv6_enabled { function sanity_check_system_ipv6_enabled {
@ -72,7 +83,7 @@ function verify_service_listen_address_is_ipv6 {
is_endpoint_ipv6=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$endpoint_address'"))') is_endpoint_ipv6=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$endpoint_address'"))')
if [[ "$is_endpoint_ipv6" != "True" ]]; then if [[ "$is_endpoint_ipv6" != "True" ]]; then
all_ipv6=False all_ipv6=False
echo $endpoint ": This is not ipv6 endpoint which means corresponding service is not listening on IPv6 address." echo $endpoint ": This is not an IPv6 endpoint which means corresponding service is not listening on an IPv6 address."
continue continue
fi fi
endpoints_verified=True endpoints_verified=True
@ -80,7 +91,7 @@ function verify_service_listen_address_is_ipv6 {
if [[ "$all_ipv6" == "False" ]] || [[ "$endpoints_verified" == "False" ]]; then if [[ "$all_ipv6" == "False" ]] || [[ "$endpoints_verified" == "False" ]]; then
exit 1 exit 1
fi fi
echo "All services deployed by devstack is on IPv6 endpoints" echo "All services deployed by devstack are on IPv6 endpoints"
echo $endpoints echo $endpoints
} }