]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Provide routes for neighbor IPv4 subnets
authorAlexey I. Froloff <raorn@raorn.name>
Tue, 30 Sep 2014 13:01:15 +0000 (17:01 +0400)
committerAlexey I. Froloff <raorn@raorn.name>
Tue, 10 Feb 2015 14:38:09 +0000 (17:38 +0300)
Network may contain several Subnets.  In this case all these subnets are
accessible via same link and two VMs with addresses from different
Subnets may talk to each other directly, bypassing default router.  For
this to work, "neighbour Subnets" should have entry in VM's routing
tables.  RFC3442 describes this situation:

   In some cases more than one IP subnet may be configured on a link.
   In such cases, a host whose IP address is in one IP subnet in the
   link could communicate directly with a host whose IP address is in a
   different IP subnet on the same link. In cases where a client is
   being assigned an IP address on an IP subnet on such a link, for each
   IP subnet in the link other than the IP subnet on which the client
   has been assigned the DHCP server MAY be configured to specify a
   router IP address of 0.0.0.0.

When network contains more that one IPv4 subnets, report these subnets
in 'classless-static-routes' DHCP option.

DocImpact

Change-Id: Ifcf1d99e0f0136bf52b8d13675b7ccfd48005fab
Closes-Bug: #1372885

neutron/agent/linux/dhcp.py
neutron/tests/unit/test_linux_dhcp.py

index 3b8da5fd4e8653b33293ce60c5700673dcb5a451..bd96fd3a1cae996f37ffdb2d977beea0f353aeba 100644 (file)
@@ -610,6 +610,11 @@ class Dnsmasq(DhcpLocalProcess):
                 )
 
             if subnet.ip_version == 4:
+                host_routes.extend(["%s,0.0.0.0" % (s.cidr) for s in
+                                    self.network.subnets
+                                    if (s.ip_version == 4 and
+                                        s.cidr != subnet.cidr)])
+
                 if host_routes:
                     if gateway:
                         host_routes.append("%s,%s" % ("0.0.0.0/0", gateway))
index 95cd838968b5d2185bc3e9452b6f3ac32458bfcc..f5e7b629aaface441f22f5bde7d7cbdf4b860bfd 100644 (file)
@@ -154,6 +154,18 @@ class FakeRouterPort(object):
             ip_address, 'dddddddd-dddd-dddd-dddd-dddddddddddd')]
 
 
+class FakeRouterPort2(object):
+    id = 'rrrrrrrr-rrrr-rrrr-rrrr-rrrrrrrrrrrr'
+    admin_state_up = True
+    device_owner = constants.DEVICE_OWNER_ROUTER_INTF
+    fixed_ips = [FakeIPAllocation('192.168.1.1',
+                                  'dddddddd-dddd-dddd-dddd-dddddddddddd')]
+    mac_address = '00:00:0f:rr:rr:r2'
+
+    def __init__(self):
+        self.extra_dhcp_opts = []
+
+
 class FakePortMultipleAgents1(object):
     id = 'rrrrrrrr-rrrr-rrrr-rrrr-rrrrrrrrrrrr'
     admin_state_up = True
@@ -203,6 +215,16 @@ class FakeV4Subnet(object):
     dns_nameservers = ['8.8.8.8']
 
 
+class FakeV4Subnet2(object):
+    id = 'dddddddd-dddd-dddd-dddd-dddddddddddd'
+    ip_version = 4
+    cidr = '192.168.1.0/24'
+    gateway_ip = '192.168.1.1'
+    enable_dhcp = True
+    host_routes = []
+    dns_nameservers = ['8.8.8.8']
+
+
 class FakeV4MetadataSubnet(object):
     id = 'dddddddd-dddd-dddd-dddd-dddddddddddd'
     ip_version = 4
@@ -371,6 +393,13 @@ class FakeDualNetworkSingleDHCP(object):
     namespace = 'qdhcp-ns'
 
 
+class FakeDualNetworkDualDHCP(object):
+    id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
+    subnets = [FakeV4Subnet(), FakeV4Subnet2()]
+    ports = [FakePort1(), FakeRouterPort(), FakeRouterPort2()]
+    namespace = 'qdhcp-ns'
+
+
 class FakeV4NoGatewayNetwork(object):
     id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
     subnets = [FakeV4SubnetNoGateway()]
@@ -959,12 +988,29 @@ class TestDnsmasq(TestBase):
         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,'
+            '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,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,0.0.0.0/0,192.168.0.1\n'
             'tag:tag0,option:router,192.168.0.1').lstrip()
 
         self._test_output_opts_file(expected, FakeDualNetworkSingleDHCP())
 
+    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,'
+            '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,192.168.1.0/24,0.0.0.0,'
+            '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,192.168.0.0/24,0.0.0.0,'
+            '0.0.0.0/0,192.168.1.1\n'
+            'tag:tag1,249,192.168.0.0/24,0.0.0.0,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())
+
     def test_output_opts_file_no_gateway(self):
         expected = (
             'tag:tag0,option:classless-static-route,'
@@ -1049,8 +1095,9 @@ class TestDnsmasq(TestBase):
         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,'
+            '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,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,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,'
             'option:tftp-server,192.168.0.3\n'