From c240e5c3ac60f49888a36168d1b6ee2c45f0795d Mon Sep 17 00:00:00 2001 From: Volodymyr Litovka Date: Fri, 12 Apr 2019 07:24:36 +0000 Subject: [PATCH] Reorder classless static route (RFC3442) records Rationale: if there are Subnet1 with Host1 and Subnet2 with Host2 and Host2 serves Network2 behind it, in order to reach Network2 it is required to add Network2 to Subnet1's host_routes with Host2 as a nexthop. In this case Neutron will offer in Subnet1 the following set of RFC3442 routes: Network2 -> Host2 Subnet2_cidr -> 0.0.0.0 which will lead to fail installing Network2 route on the Host1 since at the moment of Network2's appearance there is no information about Subnet2 route. The proposed patch orders routes in such a way that 'connected' routes (0.0.0.0) will be placed first and, thus, all subsequent routes will be installed succesfully. Change-Id: Ice70eb2090e1e99c72ae51601fefd7ec5cd8867a --- neutron/agent/linux/dhcp.py | 2 +- neutron/tests/unit/agent/linux/test_dhcp.py | 58 ++++++++++----------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py index a92272f98d9..3a05c5f02c5 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -1021,7 +1021,7 @@ class Dnsmasq(DhcpLocalProcess): if (s.ip_version == 4 and s.cidr != subnet.cidr and sub_segment_id == segment_id): - host_routes.append("%s,0.0.0.0" % s.cidr) + host_routes.insert(0, "%s,0.0.0.0" % s.cidr) if host_routes: if gateway: diff --git a/neutron/tests/unit/agent/linux/test_dhcp.py b/neutron/tests/unit/agent/linux/test_dhcp.py index 6b21526eb74..1285e5b790c 100644 --- a/neutron/tests/unit/agent/linux/test_dhcp.py +++ b/neutron/tests/unit/agent/linux/test_dhcp.py @@ -1603,11 +1603,11 @@ class TestDnsmasq(TestBase): def test_output_opts_file_single_dhcp(self): expected = ( 'tag:tag0,option:dns-server,8.8.8.8\n' - 'tag:tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1,' - '169.254.169.254/32,192.168.0.1,' - '192.168.1.0/24,0.0.0.0,0.0.0.0/0,192.168.0.1\n' - 'tag:tag0,249,20.0.0.1/24,20.0.0.1,' - '169.254.169.254/32,192.168.0.1,192.168.1.0/24,0.0.0.0,' + 'tag:tag0,option:classless-static-route,192.168.1.0/24,0.0.0.0,' + '20.0.0.1/24,20.0.0.1,169.254.169.254/32,192.168.0.1,' + '0.0.0.0/0,192.168.0.1\n' + 'tag:tag0,249,192.168.1.0/24,0.0.0.0,' + '20.0.0.1/24,20.0.0.1,169.254.169.254/32,192.168.0.1,' '0.0.0.0/0,192.168.0.1\n' 'tag:tag0,option:router,192.168.0.1').lstrip() @@ -1628,19 +1628,18 @@ class TestDnsmasq(TestBase): def test_output_opts_file_dual_dhcp_rfc3442(self): expected = ( 'tag:tag0,option:dns-server,8.8.8.8\n' - 'tag:tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1,' - '169.254.169.254/32,192.168.0.1,' - '192.168.1.0/24,0.0.0.0,0.0.0.0/0,192.168.0.1\n' - 'tag:tag0,249,20.0.0.1/24,20.0.0.1,' - '169.254.169.254/32,192.168.0.1,192.168.1.0/24,0.0.0.0,' + 'tag:tag0,option:classless-static-route,192.168.1.0/24,0.0.0.0,' + '20.0.0.1/24,20.0.0.1,169.254.169.254/32,192.168.0.1,' + '0.0.0.0/0,192.168.0.1\n' + 'tag:tag0,249,192.168.1.0/24,0.0.0.0,' + '20.0.0.1/24,20.0.0.1,169.254.169.254/32,192.168.0.1,' '0.0.0.0/0,192.168.0.1\n' 'tag:tag0,option:router,192.168.0.1\n' 'tag:tag1,option:dns-server,8.8.8.8\n' - 'tag:tag1,option:classless-static-route,' - '169.254.169.254/32,192.168.1.1,' - '192.168.0.0/24,0.0.0.0,0.0.0.0/0,192.168.1.1\n' - 'tag:tag1,249,169.254.169.254/32,192.168.1.1,' - '192.168.0.0/24,0.0.0.0,0.0.0.0/0,192.168.1.1\n' + 'tag:tag1,option:classless-static-route,192.168.0.0/24,0.0.0.0,' + '169.254.169.254/32,192.168.1.1,0.0.0.0/0,192.168.1.1\n' + 'tag:tag1,249,192.168.0.0/24,0.0.0.0,' + '169.254.169.254/32,192.168.1.1,0.0.0.0/0,192.168.1.1\n' 'tag:tag1,option:router,192.168.1.1').lstrip() self._test_output_opts_file(expected, FakeDualNetworkDualDHCP()) @@ -1666,19 +1665,18 @@ class TestDnsmasq(TestBase): def test_output_opts_file_dual_dhcp_rfc3442_one_on_link_subnet_route(self): expected = ( 'tag:tag0,option:dns-server,8.8.8.8\n' - 'tag:tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1,' - '169.254.169.254/32,192.168.0.1,' - '192.168.1.0/24,0.0.0.0,0.0.0.0/0,192.168.0.1\n' - 'tag:tag0,249,20.0.0.1/24,20.0.0.1,' - '169.254.169.254/32,192.168.0.1,192.168.1.0/24,0.0.0.0,' + 'tag:tag0,option:classless-static-route,192.168.1.0/24,0.0.0.0,' + '20.0.0.1/24,20.0.0.1,169.254.169.254/32,192.168.0.1,' + '0.0.0.0/0,192.168.0.1\n' + 'tag:tag0,249,192.168.1.0/24,0.0.0.0,' + '20.0.0.1/24,20.0.0.1,169.254.169.254/32,192.168.0.1,' '0.0.0.0/0,192.168.0.1\n' 'tag:tag0,option:router,192.168.0.1\n' 'tag:tag1,option:dns-server,8.8.8.8\n' - 'tag:tag1,option:classless-static-route,' - '169.254.169.254/32,192.168.1.1,' - '192.168.0.0/24,0.0.0.0,0.0.0.0/0,192.168.1.1\n' - 'tag:tag1,249,169.254.169.254/32,192.168.1.1,' - '192.168.0.0/24,0.0.0.0,0.0.0.0/0,192.168.1.1\n' + 'tag:tag1,option:classless-static-route,192.168.0.0/24,0.0.0.0,' + '169.254.169.254/32,192.168.1.1,0.0.0.0/0,192.168.1.1\n' + 'tag:tag1,249,192.168.0.0/24,0.0.0.0,' + '169.254.169.254/32,192.168.1.1,0.0.0.0/0,192.168.1.1\n' 'tag:tag1,option:router,192.168.1.1\n' 'tag:tag2,option:dns-server,8.8.8.8\n' 'tag:tag2,option:classless-static-route,' @@ -1793,11 +1791,11 @@ class TestDnsmasq(TestBase): def test_output_opts_file_pxe_3port_2net(self): expected = ( 'tag:tag0,option:dns-server,8.8.8.8\n' - 'tag:tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1,' - '169.254.169.254/32,192.168.0.1,' - '192.168.1.0/24,0.0.0.0,0.0.0.0/0,192.168.0.1\n' - 'tag:tag0,249,20.0.0.1/24,20.0.0.1,' - '169.254.169.254/32,192.168.0.1,192.168.1.0/24,0.0.0.0,' + 'tag:tag0,option:classless-static-route,192.168.1.0/24,0.0.0.0,' + '20.0.0.1/24,20.0.0.1,169.254.169.254/32,192.168.0.1,' + '0.0.0.0/0,192.168.0.1\n' + 'tag:tag0,249,192.168.1.0/24,0.0.0.0,' + '20.0.0.1/24,20.0.0.1,169.254.169.254/32,192.168.0.1,' '0.0.0.0/0,192.168.0.1\n' 'tag:tag0,option:router,192.168.0.1\n' 'tag:eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee,'