diff --git a/neutron/agent/linux/iptables_firewall.py b/neutron/agent/linux/iptables_firewall.py index ffe0a727290..d48bf927acd 100644 --- a/neutron/agent/linux/iptables_firewall.py +++ b/neutron/agent/linux/iptables_firewall.py @@ -775,6 +775,14 @@ def _protocol_name_map(self): if not self._iptables_protocol_name_map: tmp_map = constants.IPTABLES_PROTOCOL_NAME_MAP.copy() tmp_map.update(self._local_protocol_name_map()) + # iptables-save uses different strings for 'ipip' (protocol 4) + # depending on the distro, which corresponds to the entry for + # '4' in /etc/protocols. For example: + # - 'ipencap' in Ubuntu + # - 'ipv4' in CentOS/Fedora + # For this reason, we need to map the string for 'ipip' to the + # system-dependent string for '4', see bug #2054324. + tmp_map[constants.PROTO_NAME_IPIP] = tmp_map['4'] self._iptables_protocol_name_map = tmp_map return self._iptables_protocol_name_map diff --git a/neutron/tests/unit/agent/linux/test_iptables_firewall.py b/neutron/tests/unit/agent/linux/test_iptables_firewall.py index 89434db9660..35b1e9ba2f8 100644 --- a/neutron/tests/unit/agent/linux/test_iptables_firewall.py +++ b/neutron/tests/unit/agent/linux/test_iptables_firewall.py @@ -489,6 +489,48 @@ def test_filter_ipv4_ingress_protocol_encap_by_num(self): egress = None self._test_prepare_port_filter(rule, ingress, egress) + def test_filter_ipv4_ingress_protocol_ipip(self): + # We want to use what the system-dependent string here is for 'ipip', + # as it could be 'ipencap' or 'ipv4' depending on the distro. + # See bug #2054324. + rule = {'ethertype': 'IPv4', + 'direction': 'ingress', + 'protocol': 'ipip'} + expected_proto_name = self.firewall._iptables_protocol_name('ipip') + ingress = mock.call.add_rule('ifake_dev', + '-p %s -j RETURN' % expected_proto_name, + top=False, comment=None) + egress = None + self._test_prepare_port_filter(rule, ingress, egress) + + def test_filter_ipv4_ingress_protocol_4(self): + # We want to use what the system-dependent string here is for '4', + # as it could be 'ipencap' or 'ipv4' depending on the distro. + # See bug #2054324. + rule = {'ethertype': 'IPv4', + 'direction': 'ingress', + 'protocol': '4'} + expected_proto_name = self.firewall._iptables_protocol_name('4') + ingress = mock.call.add_rule('ifake_dev', + '-p %s -j RETURN' % expected_proto_name, + top=False, comment=None) + egress = None + self._test_prepare_port_filter(rule, ingress, egress) + + def test_filter_ipv4_ingress_protocol_94(self): + # We want to use what the system-dependent string here is for '94', + # as it could be 'ipip' or something else depending on the distro. + # See bug #2054324. + rule = {'ethertype': 'IPv4', + 'direction': 'ingress', + 'protocol': '94'} + expected_proto_name = self.firewall._iptables_protocol_name('94') + ingress = mock.call.add_rule('ifake_dev', + '-p %s -j RETURN' % expected_proto_name, + top=False, comment=None) + egress = None + self._test_prepare_port_filter(rule, ingress, egress) + def test_filter_ipv4_ingress_protocol_999_local(self): # There is no protocol 999, so let's return a mapping # that says there is and make sure the rule is created