Always fill UDP checksums in DHCP replies

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
This commit is contained in:
Darragh O'Reilly 2015-02-03 17:03:23 +00:00
parent eb1167d3f9
commit f5419d9079
2 changed files with 26 additions and 0 deletions

View 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()

View 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)