ebb439
From 44d993b41f4a9e995b2ff76938f23413bfed4652 Mon Sep 17 00:00:00 2001
ebb439
From: Numan Siddique <numans@ovn.org>
ebb439
Date: Mon, 28 Sep 2020 17:31:32 +0530
ebb439
Subject: [PATCH 4/5] ovn-northd: Optimize logical flow generation for reject
ebb439
 ACLs.
ebb439
ebb439
ovn-northd adds below lflows for a reject ACL with a match - M
ebb439
ebb439
match = (ip4 && tcp && 'M') action = tcp_reject{}
ebb439
match = (ip6 && tcp && 'M') action = tcp_reject{}
ebb439
match = (ip4 && 'M') action = icmp4{}
ebb439
match = (ip6 && 'M') action = icmp6{}
ebb439
ebb439
This approach has a couple of problems:
ebb439
   - ovn-controller can reject the lflows if there are invalid matches.
ebb439
     Eg. If match 'M' is - 'ip4 && udp'.
ebb439
ebb439
   - In a large scale deployment, this could result in lot of invalid
ebb439
     logical flows and increase the size of the SB DB.
ebb439
ebb439
This patch addresses this problem by using newly added reject OVN action.
ebb439
With this patch, there will be just one lflow for each reject ACL.
ebb439
ebb439
Acked-by: Mark Michelson <mmichels@redhat.com>
ebb439
Acked-by: Dumitru Ceara <dceara@redhat.com>
ebb439
Signed-off-by: Numan Siddique <numans@ovn.org>
ebb439
ebb439
(cherry-picked from upstream master commit 4e19493b3d4eb549fc52d6fb3cf004847b64d2de)
ebb439
ebb439
Change-Id: I540247929b4939bd5696a2edcb15a4bf7dc4af77
ebb439
---
ebb439
 northd/ovn-northd.c |  50 +----------
ebb439
 tests/ovn-northd.at | 214 +++++++-------------------------------------
ebb439
 tests/system-ovn.at |  46 +++++++++-
ebb439
 3 files changed, 81 insertions(+), 229 deletions(-)
ebb439
ebb439
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
ebb439
index b099f705b..3a71d0ee8 100644
ebb439
--- a/northd/ovn-northd.c
ebb439
+++ b/northd/ovn-northd.c
ebb439
@@ -5385,61 +5385,19 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows,
ebb439
                   ingress ? ovn_stage_get_table(S_SWITCH_OUT_QOS_MARK)
ebb439
                           : ovn_stage_get_table(S_SWITCH_IN_L2_LKUP));
ebb439
 
ebb439
-    /* TCP */
ebb439
     build_acl_log(&actions, acl);
ebb439
     if (extra_match->length > 0) {
ebb439
         ds_put_format(&match, "(%s) && ", extra_match->string);
ebb439
     }
ebb439
-    ds_put_format(&match, "ip4 && tcp && (%s)", acl->match);
ebb439
-    ds_put_format(&actions, "reg0 = 0; "
ebb439
-                  "eth.dst <-> eth.src; ip4.dst <-> ip4.src; "
ebb439
-                  "tcp_reset { outport <-> inport; %s };", next_action);
ebb439
-    ovn_lflow_add_with_hint(lflows, od, stage,
ebb439
-                            acl->priority + OVN_ACL_PRI_OFFSET + 10,
ebb439
-                            ds_cstr(&match), ds_cstr(&actions), stage_hint);
ebb439
-    ds_clear(&match);
ebb439
-    ds_clear(&actions);
ebb439
-    build_acl_log(&actions, acl);
ebb439
-    if (extra_match->length > 0) {
ebb439
-        ds_put_format(&match, "(%s) && ", extra_match->string);
ebb439
-    }
ebb439
-    ds_put_format(&match, "ip6 && tcp && (%s)", acl->match);
ebb439
-    ds_put_format(&actions, "reg0 = 0; "
ebb439
-                  "eth.dst <-> eth.src; ip6.dst <-> ip6.src; "
ebb439
-                  "tcp_reset { outport <-> inport; %s };", next_action);
ebb439
-    ovn_lflow_add_with_hint(lflows, od, stage,
ebb439
-                            acl->priority + OVN_ACL_PRI_OFFSET + 10,
ebb439
-                            ds_cstr(&match), ds_cstr(&actions), stage_hint);
ebb439
+    ds_put_cstr(&match, acl->match);
ebb439
 
ebb439
-    /* IP traffic */
ebb439
-    ds_clear(&match);
ebb439
-    ds_clear(&actions);
ebb439
-    build_acl_log(&actions, acl);
ebb439
-    if (extra_match->length > 0) {
ebb439
-        ds_put_format(&match, "(%s) && ", extra_match->string);
ebb439
-    }
ebb439
-    ds_put_format(&match, "ip4 && (%s)", acl->match);
ebb439
     if (extra_actions->length > 0) {
ebb439
         ds_put_format(&actions, "%s ", extra_actions->string);
ebb439
     }
ebb439
+
ebb439
     ds_put_format(&actions, "reg0 = 0; "
ebb439
-                  "icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; "
ebb439
-                  "outport <-> inport; %s };", next_action);
ebb439
-    ovn_lflow_add_with_hint(lflows, od, stage,
ebb439
-                            acl->priority + OVN_ACL_PRI_OFFSET,
ebb439
-                            ds_cstr(&match), ds_cstr(&actions), stage_hint);
ebb439
-    ds_clear(&match);
ebb439
-    ds_clear(&actions);
ebb439
-    build_acl_log(&actions, acl);
ebb439
-    if (extra_match->length > 0) {
ebb439
-        ds_put_format(&match, "(%s) && ", extra_match->string);
ebb439
-    }
ebb439
-    ds_put_format(&match, "ip6 && (%s)", acl->match);
ebb439
-    if (extra_actions->length > 0) {
ebb439
-        ds_put_format(&actions, "%s ", extra_actions->string);
ebb439
-    }
ebb439
-    ds_put_format(&actions, "reg0 = 0; icmp6 { "
ebb439
-                  "eth.dst <-> eth.src; ip6.dst <-> ip6.src; "
ebb439
+                  "reject { "
ebb439
+                  "/* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ "
ebb439
                   "outport <-> inport; %s };", next_action);
ebb439
     ovn_lflow_add_with_hint(lflows, od, stage,
ebb439
                             acl->priority + OVN_ACL_PRI_OFFSET,
ebb439
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
ebb439
index a6c32c115..94007fcac 100644
ebb439
--- a/tests/ovn-northd.at
ebb439
+++ b/tests/ovn-northd.at
ebb439
@@ -2028,232 +2028,86 @@ ovn-nbctl --wait=hv sync
ebb439
 
ebb439
 AT_CHECK([ovn-sbctl lflow-list sw0 | grep "ls_in_acl" | grep pg0 | sort], [0], [dnl
ebb439
   table=7 (ls_in_acl          ), priority=2002 , dnl
ebb439
-match=(ip4 && (inport == @pg0 && ip4 && tcp && tcp.dst == 80)), dnl
ebb439
-action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=egress,table=6); };)
ebb439
-  table=7 (ls_in_acl          ), priority=2002 , dnl
ebb439
-match=(ip6 && (inport == @pg0 && ip4 && tcp && tcp.dst == 80)), dnl
ebb439
-action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=egress,table=6); };)
ebb439
-  table=7 (ls_in_acl          ), priority=2012 , dnl
ebb439
-match=(ip4 && tcp && (inport == @pg0 && ip4 && tcp && tcp.dst == 80)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=egress,table=6); };)
ebb439
-  table=7 (ls_in_acl          ), priority=2012 , dnl
ebb439
-match=(ip6 && tcp && (inport == @pg0 && ip4 && tcp && tcp.dst == 80)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=egress,table=6); };)
ebb439
+match=(inport == @pg0 && ip4 && tcp && tcp.dst == 80), dnl
ebb439
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=egress,table=6); };)
ebb439
 ])
ebb439
 
ebb439
 AT_CHECK([ovn-sbctl lflow-list sw1 | grep "ls_in_acl" | grep pg0 | sort], [0], [dnl
ebb439
   table=7 (ls_in_acl          ), priority=2002 , dnl
ebb439
-match=(ip4 && (inport == @pg0 && ip4 && tcp && tcp.dst == 80)), dnl
ebb439
-action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=egress,table=6); };)
ebb439
-  table=7 (ls_in_acl          ), priority=2002 , dnl
ebb439
-match=(ip6 && (inport == @pg0 && ip4 && tcp && tcp.dst == 80)), dnl
ebb439
-action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=egress,table=6); };)
ebb439
-  table=7 (ls_in_acl          ), priority=2012 , dnl
ebb439
-match=(ip4 && tcp && (inport == @pg0 && ip4 && tcp && tcp.dst == 80)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=egress,table=6); };)
ebb439
-  table=7 (ls_in_acl          ), priority=2012 , dnl
ebb439
-match=(ip6 && tcp && (inport == @pg0 && ip4 && tcp && tcp.dst == 80)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=egress,table=6); };)
ebb439
+match=(inport == @pg0 && ip4 && tcp && tcp.dst == 80), dnl
ebb439
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=egress,table=6); };)
ebb439
 ])
ebb439
 
ebb439
 AT_CHECK([ovn-sbctl lflow-list sw0 | grep "ls_out_acl" | grep pg0 | sort], [0], [dnl
ebb439
   table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=(ip4 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=(ip6 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=(ip4 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=(ip6 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=(outport == @pg0 && ip6 && udp), dnl
ebb439
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
 ])
ebb439
 
ebb439
 AT_CHECK([ovn-sbctl lflow-list sw1 | grep "ls_out_acl" | grep pg0 | sort], [0], [dnl
ebb439
   table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=(ip4 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=(ip6 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=(ip4 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=(ip6 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=(outport == @pg0 && ip6 && udp), dnl
ebb439
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
 ])
ebb439
 
ebb439
 ovn-nbctl acl-add pg0 to-lport 1002 "outport == @pg0 && ip4 && udp" reject
ebb439
 
ebb439
 AT_CHECK([ovn-sbctl lflow-list sw0 | grep "ls_out_acl" | grep pg0 | sort], [0], [dnl
ebb439
   table=5 (ls_out_acl         ), priority=2002 , dnl
ebb439
-match=(ip4 && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2002 , dnl
ebb439
-match=(ip6 && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=(ip4 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=(outport == @pg0 && ip4 && udp), dnl
ebb439
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
   table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=(ip6 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2012 , dnl
ebb439
-match=(ip4 && tcp && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2012 , dnl
ebb439
-match=(ip6 && tcp && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=(ip4 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=(ip6 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=(outport == @pg0 && ip6 && udp), dnl
ebb439
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
 ])
ebb439
 
ebb439
 AT_CHECK([ovn-sbctl lflow-list sw1 | grep "ls_out_acl" | grep pg0 | sort], [0], [dnl
ebb439
   table=5 (ls_out_acl         ), priority=2002 , dnl
ebb439
-match=(ip4 && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2002 , dnl
ebb439
-match=(ip6 && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=(ip4 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=(outport == @pg0 && ip4 && udp), dnl
ebb439
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
   table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=(ip6 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2012 , dnl
ebb439
-match=(ip4 && tcp && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2012 , dnl
ebb439
-match=(ip6 && tcp && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=(ip4 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=(ip6 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=(outport == @pg0 && ip6 && udp), dnl
ebb439
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
 ])
ebb439
 
ebb439
 ovn-nbctl --wait=sb acl-add pg0 to-lport 1001 "outport == @pg0 && ip" allow-related
ebb439
 
ebb439
 AT_CHECK([ovn-sbctl lflow-list sw0 | grep "ls_out_acl" | grep pg0 | sort], [0], [dnl
ebb439
   table=5 (ls_out_acl         ), priority=2001 , dnl
ebb439
-match=(reg0[[7]] == 1 && (outport == @pg0 && ip)), dnl
ebb439
-action=(reg0[[1]] = 1; next;)
ebb439
+match=(reg0[[7]] == 1 && (outport == @pg0 && ip)), action=(reg0[[1]] = 1; next;)
ebb439
   table=5 (ls_out_acl         ), priority=2001 , dnl
ebb439
 match=(reg0[[8]] == 1 && (outport == @pg0 && ip)), action=(next;)
ebb439
   table=5 (ls_out_acl         ), priority=2002 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip4 && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=((reg0[[10]] == 1) && outport == @pg0 && ip4 && udp), dnl
ebb439
+action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
   table=5 (ls_out_acl         ), priority=2002 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip6 && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2002 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip4 && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2002 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip6 && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip4 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip6 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=((reg0[[9]] == 1) && outport == @pg0 && ip4 && udp), dnl
ebb439
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
   table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip4 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=((reg0[[10]] == 1) && outport == @pg0 && ip6 && udp), dnl
ebb439
+action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
   table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip6 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2012 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip4 && tcp && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2012 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip6 && tcp && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2012 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip4 && tcp && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2012 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip6 && tcp && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip4 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip6 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip4 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip6 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=((reg0[[9]] == 1) && outport == @pg0 && ip6 && udp), dnl
ebb439
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
 ])
ebb439
 
ebb439
 AT_CHECK([ovn-sbctl lflow-list sw1 | grep "ls_out_acl" | grep pg0 | sort], [0], [dnl
ebb439
   table=5 (ls_out_acl         ), priority=2001 , dnl
ebb439
-match=(reg0[[7]] == 1 && (outport == @pg0 && ip)), dnl
ebb439
-action=(reg0[[1]] = 1; next;)
ebb439
+match=(reg0[[7]] == 1 && (outport == @pg0 && ip)), action=(reg0[[1]] = 1; next;)
ebb439
   table=5 (ls_out_acl         ), priority=2001 , dnl
ebb439
 match=(reg0[[8]] == 1 && (outport == @pg0 && ip)), action=(next;)
ebb439
   table=5 (ls_out_acl         ), priority=2002 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip4 && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=((reg0[[10]] == 1) && outport == @pg0 && ip4 && udp), dnl
ebb439
+action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
   table=5 (ls_out_acl         ), priority=2002 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip6 && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2002 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip4 && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2002 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip6 && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip4 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip6 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=((reg0[[9]] == 1) && outport == @pg0 && ip4 && udp), dnl
ebb439
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
   table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip4 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=((reg0[[10]] == 1) && outport == @pg0 && ip6 && udp), dnl
ebb439
+action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
   table=5 (ls_out_acl         ), priority=2003 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip6 && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2012 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip4 && tcp && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2012 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip6 && tcp && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2012 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip4 && tcp && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2012 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip6 && tcp && (outport == @pg0 && ip4 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip4 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=((reg0[[10]] == 1) && ip6 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip4 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
-  table=5 (ls_out_acl         ), priority=2013 , dnl
ebb439
-match=((reg0[[9]] == 1) && ip6 && tcp && (outport == @pg0 && ip6 && udp)), dnl
ebb439
-action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
+match=((reg0[[9]] == 1) && outport == @pg0 && ip6 && udp), dnl
ebb439
+action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=20); };)
ebb439
 ])
ebb439
 
ebb439
 AT_CLEANUP
ebb439
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
ebb439
index 60bd20fd4..091b61f91 100644
ebb439
--- a/tests/system-ovn.at
ebb439
+++ b/tests/system-ovn.at
ebb439
@@ -4473,9 +4473,6 @@ ovn-nbctl lsp-add sw0 sw0-p2-rej
ebb439
 ovn-nbctl lsp-set-addresses sw0-p2-rej "50:54:00:00:00:04 10.0.0.4 aef0::4"
ebb439
 ovn-nbctl lsp-set-port-security sw0-p2-rej "50:54:00:00:00:04 10.0.0.4 aef0::4"
ebb439
 
ebb439
-#ovn-nbctl --log acl-add sw0 from-lport 1000 "inport == \"sw0-p1\" && tcp && tcp.dst == 80" reject
ebb439
-#ovn-nbctl --log acl-add sw0 from-lport 1000 "inport == \"sw0-p2\" && ip6 && tcp && tcp.dst == 80" reject
ebb439
-
ebb439
 # Create port group and ACLs for sw0 ports.
ebb439
 ovn-nbctl pg-add pg0_drop sw0-p1-rej sw0-p2-rej
ebb439
 ovn-nbctl acl-add pg0_drop from-lport 1001 "inport == @pg0_drop && ip" drop
ebb439
@@ -4638,6 +4635,49 @@ aef0::3 udp port objcall" | uniq | wc -l)
ebb439
     test $c -eq 1
ebb439
 ])
ebb439
 
ebb439
+# Delete all the ACLs of pg0 and add the ACL with a generic match with reject action.
ebb439
+ovn-nbctl pg-del pg0
ebb439
+ovn-nbctl pg-add pg0 sw0-p1-rej sw0-p2-rej
ebb439
+ovn-nbctl --log acl-add pg0 from-lport 1004 "inport == @pg0 && ip && (tcp || udp)" reject
ebb439
+
ebb439
+OVS_WAIT_UNTIL([
ebb439
+    ip netns exec sw0-p1-rej nc  10.0.0.4 80 2> r
ebb439
+    res=$(cat r)
ebb439
+    echo "result = $res"
ebb439
+    test "$res" = "Ncat: Connection refused."
ebb439
+])
ebb439
+
ebb439
+OVS_WAIT_UNTIL([
ebb439
+    ip netns exec sw0-p2-rej nc -6 aef0::3 80 2> r
ebb439
+    res=$(cat r)
ebb439
+    test "$res" = "Ncat: Connection refused."
ebb439
+])
ebb439
+
ebb439
+rm -f *.pcap
ebb439
+
ebb439
+NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -n -c 1 -i sw0-p1-rej icmp > sw0-p1-rej-icmp.pcap &], [0])
ebb439
+
ebb439
+printf '.%.0s' {1..100} > foo
ebb439
+OVS_WAIT_UNTIL([
ebb439
+    ip netns exec sw0-p1-rej nc -u 10.0.0.4 90 < foo
ebb439
+    c=$(cat sw0-p1-rej-icmp.pcap | grep \
ebb439
+"10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port dnsix unreachable" | uniq | wc -l)
ebb439
+    test $c -eq 1
ebb439
+])
ebb439
+
ebb439
+rm -f *.pcap
ebb439
+# Now test for IPv6 UDP.
ebb439
+NS_CHECK_EXEC([sw0-p2-rej], [tcpdump -n -c 1 -i sw0-p2-rej icmp6 > sw0-p2-rej-icmp6.pcap &], [0])
ebb439
+
ebb439
+OVS_WAIT_UNTIL([
ebb439
+    ip netns exec sw0-p2-rej nc -u -6 aef0::3 90 < foo
ebb439
+    c=$(cat sw0-p2-rej-icmp6.pcap | grep \
ebb439
+"IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \
ebb439
+aef0::3 udp port dnsix" | uniq | wc -l)
ebb439
+    test $c -eq 1
ebb439
+])
ebb439
+
ebb439
+
ebb439
 OVS_APP_EXIT_AND_WAIT([ovn-controller])
ebb439
 
ebb439
 as ovn-sb
ebb439
-- 
ebb439
2.26.2
ebb439