Merge "Disable 'accept_ra' in DHCP agent namespace" into stable/newton

This commit is contained in:
Jenkins 2017-06-15 07:04:12 +00:00 committed by Gerrit Code Review
commit 18d241db6d
6 changed files with 44 additions and 11 deletions

View File

@ -646,7 +646,8 @@ class RouterInfo(object):
return
# There is no IPv6 gw_ip, use RouterAdvt for default route.
self.driver.configure_ipv6_ra(ns_name, interface_name)
self.driver.configure_ipv6_ra(ns_name, interface_name,
n_const.ACCEPT_RA_WITH_FORWARDING)
def _external_gateway_added(self, ex_gw_port, interface_name,
ns_name, preserve_ips):

View File

@ -38,7 +38,6 @@ from neutron.agent.linux import iptables_manager
from neutron.cmd.sanity import checks
from neutron.common import constants as n_const
from neutron.common import exceptions as n_exc
from neutron.common import ipv6_utils
from neutron.common import utils as common_utils
from neutron.extensions import extra_dhcp_opt as edo_ext
from neutron.ipam import utils as ipam_utils
@ -1364,6 +1363,15 @@ class DeviceManager(object):
def plug(self, network, port, interface_name):
"""Plug device settings for the network's DHCP on this host."""
# Disable acceptance of RAs in the namespace so we don't
# auto-configure an IPv6 address since we explicitly configure
# them on the device. This must be done before any interfaces
# are plugged since it could receive an RA by the time
# plug() returns, so we have to create the namespace first.
if network.namespace:
ip_lib.IPWrapper().ensure_namespace(network.namespace)
self.driver.configure_ipv6_ra(network.namespace, 'default',
n_const.ACCEPT_RA_DISABLED)
self.driver.plug(network.id,
port.id,
interface_name,
@ -1400,10 +1408,9 @@ class DeviceManager(object):
ip_cidrs = []
for fixed_ip in port.fixed_ips:
subnet = fixed_ip.subnet
if not ipv6_utils.is_auto_address_subnet(subnet):
net = netaddr.IPNetwork(subnet.cidr)
ip_cidr = '%s/%s' % (fixed_ip.ip_address, net.prefixlen)
ip_cidrs.append(ip_cidr)
net = netaddr.IPNetwork(subnet.cidr)
ip_cidr = '%s/%s' % (fixed_ip.ip_address, net.prefixlen)
ip_cidrs.append(ip_cidr)
if self.driver.use_gateway_ips:
# For each DHCP-enabled subnet, add that subnet's gateway

View File

@ -219,11 +219,14 @@ class LinuxInterfaceDriver(object):
return (self.DEV_NAME_PREFIX + port.id)[:self.DEV_NAME_LEN]
@staticmethod
def configure_ipv6_ra(namespace, dev_name):
"""Configure acceptance of IPv6 route advertisements on an intf."""
# Learn the default router's IP address via RAs
def configure_ipv6_ra(namespace, dev_name, value):
"""Configure handling of IPv6 Router Advertisements on an
interface. See common/constants.py for possible values.
"""
ip_lib.IPWrapper(namespace=namespace).netns.execute(
['sysctl', '-w', 'net.ipv6.conf.%s.accept_ra=2' % dev_name])
['sysctl', '-w', 'net.ipv6.conf.%(dev)s.accept_ra=%(value)s' % {
'dev': dev_name,
'value': value}])
@abc.abstractmethod
def plug_new(self, network_id, port_id, device_name, mac_address,

View File

@ -128,6 +128,18 @@ IP_ALLOWED_VERSIONS = [lib_constants.IP_VERSION_4, lib_constants.IP_VERSION_6]
PORT_RANGE_MIN = 1
PORT_RANGE_MAX = 65535
# Configuration values for accept_ra sysctl, copied from linux kernel
# networking (netdev) tree, file Documentation/networking/ip-sysctl.txt
#
# Possible values are:
# 0 Do not accept Router Advertisements.
# 1 Accept Router Advertisements if forwarding is disabled.
# 2 Overrule forwarding behaviour. Accept Router Advertisements
# even if forwarding is enabled.
ACCEPT_RA_DISABLED = 0
ACCEPT_RA_WITHOUT_FORWARDING = 1
ACCEPT_RA_WITH_FORWARDING = 2
# Some components communicate using private address ranges, define
# them all here. These address ranges should not cause any issues
# even if they overlap since they are used in disjoint namespaces,

View File

@ -166,12 +166,18 @@ class DHCPAgentOVSTestFramework(base.BaseSudoTestCase):
iface_name = self.get_interface_name(network, port)
self.assertEqual(dhcp_enabled, ovs.port_exists(iface_name))
self.assert_dhcp_namespace(network.namespace, dhcp_enabled)
self.assert_accept_ra_disabled(network.namespace)
self.assert_dhcp_device(network.namespace, iface_name, dhcp_enabled)
def assert_dhcp_namespace(self, namespace, dhcp_enabled):
ip = ip_lib.IPWrapper()
self.assertEqual(dhcp_enabled, ip.netns.exists(namespace))
def assert_accept_ra_disabled(self, namespace):
actual = ip_lib.IPWrapper(namespace=namespace).netns.execute(
['sysctl', '-b', 'net.ipv6.conf.default.accept_ra'])
self.assertEqual('0', actual)
def assert_dhcp_device(self, namespace, dhcp_iface_name, dhcp_enabled):
dev = ip_lib.IPDevice(dhcp_iface_name, namespace)
self.assertEqual(dhcp_enabled, ip_lib.device_exists(

View File

@ -1500,7 +1500,8 @@ class TestDeviceManager(base.BaseTestCase):
'device_id': mock.ANY}})])
if port == fake_ipv6_port:
expected_ips = ['169.254.169.254/16']
expected_ips = ['2001:db8::a8bb:ccff:fedd:ee99/64',
'169.254.169.254/16']
else:
expected_ips = ['172.9.9.9/24', '169.254.169.254/16']
expected = [
@ -1512,6 +1513,9 @@ class TestDeviceManager(base.BaseTestCase):
if not device_is_ready:
expected.insert(1,
mock.call.configure_ipv6_ra(net.namespace,
'default', 0))
expected.insert(2,
mock.call.plug(net.id,
port.id,
'tap12345678-12',