]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Always fill UDP checksums in DHCP replies
authorDarragh O'Reilly <darragh.oreilly@hp.com>
Tue, 3 Feb 2015 17:03:23 +0000 (17:03 +0000)
committerDarragh O'Reilly <darragh.oreilly@hp.com>
Thu, 26 Feb 2015 08:30:44 +0000 (08:30 +0000)
In some cases the UDP checksums in packets from DHCP servers are
incorrect. This is a problem for some DHCP clients that ignore
packets with bad checksums. This patch inserts an iptables rule
to ensure DHCP servers always send packets with correct checksums.

Change-Id: I130fe0f2389bdc42eb8c858ea35dd840abecc2e7
Closes-Bug: 1244589

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

index 2d97f3bc7615add430d058f25d50ccabb02f1c55..457d9190880ffef1dc298c6fdb76deac9a03a53b 100644 (file)
@@ -24,6 +24,7 @@ from oslo_utils import importutils
 import six
 
 from neutron.agent.linux import ip_lib
+from neutron.agent.linux import iptables_manager
 from neutron.agent.linux import utils
 from neutron.common import constants
 from neutron.common import exceptions
@@ -925,6 +926,7 @@ class DeviceManager(object):
                              interface_name,
                              port.mac_address,
                              namespace=network.namespace)
+            self.fill_dhcp_udp_checksums(namespace=network.namespace)
         ip_cidrs = []
         for fixed_ip in port.fixed_ips:
             subnet = fixed_ip.subnet
@@ -961,3 +963,12 @@ class DeviceManager(object):
 
         self.plugin.release_dhcp_port(network.id,
                                       self.get_device_id(network))
+
+    def fill_dhcp_udp_checksums(self, namespace):
+        """Ensure DHCP reply packets always have correct UDP checksums."""
+        iptables_mgr = iptables_manager.IptablesManager(use_ipv6=False,
+                                                        namespace=namespace)
+        ipv4_rule = ('-p udp --dport %d -j CHECKSUM --checksum-fill'
+                     % constants.DHCP_RESPONSE_PORT)
+        iptables_mgr.ipv4['mangle'].add_rule('POSTROUTING', ipv4_rule)
+        iptables_mgr.apply()
index 5e100e188b9b1f49b46cd36b3f1627e483b75030..b8402def66aa50c58432a9ac11e900b3b879caca 100644 (file)
@@ -1173,6 +1173,14 @@ class TestDeviceManager(base.BaseTestCase):
         driver_cls.return_value = self.mock_driver
         iproute_cls.return_value = self.mock_iproute
 
+        iptables_cls_p = mock.patch(
+            'neutron.agent.linux.iptables_manager.IptablesManager')
+        iptables_cls = iptables_cls_p.start()
+        self.iptables_inst = mock.Mock()
+        iptables_cls.return_value = self.iptables_inst
+        self.mangle_inst = mock.Mock()
+        self.iptables_inst.ipv4 = {'mangle': self.mangle_inst}
+
     def _test_setup_helper(self, device_is_ready, net=None, port=None):
         net = net or fake_network
         port = port or fake_port1
@@ -1224,6 +1232,13 @@ class TestDeviceManager(base.BaseTestCase):
         cfg.CONF.set_override('enable_metadata_network', True)
         self._test_setup_helper(False)
 
+    def test_setup_calls_fill_dhcp_udp_checksums(self):
+        self._test_setup_helper(False)
+        rule = ('-p udp --dport %d -j CHECKSUM --checksum-fill'
+                % const.DHCP_RESPONSE_PORT)
+        expected = [mock.call.add_rule('POSTROUTING', rule)]
+        self.mangle_inst.assert_has_calls(expected)
+
     def test_setup_ipv6(self):
         self._test_setup_helper(True, net=fake_network_ipv6,
                                 port=fake_ipv6_port)