From: shylou <[email protected]>

By default, OVN skips the conntrack process for router type
LSP within a LS. It seems unnecessary for the LSP whose peer
is l3dgw_port.

Therefore, we introduce an option named 'enable_router_port_acl',
which defaults to false and can be set to true to enable
conntrack for the LSP whose peer is l3dgw_port.

And then we can implement a gateway stateful firewall by
dgw with stateful ACL. For example:

 prelude: R1-S1 is a l3dgw_port
 ovn-nbctl pg-add pg_dgw
 ovn-nbctl pg-set-ports pg_dgw S1-R1
 ovn-nbctl acl-add pg_dgw from-lport 1002 "inport == @pg_dgw && ip4" 
allow-related
 ovn-nbctl acl-add pg_dgw to-lport 1003 "outport == @pg_dgw && ip4" 
allow-related
 ovn-nbctl lsp-set-options S1-R1 router-port=R1-S1 enable_router_port_acl=true

NOTE: this option only works for the LSP whose peer is l3dgw_port.

Submitted-at: https://github.com/ovn-org/ovn/pull/226
Signed-off-by: Xie Liu <[email protected]>
Acked-by: Dumitru Ceara <[email protected]>
Signed-off-by: Numan Siddique <[email protected]>
---
 NEWS                    |   2 +
 northd/northd.c         |  15 ++++-
 northd/ovn-northd.8.xml |   7 ++-
 ovn-nb.xml              |   8 +++
 tests/ovn-northd.at     | 124 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 154 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index 20df92cb76..5f267b4c64 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,8 @@ Post v23.09.0
   - Support CIDR based MAC binding aging threshold. See ovn-nb(5) for
     'mac_binding_age_threshold' for more details.
   - ovn-northd-ddlog has been removed.
+  - A new LSP option "enable_router_port_acl" has been added to enable
+    conntrack for the router port whose peer is l3dgw_port if set it true.
 
 OVN v23.09.0 - 15 Sep 2023
 --------------------------
diff --git a/northd/northd.c b/northd/northd.c
index db3cd272e1..952f8200d4 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -1612,6 +1612,9 @@ struct ovn_port {
      * access it from any other nodes.
      */
     struct ovs_list lflows;
+
+    /* Only used for the router type LSP whose peer is l3dgw_port */
+    bool enable_router_port_acl;
 };
 
 static bool lsp_can_be_inc_processed(const struct nbrec_logical_switch_port *);
@@ -2826,6 +2829,12 @@ join_logical_ports(const struct sbrec_port_binding_table 
*sbrec_pb_table,
                         arp_proxy, op->nbsp->name);
                 }
             }
+
+            /* Only used for the router type LSP whose peer is l3dgw_port */
+            if (op->peer && is_l3dgw_port(op->peer)) {
+                op->enable_router_port_acl = smap_get_bool(
+                    &op->nbsp->options, "enable_router_port_acl", false);
+            }
         } else if (op->nbrp && op->nbrp->peer && !op->l3dgw_port) {
             struct ovn_port *peer = ovn_port_find(ports, op->nbrp->peer);
             if (peer) {
@@ -7207,7 +7216,11 @@ build_pre_acls(struct ovn_datapath *od,
      * which handles defragmentation, in order to match L4 headers. */
     if (od->has_stateful_acl) {
         for (size_t i = 0; i < od->n_router_ports; i++) {
-            skip_port_from_conntrack(od, od->router_ports[i],
+            struct ovn_port *op = od->router_ports[i];
+            if (op->enable_router_port_acl) {
+                continue;
+            }
+            skip_port_from_conntrack(od, op,
                                      S_SWITCH_IN_PRE_ACL, S_SWITCH_OUT_PRE_ACL,
                                      110, lflows);
         }
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index 98cf7adb43..f1eb9ecb1b 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -438,7 +438,12 @@
       <code>Pre-stateful</code> to send IP packets to the connection tracker
       before eventually advancing to ingress table <code>ACLs</code>. If
       special ports such as route ports or localnet ports can't use ct(), a
-      priority-110 flow is added to skip over stateful ACLs. Multicast, IPv6
+      priority-110 flow is added to skip over stateful ACLs.  This
+      priority-110 flow is not addd for router ports if the option
+      enable_router_port_acl is set to true in
+      <ref column="options:enable_router_port_acl"
+      table="Logical_Switch_Port" db="OVN_Northbound"/> column of
+      <ref table="Logical_Switch_Port" db="OVN_Northbound"/>.  Multicast, IPv6
       Neighbor Discovery and MLD traffic also skips stateful ACLs. For
       "allow-stateless" ACLs, a flow is added to bypass setting the hint for
       connection tracker processing when there are stateful ACLs or LB rules;
diff --git a/ovn-nb.xml b/ovn-nb.xml
index b2913bdd7a..765ffcf2e6 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -1107,6 +1107,14 @@
           should have a route to forward packets sent to configured proxy ARP
           MAC/IPs to an appropriate destination.
         </column>
+
+        <column name="options" key="enable_router_port_acl"
+                type='{"type": "boolean"}'>
+          Optional. Enable conntrack for the router port whose peer is
+          l3dgw_port if set to <code>true</code>. The default value is
+          <code>false</code>.
+        </column>
+
       </group>
 
       <group title="Options for localnet ports">
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 34bd25de7b..9a0d418e46 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -10970,5 +10970,129 @@ AT_CHECK([as northd ovn-appctl -t ovn-northd status], 
[0], [dnl
 Status: active
 ])
 
+AT_CLEANUP
+])
+
+OVN_FOR_EACH_NORTHD_NO_HV([
+AT_SETUP([Distributed gw port enable conntrack option])
+ovn_start
+
+check ovn-sbctl chassis-add gw1 geneve 127.0.0.1
+
+# Add a distributed router
+check ovn-nbctl lr-add R1
+check ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
+check ovn-nbctl lrp-set-gateway-chassis R1-S1 gw1
+
+# Add a external network connected to R1
+check ovn-nbctl ls-add S1
+check ovn-nbctl lsp-add S1 S1-R1
+check ovn-nbctl lsp-set-type S1-R1 router
+check ovn-nbctl lsp-set-addresses S1-R1 router
+check ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
+AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
+
+# Add a external network vif
+check ovn-nbctl lsp-add S1 S1-VIF
+check ovn-nbctl lsp-set-addresses S1-VIF "02:ac:10:01:00:02 172.16.1.11"
+
+# Add the router gw port and vif to one port_group which has stateful acls
+check ovn-nbctl --wait=sb pg-add pg_dgw S1-R1 S1-VIF
+check ovn-nbctl acl-add pg_dgw from-lport 1002 "inport == @pg_dgw && ip4" 
allow-related
+check ovn-nbctl acl-add pg_dgw to-lport 1003 "outport == @pg_dgw && ip4" 
allow-related
+
+# Check skip conntrack option with 'enable_router_port_acl' default (false)
+AT_CHECK([ovn-sbctl dump-flows S1 | grep pre_acl | sed 's/table=./table=?/'], 
[0], [dnl
+  table=? (ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(eth.mcast), 
action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(ip && inport == 
"S1-R1"), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(nd || nd_rs || nd_ra 
|| mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  table=? (ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(eth.mcast), 
action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(ip && outport == 
"S1-R1"), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(nd || nd_rs || nd_ra 
|| mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  table=? (ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+])
+
+# Enable 'enable_router_port_acl' and check the flows
+check ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1 
enable_router_port_acl=true
+AT_CHECK([ovn-sbctl dump-flows S1 | grep pre_acl | sed 's/table=./table=?/'], 
[0], [dnl
+  table=? (ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(eth.mcast), 
action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(nd || nd_rs || nd_ra 
|| mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  table=? (ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(eth.mcast), 
action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(nd || nd_rs || nd_ra 
|| mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  table=? (ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+])
+
+# ICMP packets from router port to external network should go to conntrack
+flow_eth_in='eth.src == 02:ac:10:01:00:01 && eth.dst == 02:ac:10:01:00:02'
+flow_ip_in='ip.ttl==64 && ip4.src == 172.16.10.1 && ip4.dst == 172.16.10.11'
+flow_icmp='icmp4.type == 8'
+flow_in="inport == \"S1-R1\" && ${flow_eth_in} && ${flow_ip_in} && 
${flow_icmp}"
+AT_CHECK_UNQUOTED([ovn_trace --ct est --ct est --minimal S1 "${flow_in}"], 
[0], [dnl
+ct_next(ct_state=est|trk) {
+    ct_next(ct_state=est|trk) {
+        output("S1-VIF");
+    };
+};
+])
+
+# Disable 'enable_router_port_acl' and check the flows
+check ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1 
enable_router_port_acl=false
+AT_CHECK([ovn-sbctl dump-flows S1 | grep pre_acl | sed 's/table=./table=?/'], 
[0], [dnl
+  table=? (ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(eth.mcast), 
action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(ip && inport == 
"S1-R1"), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(nd || nd_rs || nd_ra 
|| mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  table=? (ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(eth.mcast), 
action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(ip && outport == 
"S1-R1"), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(nd || nd_rs || nd_ra 
|| mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  table=? (ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+])
+
+# Clear the option 'enable_router_port_acl' and check the flows.  Before that 
enable the option.
+check ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1 
enable_router_port_acl=true
+AT_CHECK([ovn-sbctl dump-flows S1 | grep pre_acl | sed 's/table=./table=?/'], 
[0], [dnl
+  table=? (ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(eth.mcast), 
action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(nd || nd_rs || nd_ra 
|| mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  table=? (ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(eth.mcast), 
action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(nd || nd_rs || nd_ra 
|| mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  table=? (ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+])
+
+check ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
+AT_CHECK([ovn-sbctl dump-flows S1 | grep pre_acl | sed 's/table=./table=?/'], 
[0], [dnl
+  table=? (ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(eth.mcast), 
action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(ip && inport == 
"S1-R1"), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=110  , match=(nd || nd_rs || nd_ra 
|| mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;)
+  table=? (ls_in_pre_acl      ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  table=? (ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(eth.mcast), 
action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(ip && outport == 
"S1-R1"), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=110  , match=(nd || nd_rs || nd_ra 
|| mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;)
+  table=? (ls_out_pre_acl     ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  table=? (ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+])
+
+
 AT_CLEANUP
 ])
-- 
2.43.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to