Thanks for the update, Lorenzo. Looks good!

Acked-by: Mark Michelson <[email protected]>

On 12/8/22 12:15, Lorenzo Bianconi wrote:
In the current codebase ct_commit {} action clears ct_state metadata of
the incoming packet. This behaviour introduces an issue if we need to
check the connection tracking state in the subsequent pipeline stages,
e.g. for hairpin traffic:

table=14(ls_in_pre_hairpin  ), priority=100  , match=(ip && ct.trk), 
action=(reg0[6] = chk_lb_hairpin(); reg0[12] = chk_lb_hairpin_reply(); next;)

Fix the issue introducing ct_commit_continue action used to allow the ct
packet to proceed in the pipeline instead of the original one.

Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2103086
Signed-off-by: Lorenzo Bianconi <[email protected]>
---
Changes since v2:
- add ovn system-tests for ct_commit_continue
Changes since v1:
- introduce new nested action ct_commit_continue instead of modifying
   ct_commit_v2
---
  controller/chassis.c    |  7 +++++
  include/ovn/actions.h   |  2 ++
  include/ovn/features.h  |  1 +
  lib/actions.c           | 61 ++++++++++++++++++++++++++++++++++++++---
  northd/northd.c         | 40 +++++++++++++++++++++++----
  northd/northd.h         |  2 ++
  northd/ovn-northd.8.xml |  7 +++++
  ovn-sb.xml              | 15 ++++++++++
  tests/ovn-controller.at | 44 +++++++++++++++++++++++++++++
  tests/ovn-northd.at     |  8 +++---
  tests/ovn.at            |  4 +++
  tests/system-ovn.at     | 24 ++++++++++++++--
  utilities/ovn-trace.c   |  2 ++
  13 files changed, 201 insertions(+), 16 deletions(-)

diff --git a/controller/chassis.c b/controller/chassis.c
index 685d9b2ae..8dc7ecc07 100644
--- a/controller/chassis.c
+++ b/controller/chassis.c
@@ -352,6 +352,7 @@ chassis_build_other_config(const struct ovs_chassis_cfg 
*ovs_cfg,
      smap_replace(config, OVN_FEATURE_PORT_UP_NOTIF, "true");
      smap_replace(config, OVN_FEATURE_CT_NO_MASKED_LABEL, "true");
      smap_replace(config, OVN_FEATURE_MAC_BINDING_TIMESTAMP, "true");
+    smap_replace(config, OVN_FEATURE_CT_COMMIT_CONTINUE, "true");
  }
/*
@@ -469,6 +470,12 @@ chassis_other_config_changed(const struct ovs_chassis_cfg 
*ovs_cfg,
          return true;
      }
+ if (!smap_get_bool(&chassis_rec->other_config,
+                       OVN_FEATURE_CT_COMMIT_CONTINUE,
+                       false)) {
+        return true;
+    }
+
      return false;
  }
diff --git a/include/ovn/actions.h b/include/ovn/actions.h
index a56351081..927818976 100644
--- a/include/ovn/actions.h
+++ b/include/ovn/actions.h
@@ -66,6 +66,7 @@ struct ovn_extend_table;
      OVNACT(CT_NEXT,           ovnact_ct_next)         \
      OVNACT(CT_COMMIT_V1,      ovnact_ct_commit_v1)    \
      OVNACT(CT_COMMIT_V2,      ovnact_nest)            \
+    OVNACT(CT_COMMIT_CONTINUE, ovnact_nest)           \
      OVNACT(CT_DNAT,           ovnact_ct_nat)          \
      OVNACT(CT_SNAT,           ovnact_ct_nat)          \
      OVNACT(CT_DNAT_IN_CZONE,  ovnact_ct_nat)          \
@@ -321,6 +322,7 @@ struct ovnact_nest {
      struct ovnact ovnact;
      struct ovnact *nested;
      size_t nested_len;
+    uint8_t ltable;             /* Logical table ID of next table. */
  };
/* OVNACT_GET_ARP, OVNACT_GET_ND. */
diff --git a/include/ovn/features.h b/include/ovn/features.h
index 679f67457..0ad8a27b9 100644
--- a/include/ovn/features.h
+++ b/include/ovn/features.h
@@ -24,6 +24,7 @@
  #define OVN_FEATURE_PORT_UP_NOTIF      "port-up-notif"
  #define OVN_FEATURE_CT_NO_MASKED_LABEL "ct-no-masked-label"
  #define OVN_FEATURE_MAC_BINDING_TIMESTAMP "mac-binding-timestamp"
+#define OVN_FEATURE_CT_COMMIT_CONTINUE "ct-commit-continue"
/* OVS datapath supported features. Based on availability OVN might generate
   * different types of openflows.
diff --git a/lib/actions.c b/lib/actions.c
index 47ec654e1..807b84127 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -766,6 +766,13 @@ parse_CT_COMMIT(struct action_context *ctx)
      if (ctx->lexer->token.type == LEX_T_LCURLY) {
          parse_nested_action(ctx, OVNACT_CT_COMMIT_V2, "ip",
                              WR_CT_COMMIT);
+
+        if (ctx->lexer->error) {
+            return;
+        }
+
+        struct ovnact_nest *on = ctx->ovnacts->header;
+        on->ltable = 0;
      } else if (ctx->lexer->token.type == LEX_T_LPAREN) {
          parse_CT_COMMIT_V1(ctx);
      } else {
@@ -775,6 +782,7 @@ parse_CT_COMMIT(struct action_context *ctx)
                                              OVNACT_ALIGN(sizeof *on));
          on->nested_len = 0;
          on->nested = NULL;
+        on->ltable = 0;
      }
  }
@@ -871,13 +879,13 @@ format_CT_COMMIT_V2(const struct ovnact_nest *on, struct ds *s)
  }
static void
-encode_CT_COMMIT_V2(const struct ovnact_nest *on,
-                    const struct ovnact_encode_params *ep OVS_UNUSED,
-                    struct ofpbuf *ofpacts)
+encode_ct_commit_nested(const struct ovnact_nest *on,
+                        const struct ovnact_encode_params *ep,
+                        uint8_t recirc_table, struct ofpbuf *ofpacts)
  {
      struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts);
      ct->flags = NX_CT_F_COMMIT;
-    ct->recirc_table = NX_CT_RECIRC_NONE;
+    ct->recirc_table = recirc_table;
      ct->zone_src.field = ep->is_switch
          ? mf_from_id(MFF_LOG_CT_ZONE)
          : mf_from_id(MFF_LOG_DNAT_ZONE);
@@ -907,6 +915,49 @@ encode_CT_COMMIT_V2(const struct ovnact_nest *on,
      ct = ofpacts->header;
      ofpact_finish(ofpacts, &ct->ofpact);
  }
+
+static void
+encode_CT_COMMIT_V2(const struct ovnact_nest *on,
+                    const struct ovnact_encode_params *ep,
+                    struct ofpbuf *ofpacts)
+{
+    encode_ct_commit_nested(on, ep, NX_CT_RECIRC_NONE, ofpacts);
+}
+
+static void
+parse_CT_COMMIT_CONTINUE(struct action_context *ctx)
+{
+    int table = ctx->pp->cur_ltable + 1;
+    if (table >= ctx->pp->n_tables) {
+        table = 0;
+    }
+    parse_nested_action(ctx, OVNACT_CT_COMMIT_CONTINUE, "ip",
+                        WR_CT_COMMIT);
+
+    struct ovnact_nest *on = ctx->ovnacts->header;
+    on->ltable = table;
+}
+
+static void
+format_CT_COMMIT_CONTINUE(const struct ovnact_nest *on, struct ds *s)
+{
+    if (on->nested_len) {
+        format_nested_action(on, "ct_commit_continue", s);
+    } else {
+        ds_put_cstr(s, "ct_commit_continue;");
+    }
+}
+
+static void
+encode_CT_COMMIT_CONTINUE(const struct ovnact_nest *on,
+                          const struct ovnact_encode_params *ep,
+                          struct ofpbuf *ofpacts)
+{
+    uint8_t recirc_table = first_ptable(ep, ep->pipeline) + on->ltable;
+
+    encode_ct_commit_nested(on, ep, recirc_table, ofpacts);
+}
+
  
  static void
  parse_ct_nat(struct action_context *ctx, const char *name,
@@ -5288,6 +5339,8 @@ parse_action(struct action_context *ctx)
          parse_DEC_TTL(ctx);
      } else if (lexer_match_id(ctx->lexer, "ct_next")) {
          parse_CT_NEXT(ctx);
+    } else if (lexer_match_id(ctx->lexer, "ct_commit_continue")) {
+        parse_CT_COMMIT_CONTINUE(ctx);
      } else if (lexer_match_id(ctx->lexer, "ct_commit")) {
          parse_CT_COMMIT(ctx);
      } else if (lexer_match_id(ctx->lexer, "ct_dnat")) {
diff --git a/northd/northd.c b/northd/northd.c
index 7c48bb3b4..b4e7c3083 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -446,6 +446,14 @@ build_chassis_features(const struct northd_input 
*input_data,
              chassis_features->mac_binding_timestamp) {
              chassis_features->mac_binding_timestamp = false;
          }
+
+        bool ct_commit_continue =
+            smap_get_bool(&chassis->other_config,
+                          OVN_FEATURE_CT_COMMIT_CONTINUE,
+                          false);
+        if (!ct_commit_continue && chassis_features->ct_commit_continue) {
+            chassis_features->ct_commit_continue = false;
+        }
      }
  }
  
@@ -5494,6 +5502,7 @@ ls_get_acl_flags(struct ovn_datapath *od)
  {
      od->has_acls = false;
      od->has_stateful_acl = false;
+    od->has_apply_after_lb_acls = false;
if (od->nbs->n_acls) {
          od->has_acls = true;
@@ -5502,7 +5511,9 @@ ls_get_acl_flags(struct ovn_datapath *od)
              struct nbrec_acl *acl = od->nbs->acls[i];
              if (!strcmp(acl->action, "allow-related")) {
                  od->has_stateful_acl = true;
-                return;
+            }
+            if (smap_get_bool(&acl->options, "apply-after-lb", false)) {
+                od->has_apply_after_lb_acls = true;
              }
          }
      }
@@ -5516,7 +5527,9 @@ ls_get_acl_flags(struct ovn_datapath *od)
                  struct nbrec_acl *acl = ls_pg->nb_pg->acls[i];
                  if (!strcmp(acl->action, "allow-related")) {
                      od->has_stateful_acl = true;
-                    return;
+                }
+                if (smap_get_bool(&acl->options, "apply-after-lb", false)) {
+                    od->has_apply_after_lb_acls = true;
                  }
              }
          }
@@ -7467,9 +7480,17 @@ build_stateful(struct ovn_datapath *od,
       * We always set ct_mark.blocked to 0 here as
       * any packet that makes it this far is part of a connection we
       * want to allow to continue. */
-    ds_put_format(&actions, "ct_commit { %s = 0; "
-                            "ct_label.label = " REG_LABEL "; }; next;",
-                  ct_block_action);
+    if (features->ct_commit_continue && od->has_apply_after_lb_acls) {
+        ds_put_format(&actions,
+                      "ct_commit_continue { %s = 0; "
+                      "ct_label.label = " REG_LABEL "; };",
+                      ct_block_action);
+    } else {
+        ds_put_format(&actions,
+                      "ct_commit { %s = 0; "
+                      "ct_label.label = " REG_LABEL "; }; next;",
+                      ct_block_action);
+    }
      ovn_lflow_add(lflows, od, S_SWITCH_IN_STATEFUL, 100,
                    REGBIT_CONNTRACK_COMMIT" == 1 && "
                    REGBIT_ACL_LABEL" == 1",
@@ -7484,7 +7505,13 @@ build_stateful(struct ovn_datapath *od,
       * any packet that makes it this far is part of a connection we
       * want to allow to continue. */
      ds_clear(&actions);
-    ds_put_format(&actions, "ct_commit { %s = 0; }; next;", ct_block_action);
+    if (features->ct_commit_continue && od->has_apply_after_lb_acls) {
+        ds_put_format(&actions, "ct_commit_continue { %s = 0; };",
+                      ct_block_action);
+    } else {
+        ds_put_format(&actions, "ct_commit { %s = 0; }; next;",
+                      ct_block_action);
+    }
      ovn_lflow_add(lflows, od, S_SWITCH_IN_STATEFUL, 100,
                    REGBIT_CONNTRACK_COMMIT" == 1 && "
                    REGBIT_ACL_LABEL" == 0",
@@ -15895,6 +15922,7 @@ northd_init(struct northd_data *data)
      data->features = (struct chassis_features) {
          .ct_no_masked_label = true,
          .mac_binding_timestamp = true,
+        .ct_commit_continue = true,
      };
      data->ovn_internal_version_changed = false;
  }
diff --git a/northd/northd.h b/northd/northd.h
index 7942c0a34..fee68d1e7 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -69,6 +69,7 @@ struct northd_input {
  struct chassis_features {
      bool ct_no_masked_label;
      bool mac_binding_timestamp;
+    bool ct_commit_continue;
  };
struct northd_data {
@@ -211,6 +212,7 @@ struct ovn_datapath {
      bool has_unknown;
      bool has_acls;
      bool has_vtep_lports;
+    bool has_apply_after_lb_acls;
/* IPAM data. */
      struct ipam_info ipam_info;
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index dffbba96d..6a6425dd4 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -1108,6 +1108,13 @@
          action based on a hint provided by the previous tables (with a match
          for <code>reg0[1] == 1 &amp;&amp; reg0[13] == 0</code>).
        </li>
+
+      <li>
+        If the ACL is configured with <code>apply-after-lb</code> option,
+        <code>ct_commit_continue</code> action will be used instead of
+        <code>ct_commit</code> in order to preserve ct_state metadata.
+      </li>
+
        <li>
          A priority-0 flow that simply moves traffic to the next table.
        </li>
diff --git a/ovn-sb.xml b/ovn-sb.xml
index 4f485b860..6f759b428 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -1408,6 +1408,21 @@
            </p>
          </dd>
+ <dt><code>ct_commit_continue { };</code></dt>
+        <dt><code>ct_commit_continue { ct_mark=<var>value[/mask]</var>; 
};</code></dt>
+        <dt><code>ct_commit_continue { ct_label=<var>value[/mask]</var>; 
};</code></dt>
+        <dt><code>ct_commit_continue { ct_mark=<var>value[/mask]</var>; 
ct_label=<var>value[/mask]</var>; };</code></dt>
+
+        <dd>
+          <p>
+            <code>ct_commit_continue</code> action exports the same features
+            supported by <code>ct_commit</code> but allow the packet committed
+            to the ct table to continue the processing in the next pipeline
+            stage. This is useful to maintain ct metadata of the processed
+            packet.
+          </p>
+        </dd>
+
          <dt><code>ct_dnat;</code></dt>
          <dt><code>ct_dnat(<var>IP</var>);</code></dt>
          <dd>
diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
index 6bc9ba75d..efdc3948a 100644
--- a/tests/ovn-controller.at
+++ b/tests/ovn-controller.at
@@ -2499,3 +2499,47 @@ AT_CHECK([GET_LOCAL_TEMPLATE_VARS], [1], [])
AT_CLEANUP
  ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([ovn-controller - ct_commit_continue])
+AT_KEYWORDS([ct_commit_continue])
+
+ovn_start
+
+net_add n1
+sim_add hv1
+ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.1
+
+check ovn-nbctl ls-add sw0 \
+    -- lsp-add sw0 sw0-p0  \
+    -- lsp-set-addresses sw0-p0 "00:00:00:00:00:01 192.168.1.1"
+
+as hv1
+ovs-vsctl \
+    -- add-port br-int vif0 \
+    -- set Interface vif0 external_ids:iface-id=sw0-p0
+
+check ovn-nbctl pg-add pg0 sw0-p0
+check ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1004 "ip4 && ip4.dst == 
192.168.1.2" drop
+check ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip4 && tcp" 
allow-related
+check ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1003 "ip4 && icmp" 
allow-related
+check ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1001 "ip4" drop
+
+check ovn-nbctl lb-add lb0 192.168.1.10 192.168.1.2
+check ovn-nbctl ls-lb-add sw0 lb0
+
+check ovn-nbctl --wait=hv sync
+wait_for_ports_up
+
+AT_CHECK([ovn-sbctl dump-flows sw0 | grep ls_in_stateful | grep -q 
ct_commit_continue])
+
+AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=23 | grep table=24 | sed -e 
's/cookie=0x[[a-z,0-9]]*/cookie=0x0/; 
s/duration=[[0-9]]*.[[0-9]]*s/duration=<cleared>/' |sort], [0], [dnl
+ cookie=0x0 duration=<cleared>, table=23, n_packets=0, n_bytes=0, idle_age=0, 
priority=100,ip,reg0=0x2/0x2002,metadata=0x1 
actions=ct(commit,table=24,zone=NXM_NX_REG13[[0..15]],nat(src),exec(load:0->NXM_NX_CT_MARK[[0]]))
+ cookie=0x0 duration=<cleared>, table=23, n_packets=0, n_bytes=0, idle_age=0, 
priority=100,ip,reg0=0x2002/0x2002,metadata=0x1 
actions=ct(commit,table=24,zone=NXM_NX_REG13[[0..15]],nat(src),exec(load:0->NXM_NX_CT_MARK[[0]],move:NXM_NX_XXREG0[[0..31]]->NXM_NX_CT_LABEL[[96..127]]))
+ cookie=0x0 duration=<cleared>, table=23, n_packets=0, n_bytes=0, idle_age=0, 
priority=100,ipv6,reg0=0x2/0x2002,metadata=0x1 
actions=ct(commit,table=24,zone=NXM_NX_REG13[[0..15]],nat(src),exec(load:0->NXM_NX_CT_MARK[[0]]))
+ cookie=0x0 duration=<cleared>, table=23, n_packets=0, n_bytes=0, idle_age=0, 
priority=100,ipv6,reg0=0x2002/0x2002,metadata=0x1 
actions=ct(commit,table=24,zone=NXM_NX_REG13[[0..15]],nat(src),exec(load:0->NXM_NX_CT_MARK[[0]],move:NXM_NX_XXREG0[[0..31]]->NXM_NX_CT_LABEL[[96..127]]))
+])
+
+AT_CLEANUP
+])
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index ca4263eac..68440d318 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -6623,8 +6623,8 @@ AT_CHECK([grep -e "ls_in_lb " lsflows | sed 
's/table=../table=??/' | sort], [0],
AT_CHECK([grep -e "ls_in_stateful" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl
    table=??(ls_in_stateful     ), priority=0    , match=(1), action=(next;)
-  table=??(ls_in_stateful     ), priority=100  , match=(reg0[[1]] == 1 && 
reg0[[13]] == 0), action=(ct_commit { ct_mark.blocked = 0; }; next;)
-  table=??(ls_in_stateful     ), priority=100  , match=(reg0[[1]] == 1 && 
reg0[[13]] == 1), action=(ct_commit { ct_mark.blocked = 0; ct_label.label = reg3; }; 
next;)
+  table=??(ls_in_stateful     ), priority=100  , match=(reg0[[1]] == 1 && 
reg0[[13]] == 0), action=(ct_commit_continue { ct_mark.blocked = 0; };)
+  table=??(ls_in_stateful     ), priority=100  , match=(reg0[[1]] == 1 && 
reg0[[13]] == 1), action=(ct_commit_continue { ct_mark.blocked = 0; ct_label.label = 
reg3; };)
  ])
AS_BOX([Remove and add the ACLs back with a few ACLs with apply-after-lb option])
@@ -6676,8 +6676,8 @@ AT_CHECK([grep -e "ls_in_lb " lsflows | sed 
's/table=../table=??/' | sort], [0],
AT_CHECK([grep -e "ls_in_stateful" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl
    table=??(ls_in_stateful     ), priority=0    , match=(1), action=(next;)
-  table=??(ls_in_stateful     ), priority=100  , match=(reg0[[1]] == 1 && 
reg0[[13]] == 0), action=(ct_commit { ct_mark.blocked = 0; }; next;)
-  table=??(ls_in_stateful     ), priority=100  , match=(reg0[[1]] == 1 && 
reg0[[13]] == 1), action=(ct_commit { ct_mark.blocked = 0; ct_label.label = reg3; }; 
next;)
+  table=??(ls_in_stateful     ), priority=100  , match=(reg0[[1]] == 1 && 
reg0[[13]] == 0), action=(ct_commit_continue { ct_mark.blocked = 0; };)
+  table=??(ls_in_stateful     ), priority=100  , match=(reg0[[1]] == 1 && 
reg0[[13]] == 1), action=(ct_commit_continue { ct_mark.blocked = 0; ct_label.label = 
reg3; };)
  ])
AT_CLEANUP
diff --git a/tests/ovn.at b/tests/ovn.at
index f3bd53242..ed4a2f50d 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1187,6 +1187,10 @@ ct_commit { ct_mark=1; };
      formats as ct_commit { ct_mark = 1; };
      encodes as 
ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark))
      has prereqs ip
+ct_commit_continue { ct_mark=1; };
+    formats as ct_commit_continue { ct_mark = 1; };
+    encodes as 
ct(commit,table=19,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark))
+    has prereqs ip
  ct_commit { ct_mark=1/1; };
      formats as ct_commit { ct_mark = 1/1; };
      encodes as 
ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_mark))
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index b99578b9e..717bc74ed 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -4664,7 +4664,7 @@ ADD_VETH(lsp, lsp, br-int, "42.42.42.1/24", 
"00:00:00:00:00:01", \
  ovn-nbctl --wait=hv -t 3 sync
# Start IPv4 TCP server on lsp.
-NS_CHECK_EXEC([lsp], [timeout 2s nc -k -l 42.42.42.1 4041 &], [0])
+NETNS_DAEMONIZE([lsp], [nc -l -k 42.42.42.1 4041], [lsp0.pid])
# Check that IPv4 TCP hairpin connection succeeds on both VIPs.
  NS_CHECK_EXEC([lsp], [nc 88.88.88.88 8080 -z], [0], [ignore], [ignore])
@@ -4686,6 +4686,16 @@ OVS_WAIT_UNTIL([
      test "${total_pkts}" = "2"
  ])
+ovn-nbctl pg-add pg0 lsp
+ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1004 "ip4 && ip4.dst == 
10.0.0.2" drop
+ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip4 && tcp" 
allow-related
+ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip4 && udp" allow
+ovn-nbctl --wait=hv sync
+
+## Check that IPv4 TCP hairpin connection succeeds on both VIPs.
+NS_CHECK_EXEC([lsp], [nc 88.88.88.88 8080 -z], [0], [ignore], [ignore])
+NS_CHECK_EXEC([lsp], [nc 88.88.88.89 8080 -z], [0], [ignore], [ignore])
+
  OVS_APP_EXIT_AND_WAIT([ovn-controller])
as ovn-sb
@@ -4750,7 +4760,7 @@ OVS_WAIT_UNTIL([test "$(ip netns exec lsp ip a | grep 4200::1 
| grep tentative)"
  ovn-nbctl --wait=hv -t 3 sync
# Start IPv6 TCP server on lsp.
-NS_CHECK_EXEC([lsp], [timeout 2s nc -k -l 4200::1 4041 &], [0])
+NETNS_DAEMONIZE([lsp], [nc -l -k 4200::1 4041], [lsp0.pid])
# Check that IPv6 TCP hairpin connection succeeds on both VIPs.
  NS_CHECK_EXEC([lsp], [nc 8800::0088 8080 -z], [0], [ignore], [ignore])
@@ -4772,6 +4782,16 @@ OVS_WAIT_UNTIL([
      test "${total_pkts}" = "2"
  ])
+ovn-nbctl pg-add pg0 lsp
+ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip6 && tcp" 
allow-related
+ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip6 && udp" allow
+ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1000 "ip6" drop
+ovn-nbctl --wait=hv sync
+
+# Check that IPv6 TCP hairpin connection succeeds on both VIPs.
+NS_CHECK_EXEC([lsp], [nc 8800::0088 8080 -z], [0], [ignore], [ignore])
+NS_CHECK_EXEC([lsp], [nc 8800::0089 8080 -z], [0], [ignore], [ignore])
+
  OVS_APP_EXIT_AND_WAIT([ovn-controller])
as ovn-sb
diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
index 79ed5a9af..e1def9eea 100644
--- a/utilities/ovn-trace.c
+++ b/utilities/ovn-trace.c
@@ -3098,6 +3098,8 @@ trace_actions(const struct ovnact *ovnacts, size_t 
ovnacts_len,
          case OVNACT_CT_COMMIT_V2:
              /* Nothing to do. */
              break;
+        case OVNACT_CT_COMMIT_CONTINUE:
+            break;
case OVNACT_CT_DNAT:
              execute_ct_nat(ovnact_get_CT_DNAT(a), dp, uflow, pipeline, super);

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

Reply via email to