Merge "ovs-fw: Clear conntrack information before egress pipeline"

This commit is contained in:
Zuul 2018-03-17 00:38:08 +00:00 committed by Gerrit Code Review
commit ade1c606a9
3 changed files with 57 additions and 13 deletions

View File

@ -192,6 +192,15 @@ information from conntrack. It says every port has its own conntrack zone
defined by value in ``register 6``. It's there to avoid accepting established
traffic that belongs to different port with same conntrack parameters.
The very first rule in ``table 71`` is a rule removing conntrack information
for a use-case where Neutron logical port is placed directly to the hypervisor.
In such case kernel does conntrack lookup before packet reaches Open vSwitch
bridge. Tracked packets are sent back for processing by the same table after
conntrack information is cleared.
::
table=71, priority=110,ct_state=+trk actions=ct_clear,resubmit(,71)
Rules below allow ICMPv6 traffic for multicast listeners, neighbour
solicitation and neighbour advertisement.
@ -236,14 +245,14 @@ combinations. All other packets are dropped.
::
table=71, priority=65,ct_state=-trk,ip,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,nw_src=192.168.0.1 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ct_state=-trk,ip,reg5=0x1,in_port=1,dl_src=fa:16:3e:8c:84:13,nw_src=10.0.0.1 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ct_state=-trk,ip,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,nw_src=192.168.0.2 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ct_state=-trk,ip,reg5=0x2,in_port=2,dl_src=fa:16:3e:8c:84:14,nw_src=10.1.0.0/24 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ct_state=-trk,ipv6,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,ipv6_src=fe80::f816:3eff:fea4:2210 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ct_state=-trk,ipv6,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,ipv6_src=fe80::f816:3eff:fe24:57c7 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=10,ct_state=-trk,reg5=0x1,in_port=1 actions=resubmit(,93)
table=71, priority=10,ct_state=-trk,reg5=0x2,in_port=2 actions=resubmit(,93)
table=71, priority=65,ip,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,nw_src=192.168.0.1 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ip,reg5=0x1,in_port=1,dl_src=fa:16:3e:8c:84:13,nw_src=10.0.0.1 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ip,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,nw_src=192.168.0.2 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ip,reg5=0x2,in_port=2,dl_src=fa:16:3e:8c:84:14,nw_src=10.1.0.0/24 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ipv6,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,ipv6_src=fe80::f816:3eff:fea4:2210 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ipv6,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,ipv6_src=fe80::f816:3eff:fe24:57c7 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=10,reg5=0x1,in_port=1 actions=resubmit(,93)
table=71, priority=10,reg5=0x2,in_port=2 actions=resubmit(,93)
table=71, priority=0 actions=drop

View File

@ -395,6 +395,7 @@ class OVSFirewallDriver(firewall.FirewallDriver):
self.sg_to_delete = set()
self._deferred = False
self._drop_all_unmatched_flows()
self._initialize_common_flows()
self._initialize_third_party_tables()
self.conj_ip_manager = ConjIPFlowManager(self)
@ -447,6 +448,16 @@ class OVSFirewallDriver(firewall.FirewallDriver):
for table in ovs_consts.OVS_FIREWALL_TABLES:
self.int_br.br.add_flow(table=table, priority=0, actions='drop')
def _initialize_common_flows(self):
# Remove conntrack information from tracked packets
self._add_flow(
table=ovs_consts.BASE_EGRESS_TABLE,
priority=110,
ct_state=ovsfw_consts.OF_STATE_TRACKED,
actions='ct_clear,'
'resubmit(,%d)' % ovs_consts.BASE_EGRESS_TABLE,
)
def _initialize_third_party_tables(self):
self.int_br.br.add_flow(
table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE,
@ -744,7 +755,6 @@ class OVSFirewallDriver(firewall.FirewallDriver):
table=ovs_consts.BASE_EGRESS_TABLE,
priority=65,
reg_port=port.ofport,
ct_state=ovsfw_consts.OF_STATE_NOT_TRACKED,
dl_type=constants.ETHERTYPE_IP,
in_port=port.ofport,
dl_src=mac_addr,
@ -763,7 +773,6 @@ class OVSFirewallDriver(firewall.FirewallDriver):
priority=65,
reg_port=port.ofport,
in_port=port.ofport,
ct_state=ovsfw_consts.OF_STATE_NOT_TRACKED,
dl_type=constants.ETHERTYPE_IPV6,
dl_src=mac_addr,
ipv6_src=ip_addr,
@ -816,14 +825,14 @@ class OVSFirewallDriver(firewall.FirewallDriver):
actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE
)
# Drop all remaining not tracked egress connections
# Drop all remaining egress connections
self._add_flow(
table=ovs_consts.BASE_EGRESS_TABLE,
priority=10,
ct_state=ovsfw_consts.OF_STATE_NOT_TRACKED,
in_port=port.ofport,
reg_port=port.ofport,
actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE
actions='ct_clear,'
'resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE
)
# Fill in accept_or_ingress table by checking that traffic is ingress

View File

@ -29,6 +29,7 @@ import testscenarios
from neutron.agent.linux import iptables_firewall
from neutron.agent.linux import openvswitch_firewall
from neutron.agent.linux.openvswitch_firewall import constants as ovsfw_consts
from neutron.cmd.sanity import checks
from neutron.common import constants as n_const
from neutron.conf.agent import securitygroups_rpc as security_config
@ -628,6 +629,31 @@ class FirewallTestCase(BaseFirewallTestCase):
self.tester.assert_net_unreachable(self.tester.EGRESS, '1.2.3.4')
@skip_if_firewall('iptables')
def test_tracked_connection(self):
# put an openflow rule to perform a CT lookup and hence packet will
# carry conntrack information
self.tester.bridge.add_flow(
table=0,
priority=200,
dl_type="0x0800",
ct_state=ovsfw_consts.OF_STATE_NOT_TRACKED,
actions="ct(table=0)"
)
# update the sg_group to make ping pass
sg_rules = [{'ethertype': constants.IPv4,
'direction': constants.INGRESS_DIRECTION,
'protocol': constants.PROTO_NAME_ICMP},
{'ethertype': constants.IPv4,
'direction': constants.EGRESS_DIRECTION}]
self.tester.assert_no_connection(protocol=self.tester.ICMP,
direction=self.tester.INGRESS)
self._apply_security_group_rules(self.FAKE_SECURITY_GROUP_ID, sg_rules)
self.tester.assert_connection(protocol=self.tester.ICMP,
direction=self.tester.INGRESS)
class FirewallTestCaseIPv6(BaseFirewallTestCase):
scenarios = BaseFirewallTestCase.scenarios_ovs_fw_interfaces