Do not respond to ARP on IPv6-only interfaces
When using dual stack, the IPv6 router interface responds to ARP requests that only the IPv4 interface should. This results in ARP flux and can cause a guest to address packets to the wrong layer-2 address when sending traffic to the IPv4 gateway. Change arp_ignore and arp_announce sysctl options on interfaces in the router namespace to be more strict in how we respond. Closes-bug: 1692007 Change-Id: Ic3c2370995abb027a3412b473ce6bc63790c1105
This commit is contained in:
parent
e4557a7793
commit
0f076cfc2d
neutron
@ -90,9 +90,19 @@ class Namespace(object):
|
||||
self.use_ipv6 = use_ipv6
|
||||
|
||||
def create(self):
|
||||
# See networking (netdev) tree, file
|
||||
# Documentation/networking/ip-sysctl.txt for an explanation of
|
||||
# these sysctl values.
|
||||
ip_wrapper = self.ip_wrapper_root.ensure_namespace(self.name)
|
||||
cmd = ['sysctl', '-w', 'net.ipv4.ip_forward=1']
|
||||
ip_wrapper.netns.execute(cmd)
|
||||
# 1. Reply only if the target IP address is local address configured
|
||||
# on the incoming interface; and
|
||||
# 2. Always use the best local address
|
||||
cmd = ['sysctl', '-w', 'net.ipv4.conf.all.arp_ignore=1']
|
||||
ip_wrapper.netns.execute(cmd)
|
||||
cmd = ['sysctl', '-w', 'net.ipv4.conf.all.arp_announce=2']
|
||||
ip_wrapper.netns.execute(cmd)
|
||||
if self.use_ipv6:
|
||||
cmd = ['sysctl', '-w', 'net.ipv6.conf.all.forwarding=1']
|
||||
ip_wrapper.netns.execute(cmd)
|
||||
|
@ -2105,6 +2105,23 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||
agent.router_added_to_agent(None, [FAKE_ID])
|
||||
self.assertEqual(1, agent._queue.add.call_count)
|
||||
|
||||
def test_create_router_namespace(self):
|
||||
self.mock_ip.ensure_namespace.return_value = self.mock_ip
|
||||
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
|
||||
ns = namespaces.Namespace(
|
||||
'qrouter-bar', self.conf, agent.driver, agent.use_ipv6)
|
||||
ns.create()
|
||||
|
||||
calls = [mock.call(['sysctl', '-w', 'net.ipv4.ip_forward=1']),
|
||||
mock.call(['sysctl', '-w', 'net.ipv4.conf.all.arp_ignore=1']),
|
||||
mock.call(
|
||||
['sysctl', '-w', 'net.ipv4.conf.all.arp_announce=2'])]
|
||||
if agent.use_ipv6:
|
||||
calls.append(mock.call(
|
||||
['sysctl', '-w', 'net.ipv6.conf.all.forwarding=1']))
|
||||
|
||||
self.mock_ip.netns.execute.assert_has_calls(calls)
|
||||
|
||||
def test_destroy_namespace(self):
|
||||
namespace = 'qrouter-bar'
|
||||
|
||||
|
@ -191,9 +191,9 @@ class TestDvrFipNs(base.BaseTestCase):
|
||||
@mock.patch.object(ip_lib.IpNetnsCommand, 'exists')
|
||||
def _test_create(self, old_kernel, exists, execute, IPTables):
|
||||
exists.return_value = True
|
||||
# There are up to four sysctl calls - two to enable forwarding,
|
||||
# and two for ip_nonlocal_bind
|
||||
execute.side_effect = [None, None,
|
||||
# There are up to six sysctl calls - two to enable forwarding,
|
||||
# two for arp_ignore and arp_announce, and two for ip_nonlocal_bind
|
||||
execute.side_effect = [None, None, None, None,
|
||||
RuntimeError if old_kernel else None, None]
|
||||
|
||||
self.fip_ns._iptables_manager = IPTables()
|
||||
|
Loading…
x
Reference in New Issue
Block a user