[ovs-dev] [PATCH ovn] ovn-northd: Optimize logical flow generation for reject ACLs.

numans at ovn.org numans at ovn.org
Thu Sep 24 16:49:55 UTC 2020


From: Numan Siddique <numans at ovn.org>

ovn-northd adds below lflows for a reject ACL with a match - M

match = (ip4 && tcp && 'M') action = tcp_reject{}
match = (ip6 && tcp && 'M') action = tcp_reject{}
match = (ip4 && 'M') action = icmp4{}
match = (ip6 && 'M') action = icmp6{}

This approach has a couple of problems:
   - ovn-controller can reject the lflows if there are invalid matches.
     Eg. If match 'M' is - 'ip4 && udp'.

   - In a large scale deployment, this could result in lot of invalid
     logical flows and increase the size of the SB DB.

This patch addresses this problem by providing an option to the CMS
to specify the l3 protocol and l4 protocol as hints. A new column
'options' is added to the ACL table with the options -
options:l3-protocol and options:l4-protocol.

ovn-northd will now generate only the required lflows for the reject
ACL. If no options are set, then it falls back to the default scenario.

Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1876990
Reported-by: Ilya Maximets <i.maximets at ovn.org>
Signed-off-by: Numan Siddique <numans at ovn.org>
---
 northd/ovn-northd.c | 194 ++++++++++++++++++++----------
 ovn-nb.ovsschema    |   7 +-
 ovn-nb.xml          |  43 +++++++
 tests/ovn-northd.at | 285 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 461 insertions(+), 68 deletions(-)

diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 3324c9e81d..d167137e07 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -5372,73 +5372,135 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows,
     struct ds actions = DS_EMPTY_INITIALIZER;
     bool ingress = (stage == S_SWITCH_IN_ACL);
 
-    /* TCP */
-    build_acl_log(&actions, acl);
-    if (extra_match->length > 0) {
-        ds_put_format(&match, "(%s) && ", extra_match->string);
-    }
-    ds_put_format(&match, "ip4 && tcp && (%s)", acl->match);
-    ds_put_format(&actions, "reg0 = 0; "
-                  "eth.dst <-> eth.src; ip4.dst <-> ip4.src; "
-                  "tcp_reset { outport <-> inport; %s };",
-                  ingress ? "next(pipeline=egress,table=5);"
-                          : "next(pipeline=ingress,table=20);");
-    ovn_lflow_add_with_hint(lflows, od, stage,
-                            acl->priority + OVN_ACL_PRI_OFFSET + 10,
-                            ds_cstr(&match), ds_cstr(&actions), stage_hint);
-    ds_clear(&match);
-    ds_clear(&actions);
-    build_acl_log(&actions, acl);
-    if (extra_match->length > 0) {
-        ds_put_format(&match, "(%s) && ", extra_match->string);
-    }
-    ds_put_format(&match, "ip6 && tcp && (%s)", acl->match);
-    ds_put_format(&actions, "reg0 = 0; "
-                  "eth.dst <-> eth.src; ip6.dst <-> ip6.src; "
-                  "tcp_reset { outport <-> inport; %s };",
-                  ingress ? "next(pipeline=egress,table=5);"
-                          : "next(pipeline=ingress,table=20);");
-    ovn_lflow_add_with_hint(lflows, od, stage,
-                            acl->priority + OVN_ACL_PRI_OFFSET + 10,
-                            ds_cstr(&match), ds_cstr(&actions), stage_hint);
+    bool is_ip4 = true;
+    bool is_ip6 = true;
+    bool tcp_reset = true;
+    bool icmp_reset = true;
+    bool is_udp = false;
+
+    const char *l3_protocol = smap_get(&acl->options, "l3-protocol");
+    if (l3_protocol) {
+        if (!strcasecmp(l3_protocol, "ip")) {
+            is_ip4 = true;
+            is_ip6 = true;
+        } else if (!strcasecmp(l3_protocol, "ip4")) {
+            is_ip4 = true;
+            is_ip6 = false;
+        } else if (!strcasecmp(l3_protocol, "ip6")) {
+            is_ip6 = true;
+            is_ip4 = false;
+        }
+    }
+
+    const char *l4_protocol = smap_get(&acl->options, "l4-protocol");
+    if (l4_protocol) {
+        if (!strcasecmp(l4_protocol, "tcp")) {
+            tcp_reset = true;
+            icmp_reset = false;
+        } else if (!strcasecmp(l4_protocol, "udp")) {
+            tcp_reset = false;
+            is_udp = true;
+        } else {
+            tcp_reset = false;
+        }
+    }
 
-    /* IP traffic */
-    ds_clear(&match);
-    ds_clear(&actions);
-    build_acl_log(&actions, acl);
-    if (extra_match->length > 0) {
-        ds_put_format(&match, "(%s) && ", extra_match->string);
-    }
-    ds_put_format(&match, "ip4 && (%s)", acl->match);
-    if (extra_actions->length > 0) {
-        ds_put_format(&actions, "%s ", extra_actions->string);
-    }
-    ds_put_format(&actions, "reg0 = 0; "
-                  "icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; "
-                  "outport <-> inport; %s };",
-                  ingress ? "next(pipeline=egress,table=5);"
-                          : "next(pipeline=ingress,table=20);");
-    ovn_lflow_add_with_hint(lflows, od, stage,
-                            acl->priority + OVN_ACL_PRI_OFFSET,
-                            ds_cstr(&match), ds_cstr(&actions), stage_hint);
-    ds_clear(&match);
-    ds_clear(&actions);
-    build_acl_log(&actions, acl);
-    if (extra_match->length > 0) {
-        ds_put_format(&match, "(%s) && ", extra_match->string);
-    }
-    ds_put_format(&match, "ip6 && (%s)", acl->match);
-    if (extra_actions->length > 0) {
-        ds_put_format(&actions, "%s ", extra_actions->string);
-    }
-    ds_put_format(&actions, "reg0 = 0; icmp6 { "
-                  "eth.dst <-> eth.src; ip6.dst <-> ip6.src; "
-                  "outport <-> inport; %s };",
-                  ingress ? "next(pipeline=egress,table=5);"
-                          : "next(pipeline=ingress,table=20);");
-    ovn_lflow_add_with_hint(lflows, od, stage,
-                            acl->priority + OVN_ACL_PRI_OFFSET,
-                            ds_cstr(&match), ds_cstr(&actions), stage_hint);
+    if (is_ip4) {
+        if (tcp_reset) {
+            build_acl_log(&actions, acl);
+            if (extra_match->length > 0) {
+                ds_put_format(&match, "(%s) && ", extra_match->string);
+            }
+            ds_put_format(&match, "ip4 && tcp && (%s)", acl->match);
+            if (extra_actions->length > 0) {
+                ds_put_format(&actions, "%s ", extra_actions->string);
+            }
+            ds_put_format(&actions, "reg0 = 0; "
+                          "eth.dst <-> eth.src; ip4.dst <-> ip4.src; "
+                          "tcp_reset { outport <-> inport; %s };",
+                          ingress ? "next(pipeline=egress,table=5);"
+                                  : "next(pipeline=ingress,table=20);");
+            ovn_lflow_add_with_hint(lflows, od, stage,
+                                    acl->priority + OVN_ACL_PRI_OFFSET + 10,
+                                    ds_cstr(&match), ds_cstr(&actions),
+                                    stage_hint);
+        }
+
+        if (icmp_reset) {
+            ds_clear(&match);
+            ds_clear(&actions);
+            build_acl_log(&actions, acl);
+            if (extra_match->length > 0) {
+                ds_put_format(&match, "(%s) && ", extra_match->string);
+            }
+            ds_put_format(&match, "ip4 && (%s)", acl->match);
+            if (is_udp) {
+                ds_put_cstr(&match, " && udp");
+            }
+            if (extra_actions->length > 0) {
+                ds_put_format(&actions, "%s ", extra_actions->string);
+            }
+            ds_put_format(&actions, "reg0 = 0; "
+                          "icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; "
+                          "outport <-> inport; %s };",
+                          ingress ? "next(pipeline=egress,table=5);"
+                                  : "next(pipeline=ingress,table=20);");
+            ovn_lflow_add_with_hint(lflows, od, stage,
+                                    acl->priority + OVN_ACL_PRI_OFFSET,
+                                    ds_cstr(&match), ds_cstr(&actions),
+                                    stage_hint);
+        }
+    }
+
+    if (is_ip6) {
+        if (tcp_reset) {
+            ds_clear(&match);
+            ds_clear(&actions);
+            build_acl_log(&actions, acl);
+            if (extra_match->length > 0) {
+                ds_put_format(&match, "(%s) && ", extra_match->string);
+            }
+            ds_put_format(&match, "ip6 && tcp && (%s)", acl->match);
+            if (extra_actions->length > 0) {
+                ds_put_format(&actions, "%s ", extra_actions->string);
+            }
+            ds_put_format(&actions, "reg0 = 0; "
+                          "eth.dst <-> eth.src; ip6.dst <-> ip6.src; "
+                          "tcp_reset { outport <-> inport; %s };",
+                          ingress ? "next(pipeline=egress,table=5);"
+                                  : "next(pipeline=ingress,table=20);");
+            ovn_lflow_add_with_hint(lflows, od, stage,
+                                    acl->priority + OVN_ACL_PRI_OFFSET + 10,
+                                    ds_cstr(&match), ds_cstr(&actions),
+                                    stage_hint);
+        }
+
+        if (icmp_reset) {
+            ds_clear(&match);
+            ds_clear(&actions);
+            build_acl_log(&actions, acl);
+            if (extra_match->length > 0) {
+                ds_put_format(&match, "(%s) && ", extra_match->string);
+            }
+            ds_put_format(&match, "ip6 && (%s)", acl->match);
+            if (is_udp) {
+                ds_put_cstr(&match, " && udp");
+            }
+
+            if (extra_actions->length > 0) {
+                ds_put_format(&actions, "%s ", extra_actions->string);
+            }
+            ds_put_format(&actions, "reg0 = 0; icmp6 { "
+                          "eth.dst <-> eth.src; ip6.dst <-> ip6.src; "
+                          "outport <-> inport; %s };",
+                          ingress ? "next(pipeline=egress,table=5);"
+                                : "next(pipeline=ingress,table=20);");
+            ovn_lflow_add_with_hint(lflows, od, stage,
+                                    acl->priority + OVN_ACL_PRI_OFFSET,
+                                    ds_cstr(&match), ds_cstr(&actions),
+                                    stage_hint);
+        }
+    }
 
     ds_destroy(&match);
     ds_destroy(&actions);
diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
index 092322ab2c..00f1c7cd4b 100644
--- a/ovn-nb.ovsschema
+++ b/ovn-nb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Northbound",
-    "version": "5.27.0",
-    "cksum": "3507518247 26773",
+    "version": "5.28.0",
+    "cksum": "699859908 26928",
     "tables": {
         "NB_Global": {
             "columns": {
@@ -225,6 +225,9 @@
                                                         "debug"]]},
                                       "min": 0, "max": 1}},
                 "meter": {"type": {"key": "string", "min": 0, "max": 1}},
+                "options": {
+                    "type": {"key": "string", "value": "string",
+                             "min": 0, "max": "unlimited"}},
                 "external_ids": {
                     "type": {"key": "string", "value": "string",
                              "min": 0, "max": "unlimited"}}},
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 86195af341..2c3497e2ae 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -1721,6 +1721,49 @@
       </ul>
     </column>
 
+    <group title="Common options">
+      <column name="options">
+        This column provides general key/value settings. The supported
+        options are described individually below.
+      </column>
+
+      <group title="Options for providing protocol hints for reject ACL.">
+        <p>
+          The ACL match specified in the
+          <ref column="match" table="ACL" db="OVN_Northbound"/> column is
+          opaque to <code>OVN</code> and <code>ovn-northd</code> doesn't
+          look into the match fields.
+          These options can be specified by CMS to provide hints to
+          <code>OVN</code> about the L3 and L4 protocol matches for the reject
+          ACL. <code>ovn-northd</code> uses these options if set to use
+          appropriate actions when generating logical flows.
+        </p>
+
+        <p>
+          If these options are not set, then <code>ovn-northd</code> assumes
+          the reject ACL applies to IPv4, IPv6 and TCP packets.
+        </p>
+
+        <column name="options" key="l3-protocol">
+          The possible values are <code>ip</code>, <code>ip4</code> and
+          <code>ip6</code>. If the value is <code>ip</code>, it means the
+          reject ACL action applies to both IPv4 and IPv6 packets. If the
+          value is <code>ip4</code>, it means the reject ACL action applies to
+          IPv4 packets and the value <code>ip6</code> applies to IPv6 packets.
+        </column>
+
+        <column name="options" key="l4-protocol">
+          <p>
+            The possible values are <code>tcp</code> and <code>udp</code>.
+            If the value is <code>tcp</code>, it means the
+            reject ACL action applies to TCP packets. If the
+            value is <code>udp</code>, it means the reject ACL action applies
+            to UDP packets.
+          </p>
+        </column>
+      </group>
+    </group>
+
     <group title="Logging">
       <p>
         These columns control whether and how OVN logs packets that match an
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 99a9204f1f..4a30f8ed07 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -2010,3 +2010,288 @@ ovn-nbctl --wait=sb set NB_Global . options:ignore_lsp_down=true
 AT_CHECK([ovn-sbctl lflow-list | grep arp | grep 10\.0\.0\.1], [0], [ignore])
 
 AT_CLEANUP
+
+AT_SETUP([ovn-northd -- ACL reject flows])
+ovn_start
+
+ovn-nbctl ls-add sw0
+ovn-nbctl lsp-add sw0 sw0-p1
+ovn-nbctl lsp-add sw0 sw0-p2
+
+ovn-nbctl pg-add pg0 sw0-p1 sw0-p2
+ovn-nbctl acl-add pg0 to-lport 1002 "inport == @pg0 && ip" reject
+
+ovn-nbctl --wait=sb sync
+
+# If there is a reject ACL wihtout any protocol hints, then ovn-northd should
+# generate lflows with ip4 tcp_reset, icmp4, ip6 tcp_reset and icmp6 actions.
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=(ip4 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=(ip6 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=(ip4 && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=(ip6 && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+# Set l3-protocol=ip4 for the reject ACL.
+ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip4
+
+# ovn-northd should generate  2 lflows with ip4 tcp_reset and icmp4 actions.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=(ip4 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=(ip4 && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+# Set l4-protocol=tcp for the reject ACL.
+ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp
+
+# ovn-northd should generate 1 lflow with ip4 tcp_reset action.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=(ip4 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+])
+
+# Set l4-protocol=udp for the reject ACL.
+ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp
+
+# ovn-northd should generate 1 lflow with udp match and icmp4 action.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=(ip4 && (inport == @pg0 && ip) && udp), dnl
+action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+# Remove l4-protocol from the reject ACL.
+ovn-nbctl --wait=sb remove ACL . options l4-protocol
+
+# ovn-northd should generate 2 lflow with tcp_reset and icmp4 action.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=(ip4 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=(ip4 && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+# Set l3-protocol to ip.
+ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip
+
+# ovn-northd should generate 4 lflow with ip4 tcp_reset, ip6 tcp_reset, icmp4 and icmp6 actions.
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=(ip4 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=(ip6 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=(ip4 && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=(ip6 && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+# Set l3-protocol=ip6 for the reject ACL.
+ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip6
+
+# ovn-northd should generate  2 lflows with ip6 tcp_reset and icmp6 actions.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=(ip6 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=(ip6 && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+# Set l4-protocol=tcp for the reject ACL.
+ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp
+
+# ovn-northd should generate 1 lflow with ip6 tcp_reset action.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=(ip6 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+])
+
+# Set l4-protocol=udp for the reject ACL.
+ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp
+
+# ovn-northd should generate 1 lflow with udp match and icmp6 action.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=(ip6 && (inport == @pg0 && ip) && udp), dnl
+action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL.
+ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip
+ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp
+
+# ovn-northd should generate 2 lflow with ip4 tcp_reset and ip6 tcp_reset actions.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=(ip4 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=(ip6 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+])
+
+# Set l3-protocol to ip and l4-protocol=udp for the reject ACL.
+ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip
+ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp
+
+# ovn-northd should generate 2 lflows (udp match) with icmp4 and icmp6 actions.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=(ip4 && (inport == @pg0 && ip) && udp), dnl
+action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=(ip6 && (inport == @pg0 && ip) && udp), dnl
+action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+# Add an ACL with allow-related
+ovn-nbctl --wait=sb acl-add pg0 to-lport 1000 "ip" allow-related
+
+# ovn-northd should generate 4 lflow with 2 icmp4 and 2 icmp6 actions.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl\
+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); };)
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl
+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); };)
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl
+action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl
+action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL.
+rej_acl=$(ovn-nbctl --bare --columns _uuid  find ACL action=reject)
+ovn-nbctl --wait=sb set ACL $rej_acl options:l3-protocol=ip
+ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp
+
+# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 tcp_reset actions.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl
+action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl
+action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+])
+
+
+# Clear l3-protocol and set l4-protocol to udp
+ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol
+ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=udp
+
+# ovn-northd should generate 4 lflows (with udp match) with 2 icmp4 and 2 icmp6 actions.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl\
+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); };)
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl
+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); };)
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl
+action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2002 , dnl
+match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl
+action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+# Clear l3-protocol and set l4-protocol to tcp
+ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol
+ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp
+
+# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 tcp_reset actions.
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl
+action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl
+action=(ct_commit { ct_label.blocked = 1; };  reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+  table=5 (ls_out_acl         ), priority=2012 , dnl
+match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl
+action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };)
+])
+
+AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl
+])
+
+AT_CLEANUP
-- 
2.26.2



More information about the dev mailing list