diff --git a/doc/source/contributor/internals/openvswitch_firewall.rst b/doc/source/contributor/internals/openvswitch_firewall.rst index 90372bc7e8d..2a775f5c9ec 100644 --- a/doc/source/contributor/internals/openvswitch_firewall.rst +++ b/doc/source/contributor/internals/openvswitch_firewall.rst @@ -197,25 +197,25 @@ solicitation and neighbour advertisement. :: - table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=130 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=131 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=132 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=135 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=136 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=130 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=131 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=132 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=135 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=136 actions=NORMAL + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=130 actions=resubmit(,91) + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=131 actions=resubmit(,91) + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=132 actions=resubmit(,91) + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=135 actions=resubmit(,91) + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=136 actions=resubmit(,91) + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=130 actions=resubmit(,91) + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=131 actions=resubmit(,91) + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=132 actions=resubmit(,91) + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=135 actions=resubmit(,91) + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=136 actions=resubmit(,91) Following rules implement arp spoofing protection :: - table=71, priority=95,arp,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,arp_spa=192.168.0.1 actions=NORMAL - table=71, priority=95,arp,reg5=0x1,in_port=1,dl_src=fa:16:3e:8c:84:13,arp_spa=10.0.0.1 actions=NORMAL - table=71, priority=95,arp,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,arp_spa=192.168.0.2 actions=NORMAL - table=71, priority=95,arp,reg5=0x2,in_port=2,dl_src=fa:16:3e:8c:84:14,arp_spa=10.1.0.0/24 actions=NORMAL + table=71, priority=95,arp,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,arp_spa=192.168.0.1 actions=resubmit(,91) + table=71, priority=95,arp,reg5=0x1,in_port=1,dl_src=fa:16:3e:8c:84:13,arp_spa=10.0.0.1 actions=resubmit(,91) + table=71, priority=95,arp,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,arp_spa=192.168.0.2 actions=resubmit(,91) + table=71, priority=95,arp,reg5=0x2,in_port=2,dl_src=fa:16:3e:8c:84:14,arp_spa=10.1.0.0/24 actions=resubmit(,91) DHCP and DHCPv6 traffic is allowed to instance but DHCP servers are blocked on instances. @@ -224,12 +224,12 @@ instances. table=71, priority=80,udp,reg5=0x1,in_port=1,tp_src=68,tp_dst=67 actions=resubmit(,73) table=71, priority=80,udp6,reg5=0x1,in_port=1,tp_src=546,tp_dst=547 actions=resubmit(,73) - table=71, priority=70,udp,reg5=0x1,in_port=1,tp_src=67,tp_dst=68 actions=drop - table=71, priority=70,udp6,reg5=0x1,in_port=1,tp_src=547,tp_dst=546 actions=drop + table=71, priority=70,udp,reg5=0x1,in_port=1,tp_src=67,tp_dst=68 actions=resubmit(,93) + table=71, priority=70,udp6,reg5=0x1,in_port=1,tp_src=547,tp_dst=546 actions=resubmit(,93) table=71, priority=80,udp,reg5=0x2,in_port=2,tp_src=68,tp_dst=67 actions=resubmit(,73) table=71, priority=80,udp6,reg5=0x2,in_port=2,tp_src=546,tp_dst=547 actions=resubmit(,73) - table=71, priority=70,udp,reg5=0x2,in_port=2,tp_src=67,tp_dst=68 actions=drop - table=71, priority=70,udp6,reg5=0x2,in_port=2,tp_src=547,tp_dst=546 actions=drop + table=71, priority=70,udp,reg5=0x2,in_port=2,tp_src=67,tp_dst=68 actions=resubmit(,93) + table=71, priority=70,udp6,reg5=0x2,in_port=2,tp_src=547,tp_dst=546 actions=resubmit(,93) Flowing rules obtain conntrack information for valid ip and mac address combinations. All other packets are dropped. @@ -242,8 +242,8 @@ combinations. All other packets are dropped. 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=drop - table=71, priority=10,ct_state=-trk,reg5=0x2,in_port=2 actions=drop + 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=0 actions=drop @@ -260,7 +260,7 @@ In case below we allow all icmp egress traffic. table=72, priority=75,ct_state=+est-rel-rpl,icmp,reg5=0x1 actions=resubmit(,73) table=72, priority=75,ct_state=+new-est,icmp,reg5=0x1 actions=resubmit(,73) - table=72, priority=50,ct_state=+inv+trk actions=drop + table=72, priority=50,ct_state=+inv+trk actions=resubmit(,93) Important on the flows below is the ``ct_mark=0x1``. Such value have flows that @@ -270,18 +270,18 @@ rule was removed. :: - table=72, priority=50,ct_mark=0x1,reg5=0x1 actions=drop - table=72, priority=50,ct_mark=0x1,reg5=0x2 actions=drop + table=72, priority=50,ct_mark=0x1,reg5=0x1 actions=resubmit(,93) + table=72, priority=50,ct_mark=0x1,reg5=0x2 actions=resubmit(,93) All other connections that are not marked and are established or related are allowed. :: - table=72, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x1 actions=NORMAL - table=72, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x2 actions=NORMAL - table=72, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x1 actions=NORMAL - table=72, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x2 actions=NORMAL + table=72, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x1 actions=resubmit(,91) + table=72, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x2 actions=resubmit(,91) + table=72, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x1 actions=resubmit(,91) + table=72, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x2 actions=resubmit(,91) In the following flows are marked established connections that weren't matched in the previous flows, which means they don't have accepting security group @@ -289,9 +289,9 @@ rule anymore. :: - table=72, priority=40,ct_state=-est,reg5=0x1 actions=drop + table=72, priority=40,ct_state=-est,reg5=0x1 actions=resubmit(,93) table=72, priority=40,ct_state=+est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15],exec(load:0x1->NXM_NX_CT_MARK[])) - table=72, priority=40,ct_state=-est,reg5=0x2 actions=drop + table=72, priority=40,ct_state=-est,reg5=0x2 actions=resubmit(,93) table=72, priority=40,ct_state=+est,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15],exec(load:0x1->NXM_NX_CT_MARK[])) table=72, priority=0 actions=drop @@ -305,10 +305,10 @@ remaining egress connections are sent to normal switching. table=73, priority=100,reg6=0x284,dl_dst=fa:16:3e:8c:84:13 actions=load:0x1->NXM_NX_REG5[],resubmit(,81) table=73, priority=100,reg6=0x284,dl_dst=fa:16:3e:24:57:c7 actions=load:0x2->NXM_NX_REG5[],resubmit(,81) table=73, priority=100,reg6=0x284,dl_dst=fa:16:3e:8c:84:14 actions=load:0x2->NXM_NX_REG5[],resubmit(,81) - table=73, priority=90,ct_state=+new-est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15]),NORMAL - table=73, priority=90,ct_state=+new-est,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15]),NORMAL - table=73, priority=80,reg5=0x1 actions=NORMAL - table=73, priority=80,reg5=0x2 actions=NORMAL + table=73, priority=90,ct_state=+new-est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15]),resubmit(,91) + table=73, priority=90,ct_state=+new-est,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15]),resubmit(,91) + table=73, priority=80,reg5=0x1 actions=resubmit(,91) + table=73, priority=80,reg5=0x2 actions=resubmit(,91) table=73, priority=0 actions=drop ``table 81`` is similar to ``table 71``, allows basic ingress traffic for @@ -318,22 +318,22 @@ port. Not tracked packets are sent to obtain conntrack information. :: - table=81, priority=100,arp,reg5=0x1 actions=strip_vlan,output:1 - table=81, priority=100,arp,reg5=0x2 actions=strip_vlan,output:2 - table=81, priority=100,icmp6,reg5=0x1,icmp_type=130 actions=strip_vlan,output:1 - table=81, priority=100,icmp6,reg5=0x1,icmp_type=131 actions=strip_vlan,output:1 - table=81, priority=100,icmp6,reg5=0x1,icmp_type=132 actions=strip_vlan,output:1 - table=81, priority=100,icmp6,reg5=0x1,icmp_type=135 actions=strip_vlan,output:1 - table=81, priority=100,icmp6,reg5=0x1,icmp_type=136 actions=strip_vlan,output:1 - table=81, priority=100,icmp6,reg5=0x2,icmp_type=130 actions=strip_vlan,output:2 - table=81, priority=100,icmp6,reg5=0x2,icmp_type=131 actions=strip_vlan,output:2 - table=81, priority=100,icmp6,reg5=0x2,icmp_type=132 actions=strip_vlan,output:2 - table=81, priority=100,icmp6,reg5=0x2,icmp_type=135 actions=strip_vlan,output:2 - table=81, priority=100,icmp6,reg5=0x2,icmp_type=136 actions=strip_vlan,output:2 - table=81, priority=95,udp,reg5=0x1,tp_src=67,tp_dst=68 actions=strip_vlan,output:1 - table=81, priority=95,udp6,reg5=0x1,tp_src=547,tp_dst=546 actions=strip_vlan,output:1 - table=81, priority=95,udp,reg5=0x2,tp_src=67,tp_dst=68 actions=strip_vlan,output:2 - table=81, priority=95,udp6,reg5=0x2,tp_src=547,tp_dst=546 actions=strip_vlan,output:2 + table=81, priority=100,arp,reg5=0x1 actions=strip_vlan,output:1,resubmit(,92) + table=81, priority=100,arp,reg5=0x2 actions=strip_vlan,output:2,resubmit(,92) + table=81, priority=100,icmp6,reg5=0x1,icmp_type=130 actions=strip_vlan,output:1,resubmit(,92) + table=81, priority=100,icmp6,reg5=0x1,icmp_type=131 actions=strip_vlan,output:1,resubmit(,92) + table=81, priority=100,icmp6,reg5=0x1,icmp_type=132 actions=strip_vlan,output:1,resubmit(,92) + table=81, priority=100,icmp6,reg5=0x1,icmp_type=135 actions=strip_vlan,output:1,resubmit(,92) + table=81, priority=100,icmp6,reg5=0x1,icmp_type=136 actions=strip_vlan,output:1,resubmit(,92) + table=81, priority=100,icmp6,reg5=0x2,icmp_type=130 actions=strip_vlan,output:2,resubmit(,92) + table=81, priority=100,icmp6,reg5=0x2,icmp_type=131 actions=strip_vlan,output:2,resubmit(,92) + table=81, priority=100,icmp6,reg5=0x2,icmp_type=132 actions=strip_vlan,output:2,resubmit(,92) + table=81, priority=100,icmp6,reg5=0x2,icmp_type=135 actions=strip_vlan,output:2,resubmit(,92) + table=81, priority=100,icmp6,reg5=0x2,icmp_type=136 actions=strip_vlan,output:2,resubmit(,92) + table=81, priority=95,udp,reg5=0x1,tp_src=67,tp_dst=68 actions=strip_vlan,output:1,resubmit(,92) + table=81, priority=95,udp6,reg5=0x1,tp_src=547,tp_dst=546 actions=strip_vlan,output:1,resubmit(,92) + table=81, priority=95,udp,reg5=0x2,tp_src=67,tp_dst=68 actions=strip_vlan,output:2,resubmit(,92) + table=81, priority=95,udp6,reg5=0x2,tp_src=547,tp_dst=546 actions=strip_vlan,output:2,resubmit(,92) table=81, priority=90,ct_state=-trk,ip,reg5=0x1 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) table=81, priority=90,ct_state=-trk,ipv6,reg5=0x1 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) table=81, priority=90,ct_state=-trk,ip,reg5=0x2 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) @@ -358,9 +358,9 @@ them. table=82, priority=71,ct_state=+new-est,ip,reg6=0x284,nw_src=10.0.0.1 actions=conjunction(19,1/2) table=82, priority=71,ct_state=+est-rel-rpl,icmp,reg5=0x2 actions=conjunction(18,2/2) table=82, priority=71,ct_state=+new-est,icmp,reg5=0x2 actions=conjunction(19,2/2) - table=82, priority=71,conj_id=18,ct_state=+est-rel-rpl,ip,reg5=0x2 actions=strip_vlan,output:2 - table=82, priority=71,conj_id=19,ct_state=+new-est,ip,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15]),strip_vlan,output:2 - table=82, priority=50,ct_state=+inv+trk actions=drop + table=82, priority=71,conj_id=18,ct_state=+est-rel-rpl,ip,reg5=0x2 actions=strip_vlan,output:2,resubmit(,92) + table=82, priority=71,conj_id=19,ct_state=+new-est,ip,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15]),strip_vlan,output:2,resubmit(,92) + table=82, priority=50,ct_state=+inv+trk actions=resubmit(,93) There are some more security group rules with remote group IDs. Next we look at TCP related ones. Excerpt of flows that correspond to those @@ -425,15 +425,15 @@ same as in ``table 72``. :: - table=82, priority=50,ct_mark=0x1,reg5=0x1 actions=drop - table=82, priority=50,ct_mark=0x1,reg5=0x2 actions=drop - table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x1 actions=strip_vlan,output:1 - table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x2 actions=strip_vlan,output:2 - table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x1 actions=strip_vlan,output:1 - table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x2 actions=strip_vlan,output:2 - table=82, priority=40,ct_state=-est,reg5=0x1 actions=drop + table=82, priority=50,ct_mark=0x1,reg5=0x1 actions=resubmit(,93) + table=82, priority=50,ct_mark=0x1,reg5=0x2 actions=resubmit(,93) + table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x1 actions=strip_vlan,output:1,resubmit(,92) + table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x2 actions=strip_vlan,output:2,resubmit(,92) + table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x1 actions=strip_vlan,output:1,resubmit(,92) + table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x2 actions=strip_vlan,output:2,resubmit(,92) + table=82, priority=40,ct_state=-est,reg5=0x1 actions=resubmit(,93) table=82, priority=40,ct_state=+est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15],exec(load:0x1->NXM_NX_CT_MARK[])) - table=82, priority=40,ct_state=-est,reg5=0x2 actions=drop + table=82, priority=40,ct_state=-est,reg5=0x2 actions=resubmit(,93) table=82, priority=40,ct_state=+est,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15],exec(load:0x1->NXM_NX_CT_MARK[])) table=82, priority=0 actions=drop @@ -444,6 +444,20 @@ east-west traffic. For example, if port has a VIP that was migrated to a port on different node, then new port won't contain conntrack information about previous traffic that happened with VIP. +Using OpenFlow in conjunction with OVS firewall +----------------------------------------------- + +There are three tables where packets are sent once they get through the OVS +firewall pipeline. The tables can be used by other mechanisms using OpenFlow +that are supposed to work with the OVS firewall. Packets sent to ``table 91`` +are considered accepted by the egress pipeline and won't be processed further. +``NORMAL`` action is used by default in this table. Packets sent to +``table 92`` were processed by the ingress filtering pipeline. As packets from +the ingress filtering pipeline were injected to its destination, ``table 92`` +receives copies of those packets and therefore default action is ``drop``. +Finally, packets sent to ``table 93`` were filtered by the firewall and should +be dropped. Default action is ``drop`` in this table. + Future work ----------- diff --git a/neutron/agent/linux/openvswitch_firewall/firewall.py b/neutron/agent/linux/openvswitch_firewall/firewall.py index 1e5ccb287d6..518d26219df 100644 --- a/neutron/agent/linux/openvswitch_firewall/firewall.py +++ b/neutron/agent/linux/openvswitch_firewall/firewall.py @@ -387,6 +387,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): self.sg_to_delete = set() self._deferred = False self._drop_all_unmatched_flows() + self._initialize_third_party_tables() self.conj_ip_manager = ConjIPFlowManager(self) self.iptables_helper = iptables.Helper(self.int_br.br) @@ -438,6 +439,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_third_party_tables(self): + self.int_br.br.add_flow( + table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE, + priority=1, + actions='normal') + for table in (ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE, + ovs_consts.DROPPED_TRAFFIC_TABLE): + self.int_br.br.add_flow( + table=table, priority=0, actions='drop') + def get_ovs_port(self, port_id): ovs_port = self.int_br.br.get_vif_port_by_id(port_id) if not ovs_port: @@ -641,7 +652,8 @@ class OVSFirewallDriver(firewall.FirewallDriver): dl_type=constants.ETHERTYPE_IPV6, nw_proto=lib_const.PROTO_NUM_IPV6_ICMP, icmp_type=icmp_type, - actions='normal' + actions='resubmit(,%d)' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE) ) def _initialize_egress_no_port_security(self, port_id): @@ -675,7 +687,9 @@ class OVSFirewallDriver(firewall.FirewallDriver): table=ovs_consts.ACCEPT_OR_INGRESS_TABLE, priority=80, reg_port=ovs_port.ofport, - actions='normal' + actions='resubmit(,%d)' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE) + ) def _remove_egress_no_port_security(self, port_id): @@ -710,7 +724,8 @@ class OVSFirewallDriver(firewall.FirewallDriver): dl_src=mac_addr, dl_type=constants.ETHERTYPE_ARP, arp_spa=ip_addr, - actions='normal' + actions='resubmit(,%d)' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE) ) self._add_flow( table=ovs_consts.BASE_EGRESS_TABLE, @@ -773,7 +788,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): nw_proto=lib_const.PROTO_NUM_UDP, tp_src=src_port, tp_dst=dst_port, - actions='drop' + actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE ) # Drop Router Advertisements from instances @@ -785,7 +800,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): dl_type=constants.ETHERTYPE_IPV6, nw_proto=lib_const.PROTO_NUM_IPV6_ICMP, icmp_type=lib_const.ICMPV6_TYPE_RA, - actions='drop' + actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE ) # Drop all remaining not tracked egress connections @@ -795,7 +810,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): ct_state=ovsfw_consts.OF_STATE_NOT_TRACKED, in_port=port.ofport, reg_port=port.ofport, - actions='drop' + actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE ) # Fill in accept_or_ingress table by checking that traffic is ingress @@ -818,14 +833,17 @@ class OVSFirewallDriver(firewall.FirewallDriver): dl_type=ethertype, reg_port=port.ofport, ct_state=ovsfw_consts.OF_STATE_NEW_NOT_ESTABLISHED, - actions='ct(commit,zone=NXM_NX_REG{:d}[0..15]),normal'.format( - ovsfw_consts.REG_NET) + actions='ct(commit,zone=NXM_NX_REG{:d}[0..15]),' + 'resubmit(,{:d})'.format( + ovsfw_consts.REG_NET, + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE) ) self._add_flow( table=ovs_consts.ACCEPT_OR_INGRESS_TABLE, priority=80, reg_port=port.ofport, - actions='normal' + actions='resubmit(,%d)' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE) ) def _initialize_tracked_egress(self, port): @@ -834,7 +852,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): table=ovs_consts.RULES_EGRESS_TABLE, priority=50, ct_state=ovsfw_consts.OF_STATE_INVALID, - actions='drop' + actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE ) # Drop traffic for removed sg rules self._add_flow( @@ -842,7 +860,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): priority=50, reg_port=port.ofport, ct_mark=ovsfw_consts.CT_MARK_INVALID, - actions='drop' + actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE ) for state in ( @@ -856,14 +874,15 @@ class OVSFirewallDriver(firewall.FirewallDriver): ct_mark=ovsfw_consts.CT_MARK_NORMAL, reg_port=port.ofport, ct_zone=port.vlan_tag, - actions='normal' + actions='resubmit(,%d)' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE) ) self._add_flow( table=ovs_consts.RULES_EGRESS_TABLE, priority=40, reg_port=port.ofport, ct_state=ovsfw_consts.OF_STATE_NOT_ESTABLISHED, - actions='drop' + actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE ) for ethertype in [constants.ETHERTYPE_IP, constants.ETHERTYPE_IPV6]: self._add_flow( @@ -887,7 +906,9 @@ class OVSFirewallDriver(firewall.FirewallDriver): dl_type=constants.ETHERTYPE_IPV6, nw_proto=lib_const.PROTO_NUM_IPV6_ICMP, icmp_type=icmp_type, - actions='output:{:d}'.format(port.ofport), + actions='output:{:d},resubmit(,{:d})'.format( + port.ofport, + ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE), ) def _initialize_ingress(self, port): @@ -897,7 +918,9 @@ class OVSFirewallDriver(firewall.FirewallDriver): priority=100, dl_type=constants.ETHERTYPE_ARP, reg_port=port.ofport, - actions='output:{:d}'.format(port.ofport), + actions='output:{:d},resubmit(,{:d})'.format( + port.ofport, + ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE), ) self._initialize_ingress_ipv6_icmp(port) @@ -913,7 +936,9 @@ class OVSFirewallDriver(firewall.FirewallDriver): nw_proto=lib_const.PROTO_NUM_UDP, tp_src=src_port, tp_dst=dst_port, - actions='output:{:d}'.format(port.ofport), + actions='output:{:d},resubmit(,{:d})'.format( + port.ofport, + ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE), ) # Track untracked @@ -942,7 +967,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): table=ovs_consts.RULES_INGRESS_TABLE, priority=50, ct_state=ovsfw_consts.OF_STATE_INVALID, - actions='drop' + actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE ) # Drop traffic for removed sg rules self._add_flow( @@ -950,7 +975,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): priority=50, reg_port=port.ofport, ct_mark=ovsfw_consts.CT_MARK_INVALID, - actions='drop' + actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE ) # Allow established and related connections @@ -963,14 +988,16 @@ class OVSFirewallDriver(firewall.FirewallDriver): ct_state=state, ct_mark=ovsfw_consts.CT_MARK_NORMAL, ct_zone=port.vlan_tag, - actions='output:{:d}'.format(port.ofport) + actions='output:{:d},resubmit(,{:d})'.format( + port.ofport, + ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE) ) self._add_flow( table=ovs_consts.RULES_INGRESS_TABLE, priority=40, reg_port=port.ofport, ct_state=ovsfw_consts.OF_STATE_NOT_ESTABLISHED, - actions='drop' + actions='resubmit(,%d)' % ovs_consts.DROPPED_TRAFFIC_TABLE ) for ethertype in [constants.ETHERTYPE_IP, constants.ETHERTYPE_IPV6]: self._add_flow( diff --git a/neutron/agent/linux/openvswitch_firewall/rules.py b/neutron/agent/linux/openvswitch_firewall/rules.py index b92c3cc5ce0..5c395b0e088 100644 --- a/neutron/agent/linux/openvswitch_firewall/rules.py +++ b/neutron/agent/linux/openvswitch_firewall/rules.py @@ -202,7 +202,9 @@ def populate_flow_common(direction, flow_template, port): """Initialize common flow fields.""" if direction == firewall.INGRESS_DIRECTION: flow_template['table'] = ovs_consts.RULES_INGRESS_TABLE - flow_template['actions'] = "output:{:d}".format(port.ofport) + flow_template['actions'] = "output:{:d},resubmit(,{:d})".format( + port.ofport, + ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE) elif direction == firewall.EGRESS_DIRECTION: flow_template['table'] = ovs_consts.RULES_EGRESS_TABLE # Traffic can be both ingress and egress, check that no ingress rules diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py b/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py index 9f8bd1fcf52..949016bc023 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py @@ -71,6 +71,11 @@ OVS_FIREWALL_TABLES = ( RULES_INGRESS_TABLE, ) +# Tables for parties interacting with ovs firewall +ACCEPTED_EGRESS_TRAFFIC_TABLE = 91 +ACCEPTED_INGRESS_TRAFFIC_TABLE = 92 +DROPPED_TRAFFIC_TABLE = 93 + ## Tunnel bridge (tun_br) # Various tables for tunneling flows diff --git a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py index 07e7895a698..bbcea575962 100644 --- a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py +++ b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py @@ -513,7 +513,9 @@ class TestOVSFirewallDriver(base.BaseTestCase): table=ovs_consts.TRANSIENT_TABLE) filter_rule = mock.call( actions='ct(commit,zone=NXM_NX_REG6[0..15]),' - 'output:{:d}'.format(self.port_ofport), + 'output:{:d},resubmit(,{:d})'.format( + self.port_ofport, + ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE), dl_type="0x{:04x}".format(n_const.ETHERTYPE_IP), nw_proto=constants.PROTO_NUM_TCP, priority=77, 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 2ce65565008..35689fe3a70 100644 --- a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py +++ b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py @@ -186,7 +186,8 @@ class TestCreateProtocolFlows(base.BaseTestCase): rule = {'protocol': constants.PROTO_NUM_TCP} expected_flows = [{ 'table': ovs_consts.RULES_INGRESS_TABLE, - 'actions': 'output:1', + 'actions': 'output:1,resubmit(,%d)' % ( + ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE), 'nw_proto': constants.PROTO_NUM_TCP, }] self._test_create_protocol_flows_helper( @@ -392,7 +393,9 @@ class TestCreateConjFlows(base.BaseTestCase): flows[0]['ct_state']) self.assertEqual(ovsfw_consts.OF_STATE_NEW_NOT_ESTABLISHED, flows[1]['ct_state']) - self.assertEqual("output:{:d}".format(port.ofport), + self.assertEqual("output:{:d},resubmit(,{:d})".format( + port.ofport, + ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE), flows[0]['actions']) self.assertEqual("ct(commit,zone=NXM_NX_REG{:d}[0..15]),{:s}".format( ovsfw_consts.REG_NET, flows[0]['actions']),