From b82db0a9f24e16f426d9f693b7971bef4e080a7f Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Thu, 3 Aug 2017 15:36:33 +0900 Subject: [PATCH] ovsfw: Fix up port_range and ICMP type/code handling port_range_min/max should be read as ICMP type/code for ICMP(V6). Change-Id: I65157037038d11464902c0311eb4c54b84f60c72 Closes-bug: #1708358 --- .../agent/linux/openvswitch_firewall/rules.py | 18 ++++++++++- .../linux/openvswitch_firewall/test_rules.py | 31 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/neutron/agent/linux/openvswitch_firewall/rules.py b/neutron/agent/linux/openvswitch_firewall/rules.py index e2c96aac9c4..930984f7681 100644 --- a/neutron/agent/linux/openvswitch_firewall/rules.py +++ b/neutron/agent/linux/openvswitch_firewall/rules.py @@ -95,7 +95,10 @@ def create_protocol_flows(direction, flow_template, port, rule): if protocol is not None: flow_template['nw_proto'] = protocol - flows = create_port_range_flows(flow_template, rule) + if protocol in [n_consts.PROTO_NUM_ICMP, n_consts.PROTO_NUM_IPV6_ICMP]: + flows = create_icmp_flows(flow_template, rule) + else: + flows = create_port_range_flows(flow_template, rule) return flows or [flow_template] @@ -138,6 +141,19 @@ def create_port_range_flows(flow_template, rule): return flows +def create_icmp_flows(flow_template, rule): + icmp_type = rule.get('port_range_min') + if icmp_type is None: + return + flow = flow_template.copy() + flow['icmp_type'] = icmp_type + + icmp_code = rule.get('port_range_max') + if icmp_code is not None: + flow['icmp_code'] = icmp_code + return [flow] + + def create_flows_for_ip_address(ip_address, direction, ethertype, vlan_tag, conj_ids): """Create flows from a rule and an ip_address derived from diff --git a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py index ce40ed6a9bf..9c145bdb5b7 100644 --- a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py +++ b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py @@ -240,6 +240,36 @@ class TestCreateProtocolFlows(base.BaseTestCase): self._test_create_protocol_flows_helper( firewall.EGRESS_DIRECTION, rule, expected_flows) + def test_create_protocol_flows_icmp(self): + rule = {'ethertype': constants.IPv4, + 'protocol': constants.PROTO_NUM_ICMP, + 'port_range_min': 0} + expected_flows = [{ + 'table': ovs_consts.RULES_EGRESS_TABLE, + 'actions': 'resubmit(,{:d})'.format( + ovs_consts.ACCEPT_OR_INGRESS_TABLE), + 'nw_proto': constants.PROTO_NUM_ICMP, + 'icmp_type': 0 + }] + self._test_create_protocol_flows_helper( + firewall.EGRESS_DIRECTION, rule, expected_flows) + + def test_create_protocol_flows_ipv6_icmp(self): + rule = {'ethertype': constants.IPv6, + 'protocol': constants.PROTO_NUM_IPV6_ICMP, + 'port_range_min': 5, + 'port_range_max': 0} + expected_flows = [{ + 'table': ovs_consts.RULES_EGRESS_TABLE, + 'actions': 'resubmit(,{:d})'.format( + ovs_consts.ACCEPT_OR_INGRESS_TABLE), + 'nw_proto': constants.PROTO_NUM_IPV6_ICMP, + 'icmp_type': 5, + 'icmp_code': 0, + }] + self._test_create_protocol_flows_helper( + firewall.EGRESS_DIRECTION, rule, expected_flows) + class TestCreatePortRangeFlows(base.BaseTestCase): def _test_create_port_range_flows_helper(self, expected_flows, rule): @@ -294,6 +324,7 @@ class TestCreatePortRangeFlows(base.BaseTestCase): self._test_create_port_range_flows_helper(expected_flows, rule) def test_create_port_range_with_icmp_protocol(self): + # NOTE: such call is prevented by create_protocols_flows rule = { 'protocol': constants.PROTO_NUM_ICMP, 'port_range_min': 10,