Disable 'accept_ra' in DHCP agent namespace
Currently the DHCP agent relies on the acceptance of an RA to configure its IPv6 address with SLAAC or DHCPv6-stateless network modes. It should explicitly assign addresses to the agent based on the data model instead. In order to do this we must disable RAs in the namespace so that a static assignment doesn't conflict with a previously created dynamically-generated address. Change-Id: I1b38d131249d59fa486a07024d4b1ec61e693d59 Related-bug: #1627902
This commit is contained in:
parent
97f4a3fdbb
commit
904f85e2f9
|
@ -626,7 +626,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):
|
||||
|
|
|
@ -40,7 +40,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
|
||||
|
@ -1347,6 +1346,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,
|
||||
|
@ -1383,10 +1391,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
|
||||
|
|
|
@ -213,10 +213,12 @@ 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
|
||||
cmd = ['net.ipv6.conf.%s.accept_ra=2' % dev_name]
|
||||
def configure_ipv6_ra(namespace, dev_name, value):
|
||||
"""Configure handling of IPv6 Router Advertisements on an
|
||||
interface. See common/constants.py for possible values.
|
||||
"""
|
||||
cmd = ['net.ipv6.conf.%(dev)s.accept_ra=%(value)s' % {'dev': dev_name,
|
||||
'value': value}]
|
||||
ip_lib.sysctl(cmd, namespace=namespace)
|
||||
|
||||
@abc.abstractmethod
|
||||
|
|
|
@ -126,6 +126,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,
|
||||
|
|
|
@ -161,12 +161,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(
|
||||
|
|
|
@ -1444,7 +1444,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 = [
|
||||
|
@ -1456,6 +1457,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',
|
||||
|
|
Loading…
Reference in New Issue