This option changes how logical switch ACL related flows are generated
such that the following behavior is ensured:

a. If a logical switch has no ACL applied to it (either directly or
indirectly via a port group) then traffic is always allowed in the
ls_in_acl, ls_in_acl_after_lb, ls_out_acl stages.

b. If a logical switch has ACLs applied (directly or indirectly) and
NB_Global.options:default_acl_drop is set to 'false', then traffic that
doesn't match any ACL in the ls_in_acl, ls_in_acl_after_lb, ls_out_acl
stages is allowed to advance to the next step in the processing
pipeline.

c. If a logical switch has *any* ACL applied (directly or indirectly)
and NB_Global.options:default_acl_drop is set to 'true', then a default
lowest-priority rule is added to the ls_in_acl, ls_in_acl_after_lb,
ls_out_acl stages to drop traffic that is not matched by any ACLs.

The goal of the feature is to simplify the configuration of the ACLs and
port groups for CMSs that require a default-deny firewall
implementation.  One such example is with OpenStack security groups
which, when enabled, implicitly drop all not explicitly allowed traffic.

Until now the CMS had to add all logical ports corresponding to VMs in a
network to a single, huge, default-drop-port-group and apply a single
drop ACL to the port group.

With this new feature, the CMS can enable 'default_acl_drop', and punch
holes for traffic that needs to be allowed.  The resulting NB and SB
configuration is also reduced in size.

Reported-by: Daniel Alvarez Sanchez <[email protected]>
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1947807
Signed-off-by: Dumitru Ceara <[email protected]>
---
v1:
- Removed RFC tag.
- Added flows for the stateful-ACL case as pointed by Han.
---
 NEWS                    |   2 +
 northd/northd.c         |  50 ++++-
 northd/ovn-northd.8.xml |  28 ++-
 ovn-nb.xml              |   8 +
 tests/ovn-northd.at     | 483 +++++++++++++++++++++++++++++++++++++++-
 5 files changed, 551 insertions(+), 20 deletions(-)

diff --git a/NEWS b/NEWS
index c881764a6..dbe89e9cf 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ Post v22.03.0
   - Replaced the usage of masked ct_label by ct_mark in most cases to work
     better with hardware-offloading.
   - Support NAT for logical routers with multiple distributed gateway ports.
+  - Add global option (NB_Global.options:default_acl_drop) to enable
+    implicit drop behavior on logical switches with ACLs applied.
 
 OVN v22.03.0 - 11 Mar 2022
 --------------------------
diff --git a/northd/northd.c b/northd/northd.c
index bcd36bbaa..43b028c2c 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -74,6 +74,12 @@ static struct eth_addr svc_monitor_mac_ea;
  * Otherwise, it will avoid using it.  The default is true. */
 static bool use_ct_inv_match = true;
 
+/* If this option is 'true' northd will implicitly add a lowest-priority
+ * drop rule in the ACL stage of logical switches that have at least one
+ * ACL.
+ */
+static bool default_acl_drop;
+
 #define MAX_OVN_TAGS 4096
 
 /* Pipeline stages. */
@@ -6617,6 +6623,7 @@ static void
 build_acls(struct ovn_datapath *od, struct hmap *lflows,
            const struct hmap *port_groups, const struct shash *meter_groups)
 {
+    const char *default_acl_action = default_acl_drop ? "drop;" : "next;";
     bool has_stateful = od->has_stateful_acl || od->has_lb_vip;
     struct ds match   = DS_EMPTY_INITIALIZER;
     struct ds actions = DS_EMPTY_INITIALIZER;
@@ -6628,22 +6635,34 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows,
      *
      * A related rule at priority 1 is added below if there
      * are any stateful ACLs in this datapath. */
-    if (!od->has_acls && !od->has_lb_vip) {
-        ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX, "1", "next;");
-        ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX, "1", "next;");
+    if (!od->has_acls) {
+        if (!od->has_lb_vip) {
+            ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX, "1",
+                          "next;");
+            ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX, "1",
+                          "next;");
+        } else {
+            ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, 1, "1", "next;");
+            ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, 1, "1", "next;");
+        }
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL_AFTER_LB, 0, "1", "next;");
     } else {
-        ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, 0, "1", "next;");
-        ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, 0, "1", "next;");
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, 0, "1",
+                      default_acl_action);
+        ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, 0, "1",
+                      default_acl_action);
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL_AFTER_LB, 0, "1",
+                      default_acl_action);
     }
 
-    ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL_AFTER_LB, 0, "1", "next;");
 
     if (has_stateful) {
         /* Ingress and Egress ACL Table (Priority 1).
          *
-         * By default, traffic is allowed.  This is partially handled by
-         * the Priority 0 ACL flows added earlier, but we also need to
-         * commit IP flows.  This is because, while the initiater's
+         * By default, traffic is allowed (if default_acl_drop is 'false') or
+         * dropped (if default_acl_drop is 'true').  This is partially
+         * handled by the Priority 0 ACL flows added earlier, but we also
+         * need to commit IP flows.  This is because, while the initiater's
          * direction may not have any stateful rules, the server's may
          * and then its return traffic would not have an associated
          * conntrack entry and would return "+invalid".
@@ -6661,12 +6680,20 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows,
          * Subsequent packets will hit the flow at priority 0 that just
          * uses "next;". */
         ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, 1,
-                      "ip && (!ct.est || (ct.est && ct_mark.blocked == 1))",
+                      "ip && ct.est && ct_mark.blocked == 1",
                        REGBIT_CONNTRACK_COMMIT" = 1; next;");
         ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, 1,
-                      "ip && (!ct.est || (ct.est && ct_mark.blocked == 1))",
+                      "ip && ct.est && ct_mark.blocked == 1",
                        REGBIT_CONNTRACK_COMMIT" = 1; next;");
 
+        default_acl_action = default_acl_drop
+                             ? "drop;"
+                             : REGBIT_CONNTRACK_COMMIT" = 1; next;";
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, 1, "ip && !ct.est",
+                      default_acl_action);
+        ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, 1, "ip && !ct.est",
+                      default_acl_action);
+
         /* Ingress and Egress ACL Table (Priority 65532).
          *
          * Always drop traffic that's in an invalid state.  Also drop
@@ -15321,6 +15348,7 @@ ovnnb_db_run(struct northd_input *input_data,
                                         "controller_event", false);
     check_lsp_is_up = !smap_get_bool(&nb->options,
                                      "ignore_lsp_down", true);
+    default_acl_drop = smap_get_bool(&nb->options, "default_acl_drop", false);
 
     build_datapaths(input_data, ovnsb_txn, &data->datapaths, &data->lr_list);
     build_lbs(input_data, &data->datapaths, &data->lbs);
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index db4f4d267..68e0bd626 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -774,8 +774,12 @@
     <p>
       This table contains a priority-65535 flow to advance to the next table
       if the logical switch has <code>no</code> ACLs configured, otherwise a
-        priority-0 flow to advance to the next table so that ACLs allow
-        packets by default.
+      priority-0 flow to advance to the next table so that ACLs allow
+      packets by default if <ref column="options:default_acl_drop"
+      table="NB_Global" db="OVN_Northbound"/> colum of <ref table="NB_Global"
+      db="OVN_Northbound"/> is <code>false</code> or not set.  Otherwise
+      the flow action is set to <code>drop;</code> to implement a default
+      drop behavior.
     </p>
 
     <p>
@@ -784,6 +788,26 @@
     </p>
 
     <ul>
+      <li>
+        If <ref column="options:default_acl_drop" table="NB_Global"
+        db="OVN_Northbound"/> colum of <ref table="NB_Global"
+        db="OVN_Northbound"/> is <code>false</code> or not set, a priority-1
+        flow that sets the hint to commit IP traffic that is not part of
+        established sessions to the connection tracker (with action
+        <code>reg0[1] = 1; next;</code>).  This is needed for
+        the default allow policy because, while the initiator's direction
+        may not have any stateful rules, the server's may and then
+        its return traffic would not be known and marked as invalid.
+      </li>
+
+      <li>
+        If <ref column="options:default_acl_drop" table="NB_Global"
+        db="OVN_Northbound"/> colum of <ref table="NB_Global"
+        db="OVN_Northbound"/> is <code>true</code>, a priority-1
+        flow that drops IP traffic that is not part of established
+        sessions.
+      </li>
+
       <li>
         A priority-1 flow that sets the hint to commit IP traffic to the
         connection tracker (with action <code>reg0[1] = 1; next;</code>).  This
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 547f7f48a..9010240a8 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -255,6 +255,14 @@
         </p>
       </column>
 
+      <column name="options" key="default_acl_drop">
+        <p>
+          If set to <code>true</code>., <code>ovn-northd</code> will
+          generate a logical flow to drop all traffic in the ACL stages.
+          By default this option is set to <code>false</code>.
+        </p>
+      </column>
+
       <group title="Options for configuring interconnection route 
advertisement">
         <p>
           These options control how routes are advertised between OVN
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index adb304385..724ca2057 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -2227,7 +2227,8 @@ AT_CHECK([ovn-sbctl lflow-list ls | grep -e 
ls_in_acl_hint -e ls_out_acl_hint -e
   table=3 (ls_out_acl_hint    ), priority=5    , match=(!ct.trk), 
action=(reg0[[8]] = 1; reg0[[9]] = 1; next;)
   table=3 (ls_out_acl_hint    ), priority=6    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
   table=3 (ls_out_acl_hint    ), priority=7    , match=(ct.new && !ct.est), 
action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
-  table=4 (ls_out_acl         ), priority=1    , match=(ip && (!ct.est || 
(ct.est && ct_mark.blocked == 1))), action=(reg0[[1]] = 1; next;)
+  table=4 (ls_out_acl         ), priority=1    , match=(ip && !ct.est), 
action=(reg0[[1]] = 1; next;)
+  table=4 (ls_out_acl         ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
   table=4 (ls_out_acl         ), priority=65532, match=(!ct.est && ct.rel && 
!ct.new && !ct.inv && ct_mark.blocked == 0), action=(next;)
   table=4 (ls_out_acl         ), priority=65532, match=(ct.est && !ct.rel && 
!ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;)
   table=4 (ls_out_acl         ), priority=65532, match=(ct.inv || (ct.est && 
ct.rpl && ct_mark.blocked == 1)), action=(drop;)
@@ -2238,7 +2239,8 @@ AT_CHECK([ovn-sbctl lflow-list ls | grep -e 
ls_in_acl_hint -e ls_out_acl_hint -e
   table=8 (ls_in_acl_hint     ), priority=5    , match=(!ct.trk), 
action=(reg0[[8]] = 1; reg0[[9]] = 1; next;)
   table=8 (ls_in_acl_hint     ), priority=6    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
   table=8 (ls_in_acl_hint     ), priority=7    , match=(ct.new && !ct.est), 
action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
-  table=9 (ls_in_acl          ), priority=1    , match=(ip && (!ct.est || 
(ct.est && ct_mark.blocked == 1))), action=(reg0[[1]] = 1; next;)
+  table=9 (ls_in_acl          ), priority=1    , match=(ip && !ct.est), 
action=(reg0[[1]] = 1; next;)
+  table=9 (ls_in_acl          ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
   table=9 (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && 
!ct.new && !ct.inv && ct_mark.blocked == 0), action=(next;)
   table=9 (ls_in_acl          ), priority=65532, match=(ct.est && !ct.rel && 
!ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; 
reg0[[10]] = 0; next;)
   table=9 (ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && 
ct.rpl && ct_mark.blocked == 1)), action=(drop;)
@@ -2262,7 +2264,8 @@ AT_CHECK([ovn-sbctl lflow-list ls | grep -e 
ls_in_acl_hint -e ls_out_acl_hint -e
   table=3 (ls_out_acl_hint    ), priority=6    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
   table=3 (ls_out_acl_hint    ), priority=7    , match=(ct.new && !ct.est), 
action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
   table=4 (ls_out_acl         ), priority=0    , match=(1), action=(next;)
-  table=4 (ls_out_acl         ), priority=1    , match=(ip && (!ct.est || 
(ct.est && ct_mark.blocked == 1))), action=(reg0[[1]] = 1; next;)
+  table=4 (ls_out_acl         ), priority=1    , match=(ip && !ct.est), 
action=(reg0[[1]] = 1; next;)
+  table=4 (ls_out_acl         ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
   table=4 (ls_out_acl         ), priority=1001 , match=(reg0[[7]] == 1 && 
(ip)), action=(reg0[[1]] = 1; next;)
   table=4 (ls_out_acl         ), priority=1001 , match=(reg0[[8]] == 1 && 
(ip)), action=(next;)
   table=4 (ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
@@ -2279,7 +2282,8 @@ AT_CHECK([ovn-sbctl lflow-list ls | grep -e 
ls_in_acl_hint -e ls_out_acl_hint -e
   table=8 (ls_in_acl_hint     ), priority=6    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
   table=8 (ls_in_acl_hint     ), priority=7    , match=(ct.new && !ct.est), 
action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
   table=9 (ls_in_acl          ), priority=0    , match=(1), action=(next;)
-  table=9 (ls_in_acl          ), priority=1    , match=(ip && (!ct.est || 
(ct.est && ct_mark.blocked == 1))), action=(reg0[[1]] = 1; next;)
+  table=9 (ls_in_acl          ), priority=1    , match=(ip && !ct.est), 
action=(reg0[[1]] = 1; next;)
+  table=9 (ls_in_acl          ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
   table=9 (ls_in_acl          ), priority=1001 , match=(reg0[[7]] == 1 && 
(ip)), action=(reg0[[1]] = 1; next;)
   table=9 (ls_in_acl          ), priority=1001 , match=(reg0[[8]] == 1 && 
(ip)), action=(next;)
   table=9 (ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
@@ -6331,7 +6335,8 @@ AT_CAPTURE_FILE([lsflows])
 
 AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], 
[0], [dnl
   table=??(ls_in_acl          ), priority=0    , match=(1), action=(next;)
-  table=??(ls_in_acl          ), priority=1    , match=(ip && (!ct.est || 
(ct.est && ct_mark.blocked == 1))), action=(reg0[[1]] = 1; next;)
+  table=??(ls_in_acl          ), priority=1    , match=(ip && !ct.est), 
action=(reg0[[1]] = 1; next;)
+  table=??(ls_in_acl          ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
   table=??(ls_in_acl          ), priority=2001 , match=(reg0[[10]] == 1 && 
(ip4)), action=(ct_commit { ct_mark.blocked = 1; }; /* drop */)
   table=??(ls_in_acl          ), priority=2001 , match=(reg0[[9]] == 1 && 
(ip4)), action=(/* drop */)
   table=??(ls_in_acl          ), priority=2002 , match=(reg0[[7]] == 1 && (ip4 
&& tcp)), action=(reg0[[1]] = 1; next;)
@@ -6383,7 +6388,8 @@ AT_CAPTURE_FILE([lsflows])
 
 AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], 
[0], [dnl
   table=??(ls_in_acl          ), priority=0    , match=(1), action=(next;)
-  table=??(ls_in_acl          ), priority=1    , match=(ip && (!ct.est || 
(ct.est && ct_mark.blocked == 1))), action=(reg0[[1]] = 1; next;)
+  table=??(ls_in_acl          ), priority=1    , match=(ip && !ct.est), 
action=(reg0[[1]] = 1; next;)
+  table=??(ls_in_acl          ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
   table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
   table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && 
!ct.new && !ct.inv && ct_mark.blocked == 0), action=(next;)
   table=??(ls_in_acl          ), priority=65532, match=(ct.est && !ct.rel && 
!ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; 
reg0[[10]] = 0; next;)
@@ -6435,7 +6441,8 @@ AT_CAPTURE_FILE([lsflows])
 
 AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], 
[0], [dnl
   table=??(ls_in_acl          ), priority=0    , match=(1), action=(next;)
-  table=??(ls_in_acl          ), priority=1    , match=(ip && (!ct.est || 
(ct.est && ct_mark.blocked == 1))), action=(reg0[[1]] = 1; next;)
+  table=??(ls_in_acl          ), priority=1    , match=(ip && !ct.est), 
action=(reg0[[1]] = 1; next;)
+  table=??(ls_in_acl          ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
   table=??(ls_in_acl          ), priority=2002 , match=(reg0[[7]] == 1 && (ip4 
&& tcp)), action=(reg0[[1]] = 1; next;)
   table=??(ls_in_acl          ), priority=2002 , match=(reg0[[8]] == 1 && (ip4 
&& tcp)), action=(next;)
   table=??(ls_in_acl          ), priority=2003 , match=(reg0[[7]] == 1 && (ip4 
&& icmp)), action=(reg0[[1]] = 1; next;)
@@ -6664,3 +6671,465 @@ ovn-nbctl --may-exist static-mac-binding-add lr0-p0 
192.168.10.100 00:00:22:33:5
 wait_row_count Static_MAC_Binding 1 logical_port=lr0-p0 ip=192.168.10.100 
mac="00\:00\:22\:33\:55\:66"
 
 AT_CLEANUP
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([LS default ACL drop])
+AT_KEYWORDS([acl])
+
+ovn_start
+
+check ovn-nbctl ls-add ls
+check ovn-nbctl lsp-add ls lsp1 -- lsp-set-addresses lsp1 00:00:00:00:00:01
+check ovn-nbctl lsp-add ls lsp2 -- lsp-set-addresses lsp2 00:00:00:00:00:02
+
+flow="inport == \"lsp1\" && eth.src == 00:00:00:00:00:01 && eth.dst == 
00:00:00:00:00:02 && ip.ttl == 64 && ip4.src == 42.42.42.42 && ip4.dst == 
42.42.42.43 && udp && udp.src == 42 && udp.dst == 84"
+
+AS_BOX([No ACL, default_acl_drop not set])
+check ovn-nbctl --wait=sb sync
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=65535, match=(1), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl_hint     ), priority=65535, match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=65535, match=(1), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=65535, match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+])
+
+dnl UDP traffic should be allowed.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+output("lsp2");
+])
+
+AS_BOX([No ACL, default_acl_drop false])
+check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=false
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=65535, match=(1), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl_hint     ), priority=65535, match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=65535, match=(1), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=65535, match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+])
+
+dnl UDP traffic should be allowed.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+output("lsp2");
+])
+
+AS_BOX([No ACL, default_acl_drop true])
+check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=true
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=65535, match=(1), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl_hint     ), priority=65535, match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=65535, match=(1), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=65535, match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+])
+
+dnl UDP traffic should be allowed.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+output("lsp2");
+])
+
+AS_BOX([from-lport ACL])
+check ovn-nbctl acl-del ls
+check ovn-nbctl acl-add ls from-lport 1 "ip4 && tcp" allow
+
+AS_BOX([from-lport ACL, default_acl_drop not set])
+check ovn-nbctl --wait=sb remove NB_Global . options default_acl_drop
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl          ), priority=1001 , match=(ip4 && tcp), 
action=(next;)
+  table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+])
+
+dnl UDP traffic should be allowed.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+output("lsp2");
+])
+
+AS_BOX([from-lport ACL, default_acl_drop false])
+check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=false
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl          ), priority=1001 , match=(ip4 && tcp), 
action=(next;)
+  table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+])
+
+dnl UDP traffic should be allowed.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+output("lsp2");
+])
+
+AS_BOX([from-lport ACL, default_acl_drop true])
+check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=true
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_in_acl          ), priority=1001 , match=(ip4 && tcp), 
action=(next;)
+  table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+])
+
+dnl UDP traffic should be dropped.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+])
+
+AS_BOX([from-lport ACL allow-related, default_acl_drop true])
+check ovn-nbctl acl-del ls
+check ovn-nbctl --wait=sb acl-add ls from-lport 1 "ip4 && tcp" allow-related
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_in_acl          ), priority=1    , match=(ip && !ct.est), 
action=(drop;)
+  table=??(ls_in_acl          ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
+  table=??(ls_in_acl          ), priority=1001 , match=(reg0[[7]] == 1 && (ip4 
&& tcp)), action=(reg0[[1]] = 1; next;)
+  table=??(ls_in_acl          ), priority=1001 , match=(reg0[[8]] == 1 && (ip4 
&& tcp)), action=(next;)
+  table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && 
!ct.new && !ct.inv && ct_mark.blocked == 0), action=(next;)
+  table=??(ls_in_acl          ), priority=65532, match=(ct.est && !ct.rel && 
!ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; 
reg0[[10]] = 0; next;)
+  table=??(ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && 
ct.rpl && ct_mark.blocked == 1)), action=(drop;)
+  table=??(ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs 
|| mldv1 || mldv2), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl_hint     ), priority=1    , match=(ct.est && 
ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=2    , match=(ct.est && 
ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=3    , match=(!ct.est), 
action=(reg0[[9]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=4    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=5    , match=(!ct.trk), 
action=(reg0[[8]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=6    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=7    , match=(ct.new && !ct.est), 
action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  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_out_acl         ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_out_acl         ), priority=1    , match=(ip && !ct.est), 
action=(drop;)
+  table=??(ls_out_acl         ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
+  table=??(ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=65532, match=(!ct.est && ct.rel && 
!ct.new && !ct.inv && ct_mark.blocked == 0), action=(next;)
+  table=??(ls_out_acl         ), priority=65532, match=(ct.est && !ct.rel && 
!ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;)
+  table=??(ls_out_acl         ), priority=65532, match=(ct.inv || (ct.est && 
ct.rpl && ct_mark.blocked == 1)), action=(drop;)
+  table=??(ls_out_acl         ), priority=65532, match=(nd || nd_ra || nd_rs 
|| mldv1 || mldv2), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=1    , match=(ct.est && 
ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=2    , match=(ct.est && 
ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=3    , match=(!ct.est), 
action=(reg0[[9]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=4    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=5    , match=(!ct.trk), 
action=(reg0[[8]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=6    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=7    , match=(ct.new && !ct.est), 
action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; 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;)
+])
+
+dnl UDP traffic should be dropped.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+ct_next(ct_state=new|trk);
+])
+
+AS_BOX([from-lport --apply-after-lb ACL])
+check ovn-nbctl acl-del ls
+check ovn-nbctl --apply-after-lb acl-add ls from-lport 1 "ip4 && tcp" allow
+
+AS_BOX([from-lport --apply-after-lb ACL, default_acl_drop not set])
+check ovn-nbctl --wait=sb remove NB_Global . options default_acl_drop
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=1001 , match=(ip4 && tcp), 
action=(next;)
+  table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+])
+
+dnl UDP traffic should be allowed.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+output("lsp2");
+])
+
+AS_BOX([from-lport --apply-after-lb ACL, default_acl_drop false])
+check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=false
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=1001 , match=(ip4 && tcp), 
action=(next;)
+  table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+])
+
+dnl UDP traffic should be allowed.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+output("lsp2");
+])
+
+AS_BOX([from-lport --apply-after-lb ACL, default_acl_drop true])
+check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=true
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_in_acl_after_lb ), priority=1001 , match=(ip4 && tcp), 
action=(next;)
+  table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+])
+
+dnl UDP traffic should be dropped.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+])
+
+AS_BOX([from-lport --apply-after-lb ACL allow-related, default_acl_drop true])
+check ovn-nbctl acl-del ls
+check ovn-nbctl --wait=sb --apply-after-lb acl-add ls from-lport 1 "ip4 && 
tcp" allow-related
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_in_acl          ), priority=1    , match=(ip && !ct.est), 
action=(drop;)
+  table=??(ls_in_acl          ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
+  table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && 
!ct.new && !ct.inv && ct_mark.blocked == 0), action=(next;)
+  table=??(ls_in_acl          ), priority=65532, match=(ct.est && !ct.rel && 
!ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; 
reg0[[10]] = 0; next;)
+  table=??(ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && 
ct.rpl && ct_mark.blocked == 1)), action=(drop;)
+  table=??(ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs 
|| mldv1 || mldv2), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_in_acl_after_lb ), priority=1001 , match=(reg0[[7]] == 1 && (ip4 
&& tcp)), action=(reg0[[1]] = 1; next;)
+  table=??(ls_in_acl_after_lb ), priority=1001 , match=(reg0[[8]] == 1 && (ip4 
&& tcp)), action=(next;)
+  table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl_hint     ), priority=1    , match=(ct.est && 
ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=2    , match=(ct.est && 
ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=3    , match=(!ct.est), 
action=(reg0[[9]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=4    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=5    , match=(!ct.trk), 
action=(reg0[[8]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=6    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=7    , match=(ct.new && !ct.est), 
action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  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_out_acl         ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_out_acl         ), priority=1    , match=(ip && !ct.est), 
action=(drop;)
+  table=??(ls_out_acl         ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
+  table=??(ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=65532, match=(!ct.est && ct.rel && 
!ct.new && !ct.inv && ct_mark.blocked == 0), action=(next;)
+  table=??(ls_out_acl         ), priority=65532, match=(ct.est && !ct.rel && 
!ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;)
+  table=??(ls_out_acl         ), priority=65532, match=(ct.inv || (ct.est && 
ct.rpl && ct_mark.blocked == 1)), action=(drop;)
+  table=??(ls_out_acl         ), priority=65532, match=(nd || nd_ra || nd_rs 
|| mldv1 || mldv2), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=1    , match=(ct.est && 
ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=2    , match=(ct.est && 
ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=3    , match=(!ct.est), 
action=(reg0[[9]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=4    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=5    , match=(!ct.trk), 
action=(reg0[[8]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=6    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=7    , match=(ct.new && !ct.est), 
action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; 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;)
+])
+
+dnl UDP traffic should be dropped.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+ct_next(ct_state=new|trk);
+])
+
+AS_BOX([to-lport ACL])
+check ovn-nbctl acl-del ls
+check ovn-nbctl acl-add ls to-lport 1 "ip4 && tcp" allow
+
+AS_BOX([to-lport ACL, default_acl_drop not set])
+check ovn-nbctl --wait=sb remove NB_Global . options default_acl_drop
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_acl         ), priority=1001 , match=(ip4 && tcp), 
action=(next;)
+  table=??(ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+])
+
+dnl UDP traffic should be allowed.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+output("lsp2");
+])
+
+AS_BOX([to-lport ACL, default_acl_drop false])
+check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=false
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_acl         ), priority=1001 , match=(ip4 && tcp), 
action=(next;)
+  table=??(ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+])
+
+dnl UDP traffic should be allowed.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+output("lsp2");
+])
+
+AS_BOX([to-lport ACL, default_acl_drop true])
+check ovn-nbctl --wait=sb set NB_Global . options:default_acl_drop=true
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_out_acl         ), priority=1001 , match=(ip4 && tcp), 
action=(next;)
+  table=??(ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=110  , match=(eth.src == 
$svc_monitor_mac), action=(next;)
+])
+
+dnl UDP traffic should be dropped.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+])
+
+AS_BOX([to-lport ACL allow-related, default_acl_drop true])
+check ovn-nbctl acl-del ls
+check ovn-nbctl --wait=sb acl-add ls to-lport 1 "ip4 && tcp" allow-related
+AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 
's/table=../table=??/' | sort], [0], [dnl
+  table=??(ls_in_acl          ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_in_acl          ), priority=1    , match=(ip && !ct.est), 
action=(drop;)
+  table=??(ls_in_acl          ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
+  table=??(ls_in_acl          ), priority=34000, match=(eth.dst == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && 
!ct.new && !ct.inv && ct_mark.blocked == 0), action=(next;)
+  table=??(ls_in_acl          ), priority=65532, match=(ct.est && !ct.rel && 
!ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; 
reg0[[10]] = 0; next;)
+  table=??(ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && 
ct.rpl && ct_mark.blocked == 1)), action=(drop;)
+  table=??(ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs 
|| mldv1 || mldv2), action=(next;)
+  table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_acl_hint     ), priority=1    , match=(ct.est && 
ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=2    , match=(ct.est && 
ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=3    , match=(!ct.est), 
action=(reg0[[9]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=4    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=5    , match=(!ct.trk), 
action=(reg0[[8]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=6    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_in_acl_hint     ), priority=7    , match=(ct.new && !ct.est), 
action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_pre_acl      ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; next;)
+  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_out_acl         ), priority=0    , match=(1), action=(drop;)
+  table=??(ls_out_acl         ), priority=1    , match=(ip && !ct.est), 
action=(drop;)
+  table=??(ls_out_acl         ), priority=1    , match=(ip && ct.est && 
ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
+  table=??(ls_out_acl         ), priority=1001 , match=(reg0[[7]] == 1 && (ip4 
&& tcp)), action=(reg0[[1]] = 1; next;)
+  table=??(ls_out_acl         ), priority=1001 , match=(reg0[[8]] == 1 && (ip4 
&& tcp)), action=(next;)
+  table=??(ls_out_acl         ), priority=34000, match=(eth.src == 
$svc_monitor_mac), action=(next;)
+  table=??(ls_out_acl         ), priority=65532, match=(!ct.est && ct.rel && 
!ct.new && !ct.inv && ct_mark.blocked == 0), action=(next;)
+  table=??(ls_out_acl         ), priority=65532, match=(ct.est && !ct.rel && 
!ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;)
+  table=??(ls_out_acl         ), priority=65532, match=(ct.inv || (ct.est && 
ct.rpl && ct_mark.blocked == 1)), action=(drop;)
+  table=??(ls_out_acl         ), priority=65532, match=(nd || nd_ra || nd_rs 
|| mldv1 || mldv2), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_acl_hint    ), priority=1    , match=(ct.est && 
ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=2    , match=(ct.est && 
ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=3    , match=(!ct.est), 
action=(reg0[[9]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=4    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=5    , match=(!ct.trk), 
action=(reg0[[8]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=6    , match=(!ct.new && ct.est && 
!ct.rpl && ct_mark.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_out_acl_hint    ), priority=7    , match=(ct.new && !ct.est), 
action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
+  table=??(ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
+  table=??(ls_out_pre_acl     ), priority=100  , match=(ip), action=(reg0[[0]] 
= 1; 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;)
+])
+
+dnl UDP traffic should be dropped.
+AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
+# 
udp,reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,nw_src=42.42.42.42,nw_dst=42.42.42.43,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=42,tp_dst=84
+ct_next(ct_state=new|trk);
+])
+
+AT_CLEANUP
+])
-- 
2.27.0

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

Reply via email to