28d94b
diff --git a/.ci/ovn-kubernetes/Dockerfile b/.ci/ovn-kubernetes/Dockerfile
28d94b
index e74b620be..1884724ec 100644
28d94b
--- a/.ci/ovn-kubernetes/Dockerfile
28d94b
+++ b/.ci/ovn-kubernetes/Dockerfile
28d94b
@@ -1,5 +1,5 @@
28d94b
 ARG OVNKUBE_COMMIT=master
28d94b
-ARG LIBOVSDB_COMMIT=8081fe24e48f
28d94b
+ARG LIBOVSDB_COMMIT=a6a173993830
28d94b
 
28d94b
 FROM fedora:35 AS ovnbuilder
28d94b
 
28d94b
@@ -47,9 +47,17 @@ RUN GO111MODULE=on go install github.com/ovn-org/libovsdb/cmd/modelgen@${LIBOVSD
28d94b
 # Clone OVN Kubernetes and build the binary based on the commit passed as argument
28d94b
 WORKDIR /root
28d94b
 RUN git clone https://github.com/ovn-org/ovn-kubernetes.git
28d94b
-WORKDIR /root/ovn-kubernetes/go-controller
28d94b
+WORKDIR /root/ovn-kubernetes
28d94b
 RUN git checkout ${OVNKUBE_COMMIT} && git log -n 1
28d94b
 
28d94b
+# Copy the ovn-kubernetes scripts from the OVN sources and apply any
28d94b
+# custom changes if needed.
28d94b
+RUN mkdir -p /tmp/ovn/.ci/ovn-kubernetes
28d94b
+COPY .ci/ovn-kubernetes /tmp/ovn/.ci/ovn-kubernetes
28d94b
+WORKDIR /tmp/ovn
28d94b
+RUN .ci/ovn-kubernetes/prepare.sh /root/ovn-kubernetes
28d94b
+
28d94b
+WORKDIR /root/ovn-kubernetes/go-controller
28d94b
 # Make sure we use the OVN NB/SB schema from the local code.
28d94b
 COPY --from=ovnbuilder /tmp/ovn/ovn-nb.ovsschema pkg/nbdb/ovn-nb.ovsschema
28d94b
 COPY --from=ovnbuilder /tmp/ovn/ovn-sb.ovsschema pkg/sbdb/ovn-sb.ovsschema
28d94b
diff --git a/.ci/ovn-kubernetes/custom.patch b/.ci/ovn-kubernetes/custom.patch
28d94b
new file mode 100644
28d94b
index 000000000..e69de29bb
28d94b
diff --git a/.ci/ovn-kubernetes/prepare.sh b/.ci/ovn-kubernetes/prepare.sh
28d94b
new file mode 100755
28d94b
index 000000000..8fc9652af
28d94b
--- /dev/null
28d94b
+++ b/.ci/ovn-kubernetes/prepare.sh
28d94b
@@ -0,0 +1,20 @@
28d94b
+#!/bin/bash
28d94b
+
28d94b
+set -ev
28d94b
+
28d94b
+ovnk8s_path=$1
28d94b
+topdir=$PWD
28d94b
+
28d94b
+pushd ${ovnk8s_path}
28d94b
+
28d94b
+# Add here any custom operations that need to performed on the
28d94b
+# ovn-kubernetes cloned repo, e.g., custom patches.
28d94b
+
28d94b
+# git apply --allow-empty is too new so not all git versions from major
28d94b
+# distros support it, just check if the custom patch file is not empty
28d94b
+# before applying it.
28d94b
+[ -s ${topdir}/.ci/ovn-kubernetes/custom.patch ] && \
28d94b
+    git apply -v ${topdir}/.ci/ovn-kubernetes/custom.patch
28d94b
+
28d94b
+popd # ${ovnk8s_path}
28d94b
+exit 0
28d94b
diff --git a/.github/workflows/ovn-kubernetes.yml b/.github/workflows/ovn-kubernetes.yml
28d94b
index 344937e53..840ecd1e0 100644
28d94b
--- a/.github/workflows/ovn-kubernetes.yml
28d94b
+++ b/.github/workflows/ovn-kubernetes.yml
28d94b
@@ -16,7 +16,7 @@ env:
28d94b
   GO_VERSION: "1.18.4"
28d94b
   K8S_VERSION: v1.24.0
28d94b
   OVNKUBE_COMMIT: "master"
28d94b
-  LIBOVSDB_COMMIT: "98c0bad3cff1"
28d94b
+  LIBOVSDB_COMMIT: "a6a173993830"
28d94b
   KIND_CLUSTER_NAME: ovn
28d94b
   KIND_INSTALL_INGRESS: true
28d94b
   KIND_ALLOW_SYSTEM_WRITES: true
28d94b
@@ -73,6 +73,7 @@ jobs:
28d94b
     env:
28d94b
       JOB_NAME: "${{ matrix.target }}-${{ matrix.ha }}-${{ matrix.gateway-mode }}-${{ matrix.ipfamily }}-${{ matrix.disable-snat-multiple-gws }}-${{ matrix.second-bridge }}"
28d94b
       OVN_HYBRID_OVERLAY_ENABLE: "${{ matrix.target == 'control-plane' }}"
28d94b
+      KIND_INSTALL_METALLB: "${{ matrix.target == 'control-plane' }}"
28d94b
       OVN_MULTICAST_ENABLE:  "${{ matrix.target == 'control-plane' }}"
28d94b
       OVN_EMPTY_LB_EVENTS: "${{ matrix.target == 'control-plane' }}"
28d94b
       OVN_HA: "true"
28d94b
@@ -91,12 +92,19 @@ jobs:
28d94b
         go-version: ${{ env.GO_VERSION }}
28d94b
       id: go
28d94b
 
28d94b
+    - name: Check out ovn
28d94b
+      uses: actions/checkout@v3
28d94b
+
28d94b
     - name: Check out ovn-kubernetes
28d94b
       uses: actions/checkout@v3
28d94b
       with:
28d94b
           path: src/github.com/ovn-org/ovn-kubernetes
28d94b
           repository: ovn-org/ovn-kubernetes
28d94b
 
28d94b
+    - name: Prepare
28d94b
+      run: |
28d94b
+        .ci/ovn-kubernetes/prepare.sh src/github.com/ovn-org/ovn-kubernetes
28d94b
+
28d94b
     - name: Set up environment
28d94b
       run: |
28d94b
         export GOPATH=$(go env GOPATH)
28d94b
diff --git a/Makefile.am b/Makefile.am
28d94b
index c8f770146..f7758d114 100644
28d94b
--- a/Makefile.am
28d94b
+++ b/Makefile.am
28d94b
@@ -90,6 +90,8 @@ EXTRA_DIST = \
28d94b
 	.ci/osx-build.sh \
28d94b
 	.ci/osx-prepare.sh \
28d94b
 	.ci/ovn-kubernetes/Dockerfile \
28d94b
+	.ci/ovn-kubernetes/prepare.sh \
28d94b
+	.ci/ovn-kubernetes/custom.patch \
28d94b
 	.github/workflows/test.yml \
28d94b
 	.github/workflows/ovn-kubernetes.yml \
28d94b
 	boot.sh \
28d94b
diff --git a/NEWS b/NEWS
28d94b
index 0920b44e2..acb8065bc 100644
28d94b
--- a/NEWS
28d94b
+++ b/NEWS
28d94b
@@ -1,3 +1,6 @@
28d94b
+OVN v22.12.1 - xx xxx xxxx
28d94b
+--------------------------
28d94b
+
28d94b
 OVN v22.12.0 - 16 Dec 2022
28d94b
 --------------------------
28d94b
   - Add load balancer "affinity_timeout" option to configure load balancing
28d94b
diff --git a/build-aux/sodepends.py b/build-aux/sodepends.py
28d94b
index 343fda1af..7b1f9c840 100755
28d94b
--- a/build-aux/sodepends.py
28d94b
+++ b/build-aux/sodepends.py
28d94b
@@ -63,7 +63,8 @@ def sodepends(include_info, filenames, dst):
28d94b
             continue
28d94b
 
28d94b
         # Open file.
28d94b
-        include_dirs = [info[0] for info in include_info]
28d94b
+        include_dirs = [info[1] if len(info) == 2 else info[0]
28d94b
+                        for info in include_info]
28d94b
         fn = soutil.find_file(include_dirs, toplevel)
28d94b
         if not fn:
28d94b
             ok = False
28d94b
diff --git a/configure.ac b/configure.ac
28d94b
index 101467253..357758e0c 100644
28d94b
--- a/configure.ac
28d94b
+++ b/configure.ac
28d94b
@@ -13,7 +13,7 @@
28d94b
 # limitations under the License.
28d94b
 
28d94b
 AC_PREREQ(2.63)
28d94b
-AC_INIT(ovn, 22.12.0, bugs@openvswitch.org)
28d94b
+AC_INIT(ovn, 22.12.1, bugs@openvswitch.org)
28d94b
 AC_CONFIG_MACRO_DIR([m4])
28d94b
 AC_CONFIG_AUX_DIR([build-aux])
28d94b
 AC_CONFIG_HEADERS([config.h])
28d94b
diff --git a/controller/chassis.c b/controller/chassis.c
28d94b
index 685d9b2ae..98f8da2be 100644
28d94b
--- a/controller/chassis.c
28d94b
+++ b/controller/chassis.c
28d94b
@@ -352,6 +352,7 @@ chassis_build_other_config(const struct ovs_chassis_cfg *ovs_cfg,
28d94b
     smap_replace(config, OVN_FEATURE_PORT_UP_NOTIF, "true");
28d94b
     smap_replace(config, OVN_FEATURE_CT_NO_MASKED_LABEL, "true");
28d94b
     smap_replace(config, OVN_FEATURE_MAC_BINDING_TIMESTAMP, "true");
28d94b
+    smap_replace(config, OVN_FEATURE_CT_LB_RELATED, "true");
28d94b
 }
28d94b
 
28d94b
 /*
28d94b
@@ -469,6 +470,12 @@ chassis_other_config_changed(const struct ovs_chassis_cfg *ovs_cfg,
28d94b
         return true;
28d94b
     }
28d94b
 
28d94b
+    if (!smap_get_bool(&chassis_rec->other_config,
28d94b
+                       OVN_FEATURE_CT_LB_RELATED,
28d94b
+                       false)) {
28d94b
+        return true;
28d94b
+    }
28d94b
+
28d94b
     return false;
28d94b
 }
28d94b
 
28d94b
diff --git a/controller/lflow.c b/controller/lflow.c
28d94b
index bb47bb0c7..4b1cfe318 100644
28d94b
--- a/controller/lflow.c
28d94b
+++ b/controller/lflow.c
28d94b
@@ -1567,9 +1567,6 @@ add_lb_vip_hairpin_reply_action(struct in6_addr *vip6, ovs_be32 vip,
28d94b
     /* Hairpin replies have the same nw_proto as packets that created the
28d94b
      * session.
28d94b
      */
28d94b
-    union mf_value imm_proto = {
28d94b
-        .u8 = lb_proto,
28d94b
-    };
28d94b
     ol_spec = ofpbuf_put_zeros(ofpacts, sizeof *ol_spec);
28d94b
     ol_spec->dst.field = mf_from_id(MFF_IP_PROTO);
28d94b
     ol_spec->src.field = mf_from_id(MFF_IP_PROTO);
28d94b
@@ -1577,16 +1574,21 @@ add_lb_vip_hairpin_reply_action(struct in6_addr *vip6, ovs_be32 vip,
28d94b
     ol_spec->dst.n_bits = ol_spec->dst.field->n_bits;
28d94b
     ol_spec->n_bits = ol_spec->dst.n_bits;
28d94b
     ol_spec->dst_type = NX_LEARN_DST_MATCH;
28d94b
-    ol_spec->src_type = NX_LEARN_SRC_IMMEDIATE;
28d94b
-    mf_write_subfield_value(&ol_spec->dst, &imm_proto, &match);
28d94b
-
28d94b
-    /* Push value last, as this may reallocate 'ol_spec' */
28d94b
-    imm_bytes = DIV_ROUND_UP(ol_spec->dst.n_bits, 8);
28d94b
-    src_imm = ofpbuf_put_zeros(ofpacts, OFPACT_ALIGN(imm_bytes));
28d94b
-    memcpy(src_imm, &imm_proto, imm_bytes);
28d94b
 
28d94b
     /* Hairpin replies have source port == <backend-port>. */
28d94b
     if (has_l4_port) {
28d94b
+        union mf_value imm_proto = {
28d94b
+            .u8 = lb_proto,
28d94b
+        };
28d94b
+
28d94b
+        ol_spec->src_type = NX_LEARN_SRC_IMMEDIATE;
28d94b
+        mf_write_subfield_value(&ol_spec->dst, &imm_proto, &match);
28d94b
+
28d94b
+        /* Push value last, as this may reallocate 'ol_spec' */
28d94b
+        imm_bytes = DIV_ROUND_UP(ol_spec->dst.n_bits, 8);
28d94b
+        src_imm = ofpbuf_put_zeros(ofpacts, OFPACT_ALIGN(imm_bytes));
28d94b
+        memcpy(src_imm, &imm_proto, imm_bytes);
28d94b
+
28d94b
         ol_spec = ofpbuf_put_zeros(ofpacts, sizeof *ol_spec);
28d94b
         switch (lb_proto) {
28d94b
         case IPPROTO_TCP:
28d94b
@@ -1610,6 +1612,8 @@ add_lb_vip_hairpin_reply_action(struct in6_addr *vip6, ovs_be32 vip,
28d94b
         ol_spec->n_bits = ol_spec->dst.n_bits;
28d94b
         ol_spec->dst_type = NX_LEARN_DST_MATCH;
28d94b
         ol_spec->src_type = NX_LEARN_SRC_FIELD;
28d94b
+    } else {
28d94b
+        ol_spec->src_type = NX_LEARN_SRC_FIELD;
28d94b
     }
28d94b
 
28d94b
     /* Set MLF_LOOKUP_LB_HAIRPIN_BIT for hairpin replies. */
28d94b
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
28d94b
index 73c33a6bf..c899283dc 100644
28d94b
--- a/controller/ovn-controller.c
28d94b
+++ b/controller/ovn-controller.c
28d94b
@@ -755,6 +755,11 @@ update_ct_zones(const struct shash *binding_lports,
28d94b
             }
28d94b
             bitmap_set1(ct_zone_bitmap, snat_req_node->data);
28d94b
             node->data = snat_req_node->data;
28d94b
+        } else {
28d94b
+            add_pending_ct_zone_entry(pending_ct_zones, CT_ZONE_OF_QUEUED,
28d94b
+                                      snat_req_node->data, true, snat_req_node->name);
28d94b
+            bitmap_set1(ct_zone_bitmap, snat_req_node->data);
28d94b
+            simap_put(ct_zones, snat_req_node->name, snat_req_node->data);
28d94b
         }
28d94b
     }
28d94b
 
28d94b
diff --git a/controller/pinctrl.c b/controller/pinctrl.c
28d94b
index 82da6ae73..e4d530138 100644
28d94b
--- a/controller/pinctrl.c
28d94b
+++ b/controller/pinctrl.c
28d94b
@@ -1419,7 +1419,6 @@ prepare_ipv6_prefixd(struct ovsdb_idl_txn *ovnsb_idl_txn,
28d94b
 
28d94b
 struct buffer_info {
28d94b
     struct ofpbuf ofpacts;
28d94b
-    ofp_port_t ofp_port;
28d94b
     struct dp_packet *p;
28d94b
 };
28d94b
 
28d94b
@@ -1495,7 +1494,6 @@ buffered_push_packet(struct buffered_packets *bp,
28d94b
     union mf_value pkt_mark_value;
28d94b
     mf_get_value(pkt_mark_field, &md->flow, &pkt_mark_value);
28d94b
     ofpact_put_set_field(&bi->ofpacts, pkt_mark_field, &pkt_mark_value, NULL);
28d94b
-    bi->ofp_port = md->flow.in_port.ofp_port;
28d94b
 
28d94b
     struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&bi->ofpacts);
28d94b
     resubmit->in_port = OFPP_CONTROLLER;
28d94b
@@ -1531,7 +1529,7 @@ buffered_send_packets(struct rconn *swconn, struct buffered_packets *bp,
28d94b
             .ofpacts = bi->ofpacts.data,
28d94b
             .ofpacts_len = bi->ofpacts.size,
28d94b
         };
28d94b
-        match_set_in_port(&po.flow_metadata, bi->ofp_port);
28d94b
+        match_set_in_port(&po.flow_metadata, OFPP_CONTROLLER);
28d94b
         queue_msg(swconn, ofputil_encode_packet_out(&po, proto));
28d94b
 
28d94b
         ofpbuf_uninit(&bi->ofpacts);
28d94b
diff --git a/debian/changelog b/debian/changelog
28d94b
index 6f5a9ac2a..d658774f6 100644
28d94b
--- a/debian/changelog
28d94b
+++ b/debian/changelog
28d94b
@@ -1,3 +1,9 @@
28d94b
+OVN (22.12.1-1) unstable; urgency=low
28d94b
+   [ OVN team ]
28d94b
+   * New upstream version
28d94b
+
28d94b
+ -- OVN team <dev@openvswitch.org>  Fri, 16 Dec 2022 09:52:44 -0500
28d94b
+
28d94b
 ovn (22.12.0-1) unstable; urgency=low
28d94b
 
28d94b
    * New upstream version
28d94b
diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
28d94b
index 73ce77e5c..9a80a7f68 100644
28d94b
--- a/ic/ovn-ic.c
28d94b
+++ b/ic/ovn-ic.c
28d94b
@@ -1911,13 +1911,112 @@ main(int argc, char *argv[])
28d94b
     struct ovsdb_idl_loop ovnisb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
28d94b
         ovsdb_idl_create(ovn_ic_sb_db, &icsbrec_idl_class, true, true));
28d94b
 
28d94b
-    /* ovn-nb db. XXX: add only needed tables and columns */
28d94b
+    /* ovn-nb db. */
28d94b
     struct ovsdb_idl_loop ovnnb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
28d94b
-        ovsdb_idl_create(ovnnb_db, &nbrec_idl_class, true, true));
28d94b
-
28d94b
-    /* ovn-sb db. XXX: add only needed tables and columns */
28d94b
+        ovsdb_idl_create(ovnnb_db, &nbrec_idl_class, false, true));
28d94b
+
28d94b
+    ovsdb_idl_add_table(ovnnb_idl_loop.idl, &nbrec_table_nb_global);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl, &nbrec_nb_global_col_name);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl, &nbrec_nb_global_col_options);
28d94b
+
28d94b
+    ovsdb_idl_add_table(ovnnb_idl_loop.idl,
28d94b
+                        &nbrec_table_logical_router_static_route);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_static_route_col_route_table);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_static_route_col_ip_prefix);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_static_route_col_nexthop);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_static_route_col_external_ids);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_static_route_col_options);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_static_route_col_policy);
28d94b
+
28d94b
+    ovsdb_idl_add_table(ovnnb_idl_loop.idl, &nbrec_table_logical_router);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_col_name);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_col_static_routes);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_col_ports);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_col_options);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_col_external_ids);
28d94b
+
28d94b
+    ovsdb_idl_add_table(ovnnb_idl_loop.idl, &nbrec_table_logical_router_port);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_port_col_name);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_port_col_networks);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_port_col_external_ids);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_router_port_col_options);
28d94b
+
28d94b
+    ovsdb_idl_add_table(ovnnb_idl_loop.idl, &nbrec_table_logical_switch);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_switch_col_name);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_switch_col_ports);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_switch_col_other_config);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_switch_col_external_ids);
28d94b
+
28d94b
+    ovsdb_idl_add_table(ovnnb_idl_loop.idl, &nbrec_table_logical_switch_port);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_switch_port_col_name);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_switch_port_col_addresses);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_switch_port_col_options);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_switch_port_col_type);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_switch_port_col_up);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_switch_port_col_addresses);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_switch_port_col_enabled);
28d94b
+    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
28d94b
+                         &nbrec_logical_switch_port_col_external_ids);
28d94b
+
28d94b
+    /* ovn-sb db. */
28d94b
     struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
28d94b
-        ovsdb_idl_create(ovnsb_db, &sbrec_idl_class, true, true));
28d94b
+        ovsdb_idl_create(ovnsb_db, &sbrec_idl_class, false, true));
28d94b
+
28d94b
+    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_encaps);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_name);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_hostname);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_other_config);
28d94b
+
28d94b
+    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_encap);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_encap_col_chassis_name);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_encap_col_type);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_encap_col_ip);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_encap_col_options);
28d94b
+
28d94b
+    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_datapath_binding);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl,
28d94b
+                         &sbrec_datapath_binding_col_external_ids);
28d94b
+
28d94b
+    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_port_binding);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl,
28d94b
+                         &sbrec_port_binding_col_datapath);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl,
28d94b
+                         &sbrec_port_binding_col_mac);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl,
28d94b
+                         &sbrec_port_binding_col_options);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl,
28d94b
+                         &sbrec_port_binding_col_logical_port);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl,
28d94b
+                         &sbrec_port_binding_col_external_ids);
28d94b
+    ovsdb_idl_add_column(ovnsb_idl_loop.idl,
28d94b
+                         &sbrec_port_binding_col_chassis);
28d94b
 
28d94b
     /* Create IDL indexes */
28d94b
     struct ovsdb_idl_index *nbrec_ls_by_name
28d94b
diff --git a/include/ovn/features.h b/include/ovn/features.h
28d94b
index 679f67457..5bcd68739 100644
28d94b
--- a/include/ovn/features.h
28d94b
+++ b/include/ovn/features.h
28d94b
@@ -24,6 +24,7 @@
28d94b
 #define OVN_FEATURE_PORT_UP_NOTIF      "port-up-notif"
28d94b
 #define OVN_FEATURE_CT_NO_MASKED_LABEL "ct-no-masked-label"
28d94b
 #define OVN_FEATURE_MAC_BINDING_TIMESTAMP "mac-binding-timestamp"
28d94b
+#define OVN_FEATURE_CT_LB_RELATED "ovn-ct-lb-related"
28d94b
 
28d94b
 /* OVS datapath supported features.  Based on availability OVN might generate
28d94b
  * different types of openflows.
28d94b
diff --git a/include/ovn/lex.h b/include/ovn/lex.h
28d94b
index 9159b7a26..64d33361f 100644
28d94b
--- a/include/ovn/lex.h
28d94b
+++ b/include/ovn/lex.h
28d94b
@@ -29,6 +29,8 @@
28d94b
 
28d94b
 struct ds;
28d94b
 
28d94b
+#define LEX_TEMPLATE_PREFIX '^'
28d94b
+
28d94b
 /* Token type. */
28d94b
 enum lex_type {
28d94b
     LEX_T_END,                  /* end of input */
28d94b
diff --git a/lib/lb.c b/lib/lb.c
28d94b
index 43628bba7..c13d07b99 100644
28d94b
--- a/lib/lb.c
28d94b
+++ b/lib/lb.c
28d94b
@@ -314,11 +314,10 @@ ovn_lb_vip_destroy(struct ovn_lb_vip *vip)
28d94b
     free(vip->backends);
28d94b
 }
28d94b
 
28d94b
-void
28d94b
-ovn_lb_vip_format(const struct ovn_lb_vip *vip, struct ds *s, bool template)
28d94b
+static void
28d94b
+ovn_lb_vip_format__(const struct ovn_lb_vip *vip, struct ds *s,
28d94b
+                    bool needs_brackets)
28d94b
 {
28d94b
-    bool needs_brackets = vip->address_family == AF_INET6 && vip->port_str
28d94b
-                          && !template;
28d94b
     if (needs_brackets) {
28d94b
         ds_put_char(s, '[');
28d94b
     }
28d94b
@@ -331,6 +330,30 @@ ovn_lb_vip_format(const struct ovn_lb_vip *vip, struct ds *s, bool template)
28d94b
     }
28d94b
 }
28d94b
 
28d94b
+/* Formats the VIP in the way the ovn-controller expects it, that is,
28d94b
+ * template IPv6 variables need to be between brackets too.
28d94b
+ */
28d94b
+static char *
28d94b
+ovn_lb_vip6_template_format_internal(const struct ovn_lb_vip *vip)
28d94b
+{
28d94b
+    struct ds s = DS_EMPTY_INITIALIZER;
28d94b
+
28d94b
+    if (vip->vip_str && *vip->vip_str == LEX_TEMPLATE_PREFIX) {
28d94b
+        ovn_lb_vip_format__(vip, &s, true);
28d94b
+    } else {
28d94b
+        ovn_lb_vip_format(vip, &s, !!vip->port_str);
28d94b
+    }
28d94b
+    return ds_steal_cstr(&s);
28d94b
+}
28d94b
+
28d94b
+void
28d94b
+ovn_lb_vip_format(const struct ovn_lb_vip *vip, struct ds *s, bool template)
28d94b
+{
28d94b
+    bool needs_brackets = vip->address_family == AF_INET6 && vip->port_str
28d94b
+                          && !template;
28d94b
+    ovn_lb_vip_format__(vip, s, needs_brackets);
28d94b
+}
28d94b
+
28d94b
 void
28d94b
 ovn_lb_vip_backends_format(const struct ovn_lb_vip *vip, struct ds *s,
28d94b
                            bool template)
28d94b
@@ -512,6 +535,7 @@ ovn_northd_lb_create(const struct nbrec_load_balancer *nbrec_lb)
28d94b
     lb->n_vips = smap_count(&nbrec_lb->vips);
28d94b
     lb->vips = xcalloc(lb->n_vips, sizeof *lb->vips);
28d94b
     lb->vips_nb = xcalloc(lb->n_vips, sizeof *lb->vips_nb);
28d94b
+    smap_init(&lb->template_vips);
28d94b
     lb->controller_event = smap_get_bool(&nbrec_lb->options, "event", false);
28d94b
 
28d94b
     bool routable = smap_get_bool(&nbrec_lb->options, "add_route", false);
28d94b
@@ -560,6 +584,12 @@ ovn_northd_lb_create(const struct nbrec_load_balancer *nbrec_lb)
28d94b
         } else {
28d94b
             sset_add(&lb->ips_v6, lb_vip->vip_str);
28d94b
         }
28d94b
+
28d94b
+        if (lb->template && address_family == AF_INET6) {
28d94b
+            smap_add_nocopy(&lb->template_vips,
28d94b
+                            ovn_lb_vip6_template_format_internal(lb_vip),
28d94b
+                            xstrdup(node->value));
28d94b
+        }
28d94b
         n_vips++;
28d94b
     }
28d94b
 
28d94b
@@ -604,6 +634,15 @@ ovn_northd_lb_find(const struct hmap *lbs, const struct uuid *uuid)
28d94b
     return NULL;
28d94b
 }
28d94b
 
28d94b
+const struct smap *
28d94b
+ovn_northd_lb_get_vips(const struct ovn_northd_lb *lb)
28d94b
+{
28d94b
+    if (!smap_is_empty(&lb->template_vips)) {
28d94b
+        return &lb->template_vips;
28d94b
+    }
28d94b
+    return &lb->nlb->vips;
28d94b
+}
28d94b
+
28d94b
 void
28d94b
 ovn_northd_lb_add_lr(struct ovn_northd_lb *lb, size_t n,
28d94b
                      struct ovn_datapath **ods)
28d94b
@@ -637,6 +676,7 @@ ovn_northd_lb_destroy(struct ovn_northd_lb *lb)
28d94b
     }
28d94b
     free(lb->vips);
28d94b
     free(lb->vips_nb);
28d94b
+    smap_destroy(&lb->template_vips);
28d94b
     sset_destroy(&lb->ips_v4);
28d94b
     sset_destroy(&lb->ips_v6);
28d94b
     free(lb->selection_fields);
28d94b
diff --git a/lib/lb.h b/lib/lb.h
28d94b
index 55a41ae0b..55becc1bf 100644
28d94b
--- a/lib/lb.h
28d94b
+++ b/lib/lb.h
28d94b
@@ -19,6 +19,7 @@
28d94b
 
28d94b
 #include <sys/types.h>
28d94b
 #include <netinet/in.h>
28d94b
+#include "lib/smap.h"
28d94b
 #include "openvswitch/hmap.h"
28d94b
 #include "ovn-util.h"
28d94b
 #include "sset.h"
28d94b
@@ -62,6 +63,9 @@ struct ovn_northd_lb {
28d94b
     char *selection_fields;
28d94b
     struct ovn_lb_vip *vips;
28d94b
     struct ovn_northd_lb_vip *vips_nb;
28d94b
+    struct smap template_vips; /* Slightly changed template VIPs, populated
28d94b
+                                * if needed.  Until now it's only required
28d94b
+                                * for IPv6 template load balancers. */
28d94b
     size_t n_vips;
28d94b
 
28d94b
     enum lb_neighbor_responder_mode neigh_mode;
28d94b
@@ -130,6 +134,7 @@ struct ovn_northd_lb_backend {
28d94b
 struct ovn_northd_lb *ovn_northd_lb_create(const struct nbrec_load_balancer *);
28d94b
 struct ovn_northd_lb *ovn_northd_lb_find(const struct hmap *,
28d94b
                                          const struct uuid *);
28d94b
+const struct smap *ovn_northd_lb_get_vips(const struct ovn_northd_lb *);
28d94b
 void ovn_northd_lb_destroy(struct ovn_northd_lb *);
28d94b
 void ovn_northd_lb_add_lr(struct ovn_northd_lb *lb, size_t n,
28d94b
                           struct ovn_datapath **ods);
28d94b
diff --git a/lib/lex.c b/lib/lex.c
28d94b
index 5251868b5..a8b9812bb 100644
28d94b
--- a/lib/lex.c
28d94b
+++ b/lib/lex.c
28d94b
@@ -782,7 +782,7 @@ next:
28d94b
         p = lex_parse_port_group(p, token);
28d94b
         break;
28d94b
 
28d94b
-    case '^':
28d94b
+    case LEX_TEMPLATE_PREFIX:
28d94b
         p = lex_parse_template(p, token);
28d94b
         break;
28d94b
 
28d94b
@@ -1061,7 +1061,7 @@ lexer_parse_template_string(const char *s, const struct smap *template_vars,
28d94b
                             struct sset *template_vars_ref)
28d94b
 {
28d94b
     /* No '^' means no templates. */
28d94b
-    if (!strchr(s, '^')) {
28d94b
+    if (!strchr(s, LEX_TEMPLATE_PREFIX)) {
28d94b
         return lex_str_use(s);
28d94b
     }
28d94b
 
28d94b
diff --git a/lib/ovn-util.c b/lib/ovn-util.c
28d94b
index 86b98acf7..69ab56423 100644
28d94b
--- a/lib/ovn-util.c
28d94b
+++ b/lib/ovn-util.c
28d94b
@@ -825,24 +825,6 @@ ovn_get_internal_version(void)
28d94b
                      N_OVNACTS, OVN_INTERNAL_MINOR_VER);
28d94b
 }
28d94b
 
28d94b
-unsigned int
28d94b
-ovn_parse_internal_version_minor(const char *ver)
28d94b
-{
28d94b
-    const char *p = ver + strlen(ver);
28d94b
-    for (int i = 0; i < strlen(ver); i++) {
28d94b
-        if (*p == '.') {
28d94b
-            break;
28d94b
-        }
28d94b
-        p--;
28d94b
-    }
28d94b
-
28d94b
-    unsigned int minor;
28d94b
-    if (ovs_scan(p, ".%u", &minor)) {
28d94b
-        return minor;
28d94b
-    }
28d94b
-    return 0;
28d94b
-}
28d94b
-
28d94b
 #ifdef DDLOG
28d94b
 /* Callbacks used by the ddlog northd code to print warnings and errors. */
28d94b
 void
28d94b
diff --git a/lib/ovn-util.h b/lib/ovn-util.h
28d94b
index 809ff1d36..48dc846ad 100644
28d94b
--- a/lib/ovn-util.h
28d94b
+++ b/lib/ovn-util.h
28d94b
@@ -70,6 +70,23 @@ struct lport_addresses {
28d94b
     struct ipv6_netaddr *ipv6_addrs;
28d94b
 };
28d94b
 
28d94b
+static inline bool
28d94b
+ipv6_is_all_router(const struct in6_addr *addr)
28d94b
+{
28d94b
+    return ipv6_addr_equals(addr, &in6addr_all_routers);
28d94b
+}
28d94b
+
28d94b
+static const struct in6_addr in6addr_all_site_routers = {{{
28d94b
+    0xff,0x05,0x00,0x00,0x00,0x00,0x00,0x00,
28d94b
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02
28d94b
+}}};
28d94b
+
28d94b
+static inline bool
28d94b
+ipv6_is_all_site_router(const struct in6_addr *addr)
28d94b
+{
28d94b
+    return ipv6_addr_equals(addr, &in6addr_all_site_routers);
28d94b
+}
28d94b
+
28d94b
 bool is_dynamic_lsp_address(const char *address);
28d94b
 bool extract_addresses(const char *address, struct lport_addresses *,
28d94b
                        int *ofs);
28d94b
@@ -248,11 +265,6 @@ bool ip_address_and_port_from_lb_key(const char *key, char **ip_address,
28d94b
  * value. */
28d94b
 char *ovn_get_internal_version(void);
28d94b
 
28d94b
-/* Parse the provided internal version string and return the "minor" part which
28d94b
- * is expected to be an unsigned integer followed by the last "." in the
28d94b
- * string. Returns 0 if the string can't be parsed. */
28d94b
-unsigned int ovn_parse_internal_version_minor(const char *ver);
28d94b
-
28d94b
 /* OVN Packet definitions. These may eventually find a home in OVS's
28d94b
  * packets.h file. For the time being, they live here because OVN uses them
28d94b
  * and OVS does not.
28d94b
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
28d94b
index 363e384bd..a7b735333 100644
28d94b
--- a/northd/inc-proc-northd.c
28d94b
+++ b/northd/inc-proc-northd.c
28d94b
@@ -34,10 +34,13 @@
28d94b
 #include "en-lflow.h"
28d94b
 #include "en-northd-output.h"
28d94b
 #include "en-sync-sb.h"
28d94b
+#include "unixctl.h"
28d94b
 #include "util.h"
28d94b
 
28d94b
 VLOG_DEFINE_THIS_MODULE(inc_proc_northd);
28d94b
 
28d94b
+static unixctl_cb_func chassis_features_list;
28d94b
+
28d94b
 #define NB_NODES \
28d94b
     NB_NODE(nb_global, "nb_global") \
28d94b
     NB_NODE(copp, "copp") \
28d94b
@@ -306,6 +309,12 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
28d94b
     engine_ovsdb_node_add_index(&en_sb_address_set,
28d94b
                                 "sbrec_address_set_by_name",
28d94b
                                 sbrec_address_set_by_name);
28d94b
+
28d94b
+    struct northd_data *northd_data =
28d94b
+        engine_get_internal_data(&en_northd);
28d94b
+    unixctl_command_register("debug/chassis-features-list", "", 0, 0,
28d94b
+                             chassis_features_list,
28d94b
+                             &northd_data->features);
28d94b
 }
28d94b
 
28d94b
 void inc_proc_northd_run(struct ovsdb_idl_txn *ovnnb_txn,
28d94b
@@ -354,3 +363,20 @@ void inc_proc_northd_cleanup(void)
28d94b
     engine_cleanup();
28d94b
     engine_set_context(NULL);
28d94b
 }
28d94b
+
28d94b
+static void
28d94b
+chassis_features_list(struct unixctl_conn *conn, int argc OVS_UNUSED,
28d94b
+                      const char *argv[] OVS_UNUSED, void *features_)
28d94b
+{
28d94b
+    struct chassis_features *features = features_;
28d94b
+    struct ds ds = DS_EMPTY_INITIALIZER;
28d94b
+
28d94b
+    ds_put_format(&ds, "ct_no_masked_label:    %s\n",
28d94b
+                  features->ct_no_masked_label ? "true" : "false");
28d94b
+    ds_put_format(&ds, "ct_lb_related:         %s\n",
28d94b
+                  features->ct_lb_related ? "true" : "false");
28d94b
+    ds_put_format(&ds, "mac_binding_timestamp: %s\n",
28d94b
+                  features->mac_binding_timestamp ? "true" : "false");
28d94b
+    unixctl_command_reply(conn, ds_cstr(&ds);;
28d94b
+    ds_destroy(&ds);
28d94b
+}
28d94b
diff --git a/northd/northd.c b/northd/northd.c
28d94b
index 841ae9cc5..9cedec909 100644
28d94b
--- a/northd/northd.c
28d94b
+++ b/northd/northd.c
28d94b
@@ -125,11 +125,11 @@ enum ovn_stage {
28d94b
     PIPELINE_STAGE(SWITCH, IN,  LB_AFF_CHECK,  11, "ls_in_lb_aff_check")  \
28d94b
     PIPELINE_STAGE(SWITCH, IN,  LB,            12, "ls_in_lb")            \
28d94b
     PIPELINE_STAGE(SWITCH, IN,  LB_AFF_LEARN,  13, "ls_in_lb_aff_learn")  \
28d94b
-    PIPELINE_STAGE(SWITCH, IN,  ACL_AFTER_LB,  14, "ls_in_acl_after_lb")  \
28d94b
-    PIPELINE_STAGE(SWITCH, IN,  STATEFUL,      15, "ls_in_stateful")      \
28d94b
-    PIPELINE_STAGE(SWITCH, IN,  PRE_HAIRPIN,   16, "ls_in_pre_hairpin")   \
28d94b
-    PIPELINE_STAGE(SWITCH, IN,  NAT_HAIRPIN,   17, "ls_in_nat_hairpin")   \
28d94b
-    PIPELINE_STAGE(SWITCH, IN,  HAIRPIN,       18, "ls_in_hairpin")       \
28d94b
+    PIPELINE_STAGE(SWITCH, IN,  PRE_HAIRPIN,   14, "ls_in_pre_hairpin")   \
28d94b
+    PIPELINE_STAGE(SWITCH, IN,  NAT_HAIRPIN,   15, "ls_in_nat_hairpin")   \
28d94b
+    PIPELINE_STAGE(SWITCH, IN,  HAIRPIN,       16, "ls_in_hairpin")       \
28d94b
+    PIPELINE_STAGE(SWITCH, IN,  ACL_AFTER_LB,  17, "ls_in_acl_after_lb")  \
28d94b
+    PIPELINE_STAGE(SWITCH, IN,  STATEFUL,      18, "ls_in_stateful")      \
28d94b
     PIPELINE_STAGE(SWITCH, IN,  ARP_ND_RSP,    19, "ls_in_arp_rsp")       \
28d94b
     PIPELINE_STAGE(SWITCH, IN,  DHCP_OPTIONS,  20, "ls_in_dhcp_options")  \
28d94b
     PIPELINE_STAGE(SWITCH, IN,  DHCP_RESPONSE, 21, "ls_in_dhcp_response") \
28d94b
@@ -215,6 +215,7 @@ enum ovn_stage {
28d94b
 #define REGBIT_ACL_LABEL          "reg0[13]"
28d94b
 #define REGBIT_FROM_RAMP          "reg0[14]"
28d94b
 #define REGBIT_PORT_SEC_DROP      "reg0[15]"
28d94b
+#define REGBIT_ACL_HINT_ALLOW_REL "reg0[17]"
28d94b
 
28d94b
 #define REG_ORIG_DIP_IPV4         "reg1"
28d94b
 #define REG_ORIG_DIP_IPV6         "xxreg1"
28d94b
@@ -430,6 +431,13 @@ build_chassis_features(const struct northd_input *input_data,
28d94b
     const struct sbrec_chassis *chassis;
28d94b
 
28d94b
     SBREC_CHASSIS_TABLE_FOR_EACH (chassis, input_data->sbrec_chassis) {
28d94b
+        /* Only consider local AZ chassis.  Remote ones don't install
28d94b
+         * flows generated by the local northd.
28d94b
+         */
28d94b
+        if (smap_get_bool(&chassis->other_config, "is-remote", false)) {
28d94b
+            continue;
28d94b
+        }
28d94b
+
28d94b
         bool ct_no_masked_label =
28d94b
             smap_get_bool(&chassis->other_config,
28d94b
                           OVN_FEATURE_CT_NO_MASKED_LABEL,
28d94b
@@ -446,6 +454,15 @@ build_chassis_features(const struct northd_input *input_data,
28d94b
             chassis_features->mac_binding_timestamp) {
28d94b
             chassis_features->mac_binding_timestamp = false;
28d94b
         }
28d94b
+
28d94b
+        bool ct_lb_related =
28d94b
+            smap_get_bool(&chassis->other_config,
28d94b
+                          OVN_FEATURE_CT_LB_RELATED,
28d94b
+                          false);
28d94b
+        if (!ct_lb_related &&
28d94b
+            chassis_features->ct_lb_related) {
28d94b
+            chassis_features->ct_lb_related = false;
28d94b
+        }
28d94b
     }
28d94b
 }
28d94b
 
28d94b
@@ -4410,7 +4427,7 @@ sync_lbs(struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn,
28d94b
 
28d94b
         /* Update columns. */
28d94b
         sbrec_load_balancer_set_name(lb->slb, lb->nlb->name);
28d94b
-        sbrec_load_balancer_set_vips(lb->slb, &lb->nlb->vips);
28d94b
+        sbrec_load_balancer_set_vips(lb->slb, ovn_northd_lb_get_vips(lb));
28d94b
         sbrec_load_balancer_set_protocol(lb->slb, lb->nlb->protocol);
28d94b
         sbrec_load_balancer_set_datapath_group(lb->slb, dpg->dp_group);
28d94b
         sbrec_load_balancer_set_options(lb->slb, &options);
28d94b
@@ -4849,7 +4866,7 @@ ovn_igmp_group_get_ports(const struct sbrec_igmp_group *sb_igmp_group,
28d94b
         struct ovn_port *port =
28d94b
             ovn_port_find(ovn_ports, sb_igmp_group->ports[i]->logical_port);
28d94b
 
28d94b
-        if (!port) {
28d94b
+        if (!port || !port->nbsp) {
28d94b
             continue;
28d94b
         }
28d94b
 
28d94b
@@ -6758,7 +6775,8 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features,
28d94b
                       ct_blocked_match);
28d94b
         ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX - 3,
28d94b
                       ds_cstr(&match), REGBIT_ACL_HINT_DROP" = 0; "
28d94b
-                      REGBIT_ACL_HINT_BLOCK" = 0; next;");
28d94b
+                      REGBIT_ACL_HINT_BLOCK" = 0; "
28d94b
+                      REGBIT_ACL_HINT_ALLOW_REL" = 1; next;");
28d94b
         ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX - 3,
28d94b
                       ds_cstr(&match), "next;");
28d94b
 
28d94b
@@ -6774,14 +6792,21 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features,
28d94b
          * a dynamically negotiated FTP data channel), but will allow
28d94b
          * related traffic such as an ICMP Port Unreachable through
28d94b
          * that's generated from a non-listening UDP port.  */
28d94b
+        const char *ct_in_acl_action =
28d94b
+            features->ct_lb_related
28d94b
+            ? REGBIT_ACL_HINT_ALLOW_REL" = 1; ct_commit_nat;"
28d94b
+            : REGBIT_ACL_HINT_ALLOW_REL" = 1; next;";
28d94b
+        const char *ct_out_acl_action = features->ct_lb_related
28d94b
+                                        ? "ct_commit_nat;"
28d94b
+                                        : "next;";
28d94b
         ds_clear(&match);
28d94b
         ds_put_format(&match, "!ct.est && ct.rel && !ct.new%s && %s == 0",
28d94b
                       use_ct_inv_match ? " && !ct.inv" : "",
28d94b
                       ct_blocked_match);
28d94b
         ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX - 3,
28d94b
-                      ds_cstr(&match), "ct_commit_nat;");
28d94b
+                      ds_cstr(&match), ct_in_acl_action);
28d94b
         ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX - 3,
28d94b
-                      ds_cstr(&match), "ct_commit_nat;");
28d94b
+                      ds_cstr(&match), ct_out_acl_action);
28d94b
 
28d94b
         /* Ingress and Egress ACL Table (Priority 65532).
28d94b
          *
28d94b
@@ -6790,6 +6815,11 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features,
28d94b
                       "nd || nd_ra || nd_rs || mldv1 || mldv2", "next;");
28d94b
         ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX - 3,
28d94b
                       "nd || nd_ra || nd_rs || mldv1 || mldv2", "next;");
28d94b
+
28d94b
+        /* Reply and related traffic matched by an "allow-related" ACL
28d94b
+         * should be allowed in the ls_in_acl_after_lb stage too. */
28d94b
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL_AFTER_LB, UINT16_MAX - 3,
28d94b
+                      REGBIT_ACL_HINT_ALLOW_REL" == 1", "next;");
28d94b
     }
28d94b
 
28d94b
     /* Ingress or Egress ACL Table (Various priorities). */
28d94b
@@ -7838,7 +7868,7 @@ build_lrouter_groups(struct hmap *ports, struct ovs_list *lr_list)
28d94b
 }
28d94b
 
28d94b
 /*
28d94b
- * Ingress table 24: Flows that flood self originated ARP/RARP/ND packets in
28d94b
+ * Ingress table 25: Flows that flood self originated ARP/RARP/ND packets in
28d94b
  * the switching domain.
28d94b
  */
28d94b
 static void
28d94b
@@ -7952,7 +7982,7 @@ lrouter_port_ipv6_reachable(const struct ovn_port *op,
28d94b
 }
28d94b
 
28d94b
 /*
28d94b
- * Ingress table 24: Flows that forward ARP/ND requests only to the routers
28d94b
+ * Ingress table 25: Flows that forward ARP/ND requests only to the routers
28d94b
  * that own the addresses. Other ARP/ND packets are still flooded in the
28d94b
  * switching domain as regular broadcast.
28d94b
  */
28d94b
@@ -7989,7 +8019,7 @@ build_lswitch_rport_arp_req_flow(const char *ips,
28d94b
 }
28d94b
 
28d94b
 /*
28d94b
- * Ingress table 24: Flows that forward ARP/ND requests only to the routers
28d94b
+ * Ingress table 25: Flows that forward ARP/ND requests only to the routers
28d94b
  * that own the addresses.
28d94b
  * Priorities:
28d94b
  * - 80: self originated GARPs that need to follow regular processing.
28d94b
@@ -8318,7 +8348,8 @@ build_lswitch_flows(const struct hmap *datapaths,
28d94b
 
28d94b
     struct ovn_datapath *od;
28d94b
 
28d94b
-    /* Ingress table 25: Destination lookup for unknown MACs (priority 0). */
28d94b
+    /* Ingress table 25/26: Destination lookup for unknown MACs
28d94b
+     * (priority 0). */
28d94b
     HMAP_FOR_EACH (od, key_node, datapaths) {
28d94b
         if (!od->nbs) {
28d94b
             continue;
28d94b
@@ -8393,7 +8424,7 @@ build_lswitch_lflows_admission_control(struct ovn_datapath *od,
28d94b
     }
28d94b
 }
28d94b
 
28d94b
-/* Ingress table 18: ARP/ND responder, skip requests coming from localnet
28d94b
+/* Ingress table 19: ARP/ND responder, skip requests coming from localnet
28d94b
  * ports. (priority 100); see ovn-northd.8.xml for the rationale. */
28d94b
 
28d94b
 static void
28d94b
@@ -8411,7 +8442,7 @@ build_lswitch_arp_nd_responder_skip_local(struct ovn_port *op,
28d94b
     }
28d94b
 }
28d94b
 
28d94b
-/* Ingress table 18: ARP/ND responder, reply for known IPs.
28d94b
+/* Ingress table 19: ARP/ND responder, reply for known IPs.
28d94b
  * (priority 50). */
28d94b
 static void
28d94b
 build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op,
28d94b
@@ -8671,7 +8702,7 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op,
28d94b
     }
28d94b
 }
28d94b
 
28d94b
-/* Ingress table 18: ARP/ND responder, by default goto next.
28d94b
+/* Ingress table 19: ARP/ND responder, by default goto next.
28d94b
  * (priority 0)*/
28d94b
 static void
28d94b
 build_lswitch_arp_nd_responder_default(struct ovn_datapath *od,
28d94b
@@ -8682,7 +8713,7 @@ build_lswitch_arp_nd_responder_default(struct ovn_datapath *od,
28d94b
     }
28d94b
 }
28d94b
 
28d94b
-/* Ingress table 18: ARP/ND responder for service monitor source ip.
28d94b
+/* Ingress table 19: ARP/ND responder for service monitor source ip.
28d94b
  * (priority 110)*/
28d94b
 static void
28d94b
 build_lswitch_arp_nd_service_monitor(struct ovn_northd_lb *lb,
28d94b
@@ -8730,7 +8761,7 @@ build_lswitch_arp_nd_service_monitor(struct ovn_northd_lb *lb,
28d94b
 }
28d94b
 
28d94b
 
28d94b
-/* Logical switch ingress table 19 and 20: DHCP options and response
28d94b
+/* Logical switch ingress table 20 and 21: DHCP options and response
28d94b
  * priority 100 flows. */
28d94b
 static void
28d94b
 build_lswitch_dhcp_options_and_response(struct ovn_port *op,
28d94b
@@ -8782,11 +8813,11 @@ build_lswitch_dhcp_options_and_response(struct ovn_port *op,
28d94b
     }
28d94b
 }
28d94b
 
28d94b
-/* Ingress table 19 and 20: DHCP options and response, by default goto
28d94b
+/* Ingress table 20 and 21: DHCP options and response, by default goto
28d94b
  * next. (priority 0).
28d94b
- * Ingress table 21 and 22: DNS lookup and response, by default goto next.
28d94b
+ * Ingress table 22 and 23: DNS lookup and response, by default goto next.
28d94b
  * (priority 0).
28d94b
- * Ingress table 23 - External port handling, by default goto next.
28d94b
+ * Ingress table 24 - External port handling, by default goto next.
28d94b
  * (priority 0). */
28d94b
 static void
28d94b
 build_lswitch_dhcp_and_dns_defaults(struct ovn_datapath *od,
28d94b
@@ -8801,7 +8832,7 @@ build_lswitch_dhcp_and_dns_defaults(struct ovn_datapath *od,
28d94b
     }
28d94b
 }
28d94b
 
28d94b
-/* Logical switch ingress table 21 and 22: DNS lookup and response
28d94b
+/* Logical switch ingress table 22 and 23: DNS lookup and response
28d94b
 * priority 100 flows.
28d94b
 */
28d94b
 static void
28d94b
@@ -8829,7 +8860,7 @@ build_lswitch_dns_lookup_and_response(struct ovn_datapath *od,
28d94b
     }
28d94b
 }
28d94b
 
28d94b
-/* Table 23: External port. Drop ARP request for router ips from
28d94b
+/* Table 24: External port. Drop ARP request for router ips from
28d94b
  * external ports  on chassis not binding those ports.
28d94b
  * This makes the router pipeline to be run only on the chassis
28d94b
  * binding the external ports. */
28d94b
@@ -8846,7 +8877,7 @@ build_lswitch_external_port(struct ovn_port *op,
28d94b
     }
28d94b
 }
28d94b
 
28d94b
-/* Ingress table 24: Destination lookup, broadcast and multicast handling
28d94b
+/* Ingress table 25: Destination lookup, broadcast and multicast handling
28d94b
  * (priority 70 - 100). */
28d94b
 static void
28d94b
 build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od,
28d94b
@@ -8931,7 +8962,7 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od,
28d94b
 }
28d94b
 
28d94b
 
28d94b
-/* Ingress table 24: Add IP multicast flows learnt from IGMP/MLD
28d94b
+/* Ingress table 25: Add IP multicast flows learnt from IGMP/MLD
28d94b
  * (priority 90). */
28d94b
 static void
28d94b
 build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group,
28d94b
@@ -8973,9 +9004,11 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group,
28d94b
                           igmp_group->mcgroup.name);
28d94b
         } else {
28d94b
             /* RFC 4291, section 2.7.1: Skip groups that correspond to all
28d94b
-             * hosts.
28d94b
+             * hosts, all link-local routers and all site routers.
28d94b
              */
28d94b
-            if (ipv6_is_all_hosts(&igmp_group->address)) {
28d94b
+            if (ipv6_is_all_hosts(&igmp_group->address) ||
28d94b
+                ipv6_is_all_router(&igmp_group->address) ||
28d94b
+                ipv6_is_all_site_router(&igmp_group->address)) {
28d94b
                 return;
28d94b
             }
28d94b
             if (atomic_compare_exchange_strong(
28d94b
@@ -9013,7 +9046,7 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group,
28d94b
 
28d94b
 static struct ovs_mutex mcgroup_mutex = OVS_MUTEX_INITIALIZER;
28d94b
 
28d94b
-/* Ingress table 24: Destination lookup, unicast handling (priority 50), */
28d94b
+/* Ingress table 25: Destination lookup, unicast handling (priority 50), */
28d94b
 static void
28d94b
 build_lswitch_ip_unicast_lookup(struct ovn_port *op,
28d94b
                                 struct hmap *lflows,
28d94b
@@ -10471,9 +10504,11 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip,
28d94b
                                struct hmap *lflows,
28d94b
                                struct ds *match, struct ds *action,
28d94b
                                const struct shash *meter_groups,
28d94b
-                               bool ct_lb_mark)
28d94b
+                               const struct chassis_features *features)
28d94b
 {
28d94b
-    const char *ct_natted = ct_lb_mark ? "ct_mark.natted" : "ct_label.natted";
28d94b
+    const char *ct_natted = features->ct_no_masked_label
28d94b
+                            ? "ct_mark.natted"
28d94b
+                            : "ct_label.natted";
28d94b
     char *skip_snat_new_action = NULL;
28d94b
     char *skip_snat_est_action = NULL;
28d94b
     char *new_match;
28d94b
@@ -10484,7 +10519,7 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip,
28d94b
 
28d94b
     bool reject = build_lb_vip_actions(lb_vip, vips_nb, action,
28d94b
                                        lb->selection_fields, false,
28d94b
-                                       ct_lb_mark);
28d94b
+                                       features->ct_no_masked_label);
28d94b
     bool drop = !!strncmp(ds_cstr(action), "ct_lb", strlen("ct_lb"));
28d94b
     if (!drop) {
28d94b
         /* Remove the trailing ");". */
28d94b
@@ -10506,9 +10541,11 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip,
28d94b
     }
28d94b
 
28d94b
     if (lb->skip_snat) {
28d94b
-        skip_snat_new_action = xasprintf("flags.skip_snat_for_lb = 1; %s%s",
28d94b
-                                         ds_cstr(action),
28d94b
-                                         drop ? "" : "; skip_snat);");
28d94b
+        const char *skip_snat = features->ct_lb_related && !drop
28d94b
+                                ? "; skip_snat"
28d94b
+                                : "";
28d94b
+        skip_snat_new_action = xasprintf("flags.skip_snat_for_lb = 1; %s%s);",
28d94b
+                                         ds_cstr(action), skip_snat);
28d94b
         skip_snat_est_action = xasprintf("flags.skip_snat_for_lb = 1; "
28d94b
                                          "next;");
28d94b
     }
28d94b
@@ -10641,9 +10678,11 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip,
28d94b
             skip_snat_new_action, est_match,
28d94b
             skip_snat_est_action, lflows, prio, meter_groups);
28d94b
 
28d94b
-    char *new_actions = xasprintf("flags.force_snat_for_lb = 1; %s%s",
28d94b
-                                  ds_cstr(action),
28d94b
-                                  drop ? "" : "; force_snat);");
28d94b
+    const char *force_snat = features->ct_lb_related && !drop
28d94b
+                             ? "; force_snat"
28d94b
+                             : "";
28d94b
+    char *new_actions = xasprintf("flags.force_snat_for_lb = 1; %s%s);",
28d94b
+                                  ds_cstr(action), force_snat);
28d94b
     build_gw_lrouter_nat_flows_for_lb(lb, gw_router_force_snat,
28d94b
             n_gw_router_force_snat, reject, new_match,
28d94b
             new_actions, est_match,
28d94b
@@ -10898,7 +10937,7 @@ build_lrouter_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows,
28d94b
 
28d94b
         build_lrouter_nat_flows_for_lb(lb_vip, lb, &lb->vips_nb[i],
28d94b
                                        lflows, match, action, meter_groups,
28d94b
-                                       features->ct_no_masked_label);
28d94b
+                                       features);
28d94b
 
28d94b
         if (!build_empty_lb_event_flow(lb_vip, lb, match, action)) {
28d94b
             continue;
28d94b
@@ -14208,7 +14247,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows,
28d94b
                                 const struct hmap *ports, struct ds *match,
28d94b
                                 struct ds *actions,
28d94b
                                 const struct shash *meter_groups,
28d94b
-                                bool ct_lb_mark)
28d94b
+                                const struct chassis_features *features)
28d94b
 {
28d94b
     if (!od->nbr) {
28d94b
         return;
28d94b
@@ -14239,9 +14278,11 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows,
28d94b
      * a dynamically negotiated FTP data channel), but will allow
28d94b
      * related traffic such as an ICMP Port Unreachable through
28d94b
      * that's generated from a non-listening UDP port.  */
28d94b
-    if (od->has_lb_vip) {
28d94b
+    if (od->has_lb_vip && features->ct_lb_related) {
28d94b
         ds_clear(match);
28d94b
-        const char *ct_flag_reg = ct_lb_mark ? "ct_mark" : "ct_label";
28d94b
+        const char *ct_flag_reg = features->ct_no_masked_label
28d94b
+                                  ? "ct_mark"
28d94b
+                                  : "ct_label";
28d94b
 
28d94b
         ds_put_cstr(match, "ct.rel && !ct.est && !ct.new");
28d94b
         size_t match_len = match->length;
28d94b
@@ -14328,6 +14369,23 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows,
28d94b
             sset_add(&nat_entries, nat->external_ip);
28d94b
         } else {
28d94b
             if (!sset_contains(&nat_entries, nat->external_ip)) {
28d94b
+                /* Drop packets coming in from external that still has
28d94b
+                 * destination IP equals to the NAT external IP, to avoid loop.
28d94b
+                 * The packets must have gone through DNAT/unSNAT stage but
28d94b
+                 * failed to convert the destination. */
28d94b
+                ds_clear(match);
28d94b
+                ds_put_format(
28d94b
+                    match, "inport == %s && outport == %s && ip%s.dst == %s",
28d94b
+                    l3dgw_port->json_key, l3dgw_port->json_key,
28d94b
+                    is_v6 ? "6" : "4", nat->external_ip);
28d94b
+                ovn_lflow_add_with_hint(lflows, od,
28d94b
+                                        S_ROUTER_IN_ARP_RESOLVE,
28d94b
+                                        150, ds_cstr(match),
28d94b
+                                        debug_drop_action(),
28d94b
+                                        &nat->header_);
28d94b
+                /* Now for packets coming from other (downlink) LRPs, allow ARP
28d94b
+                 * resolve for the NAT IP, so that such packets can be
28d94b
+                 * forwarded for E/W NAT. */
28d94b
                 ds_clear(match);
28d94b
                 ds_put_format(
28d94b
                     match, "outport == %s && %s == %s",
28d94b
@@ -14464,7 +14522,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows,
28d94b
 
28d94b
     if (od->nbr->n_nat) {
28d94b
         ds_clear(match);
28d94b
-        const char *ct_natted = ct_lb_mark ?
28d94b
+        const char *ct_natted = features->ct_no_masked_label ?
28d94b
                                 "ct_mark.natted" :
28d94b
                                 "ct_label.natted";
28d94b
         ds_put_format(match, "ip && %s == 1", ct_natted);
28d94b
@@ -14581,7 +14639,7 @@ build_lswitch_and_lrouter_iterate_by_od(struct ovn_datapath *od,
28d94b
     build_lrouter_arp_nd_for_datapath(od, lsi->lflows, lsi->meter_groups);
28d94b
     build_lrouter_nat_defrag_and_lb(od, lsi->lflows, lsi->ports, &lsi->match,
28d94b
                                     &lsi->actions, lsi->meter_groups,
28d94b
-                                    lsi->features->ct_no_masked_label);
28d94b
+                                    lsi->features);
28d94b
     build_lb_affinity_default_flows(od, lsi->lflows);
28d94b
 }
28d94b
 
28d94b
@@ -16073,6 +16131,7 @@ northd_init(struct northd_data *data)
28d94b
     data->features = (struct chassis_features) {
28d94b
         .ct_no_masked_label = true,
28d94b
         .mac_binding_timestamp = true,
28d94b
+        .ct_lb_related = true,
28d94b
     };
28d94b
     data->ovn_internal_version_changed = false;
28d94b
 }
28d94b
diff --git a/northd/northd.h b/northd/northd.h
28d94b
index ff8727cb7..4d9055296 100644
28d94b
--- a/northd/northd.h
28d94b
+++ b/northd/northd.h
28d94b
@@ -71,6 +71,7 @@ struct northd_input {
28d94b
 struct chassis_features {
28d94b
     bool ct_no_masked_label;
28d94b
     bool mac_binding_timestamp;
28d94b
+    bool ct_lb_related;
28d94b
 };
28d94b
 
28d94b
 struct northd_data {
28d94b
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
28d94b
index 058cbf71a..4de015e40 100644
28d94b
--- a/northd/ovn-northd.8.xml
28d94b
+++ b/northd/ovn-northd.8.xml
28d94b
@@ -790,8 +790,9 @@
28d94b
         policy, ct_mark.blocked will get set and packets in the
28d94b
         reply direction will no longer be allowed, either. This flow also
28d94b
         clears the register bits reg0[9] and
28d94b
-        reg0[10].  If ACL logging and logging of related packets
28d94b
-        is enabled, then a companion priority-65533 flow will be installed that
28d94b
+        reg0[10] and sets register bit reg0[17].
28d94b
+        If ACL logging and logging of related packets is enabled, then a
28d94b
+        companion priority-65533 flow will be installed that
28d94b
         accomplishes the same thing but also logs the traffic.
28d94b
       
28d94b
 
28d94b
@@ -1028,92 +1029,7 @@
28d94b
       
28d94b
     
28d94b
 
28d94b
-    

Ingress table 14: from-lport ACLs after LB

28d94b
-
28d94b
-    

28d94b
-      Logical flows in this table closely reproduce those in the
28d94b
-      ACL table in the OVN_Northbound database
28d94b
-      for the from-lport direction with the option
28d94b
-      apply-after-lb set to true.
28d94b
-      The priority values from the ACL table have a
28d94b
-      limited range and have 1000 added to them to leave room for OVN default
28d94b
-      flows at both higher and lower priorities.
28d94b
-    

28d94b
-
28d94b
-    
    28d94b
    -      
  • 28d94b
    -        allow apply-after-lb ACLs translate into logical flows
    28d94b
    -        with the next; action.  If there are any stateful ACLs
    28d94b
    -        (including both before-lb and after-lb ACLs)
    28d94b
    -        on this datapath, then allow ACLs translate to
    28d94b
    -        ct_commit; next; (which acts as a hint for the next tables
    28d94b
    -        to commit the connection to conntrack). In case the ACL
    28d94b
    -        has a label then reg3 is loaded with the label value and
    28d94b
    -        reg0[13] bit is set to 1 (which acts as a hint for the
    28d94b
    -        next tables to commit the label to conntrack).
    28d94b
    -      
    28d94b
    -      
  • 28d94b
    -        allow-related apply-after-lb ACLs translate into logical
    28d94b
    -        flows with the ct_commit(ct_label=0/1); next; actions
    28d94b
    -        for new connections and reg0[1] = 1; next; for existing
    28d94b
    -        connections.  In case the ACL has a label then
    28d94b
    -        reg3 is loaded with the label value and
    28d94b
    -        reg0[13] bit is set to 1 (which acts as a hint for the
    28d94b
    -        next tables to commit the label to conntrack).
    28d94b
    -      
    28d94b
    -      
  • 28d94b
    -        allow-stateless apply-after-lb ACLs translate into logical
    28d94b
    -        flows with the next; action.
    28d94b
    -      
    28d94b
    -      
  • 28d94b
    -        reject apply-after-lb ACLs translate into logical
    28d94b
    -        flows with the
    28d94b
    -        tcp_reset { output <-> inport;
    28d94b
    -        next(pipeline=egress,table=5);}
    28d94b
    -        action for TCP connections,icmp4/icmp6 action
    28d94b
    -        for UDP connections, and sctp_abort {output <-%gt; inport;
    28d94b
    -        next(pipeline=egress,table=5);} action for SCTP associations.
    28d94b
    -      
    28d94b
    -      
  • 28d94b
    -        Other apply-after-lb ACLs translate to drop; for new
    28d94b
    -        or untracked connections and ct_commit(ct_label=1/1); for
    28d94b
    -        known connections.  Setting ct_label marks a connection
    28d94b
    -        as one that was previously allowed, but should no longer be
    28d94b
    -        allowed due to a policy change.
    28d94b
    -      
    28d94b
    -    
    28d94b
    -
    28d94b
    -    
      28d94b
      -      
    • 28d94b
      -        One priority-0 fallback flow that matches all packets and advances to
      28d94b
      -        the next table.
      28d94b
      -      
      28d94b
      -    
      28d94b
      -
      28d94b
      -    

      Ingress Table 15: Stateful

      28d94b
      -
      28d94b
      -    
        28d94b
        -      
      • 28d94b
        -        A priority 100 flow is added which commits the packet to the conntrack
        28d94b
        -        and sets the most significant 32-bits of ct_label with the
        28d94b
        -        reg3 value based on the hint provided by previous tables
        28d94b
        -        (with a match for reg0[1] == 1 && reg0[13] == 1).
        28d94b
        -        This is used by the ACLs with label to commit the label
        28d94b
        -        value to conntrack.
        28d94b
        -      
        28d94b
        -
        28d94b
        -      
      • 28d94b
        -        For ACLs without label, a second priority-100 flow commits
        28d94b
        -        packets to connection tracker using ct_commit; next;
        28d94b
        -        action based on a hint provided by the previous tables (with a match
        28d94b
        -        for reg0[1] == 1 && reg0[13] == 0).
        28d94b
        -      
        28d94b
        -      
      • 28d94b
        -        A priority-0 flow that simply moves traffic to the next table.
        28d94b
        -      
        28d94b
        -    
        28d94b
        -
        28d94b
        -    

        Ingress Table 16: Pre-Hairpin

        28d94b
        +    

        Ingress Table 14: Pre-Hairpin

        28d94b
             
          28d94b
                 
        • 28d94b
                   If the logical switch has load balancer(s) configured, then a
          28d94b
          @@ -1131,7 +1047,7 @@
          28d94b
                 
          28d94b
               
          28d94b
           
          28d94b
          -    

          Ingress Table 17: Nat-Hairpin

          28d94b
          +    

          Ingress Table 15: Nat-Hairpin

          28d94b
               
            28d94b
                   
          • 28d94b
                      If the logical switch has load balancer(s) configured, then a
            28d94b
            @@ -1166,7 +1082,7 @@
            28d94b
                   
            28d94b
                 
            28d94b
             
            28d94b
            -    

            Ingress Table 18: Hairpin

            28d94b
            +    

            Ingress Table 16: Hairpin

            28d94b
                 
              28d94b
                     
            • 28d94b
                       

              28d94b
              @@ -1200,6 +1116,100 @@
              28d94b
                     
              28d94b
                   
              28d94b
               
              28d94b
              +    

              Ingress table 17: from-lport ACLs after LB

              28d94b
              +
              28d94b
              +    

              28d94b
              +      Logical flows in this table closely reproduce those in the
              28d94b
              +      ACL table in the OVN_Northbound database
              28d94b
              +      for the from-lport direction with the option
              28d94b
              +      apply-after-lb set to true.
              28d94b
              +      The priority values from the ACL table have a
              28d94b
              +      limited range and have 1000 added to them to leave room for OVN default
              28d94b
              +      flows at both higher and lower priorities.
              28d94b
              +    

              28d94b
              +
              28d94b
              +    
                28d94b
                +      
              • 28d94b
                +        allow apply-after-lb ACLs translate into logical flows
                28d94b
                +        with the next; action.  If there are any stateful ACLs
                28d94b
                +        (including both before-lb and after-lb ACLs)
                28d94b
                +        on this datapath, then allow ACLs translate to
                28d94b
                +        ct_commit; next; (which acts as a hint for the next tables
                28d94b
                +        to commit the connection to conntrack). In case the ACL
                28d94b
                +        has a label then reg3 is loaded with the label value and
                28d94b
                +        reg0[13] bit is set to 1 (which acts as a hint for the
                28d94b
                +        next tables to commit the label to conntrack).
                28d94b
                +      
                28d94b
                +      
              • 28d94b
                +        allow-related apply-after-lb ACLs translate into logical
                28d94b
                +        flows with the ct_commit(ct_label=0/1); next; actions
                28d94b
                +        for new connections and reg0[1] = 1; next; for existing
                28d94b
                +        connections.  In case the ACL has a label then
                28d94b
                +        reg3 is loaded with the label value and
                28d94b
                +        reg0[13] bit is set to 1 (which acts as a hint for the
                28d94b
                +        next tables to commit the label to conntrack).
                28d94b
                +      
                28d94b
                +      
              • 28d94b
                +        allow-stateless apply-after-lb ACLs translate into logical
                28d94b
                +        flows with the next; action.
                28d94b
                +      
                28d94b
                +      
              • 28d94b
                +        reject apply-after-lb ACLs translate into logical
                28d94b
                +        flows with the
                28d94b
                +        tcp_reset { output <-> inport;
                28d94b
                +        next(pipeline=egress,table=5);}
                28d94b
                +        action for TCP connections,icmp4/icmp6 action
                28d94b
                +        for UDP connections, and sctp_abort {output <-%gt; inport;
                28d94b
                +        next(pipeline=egress,table=5);} action for SCTP associations.
                28d94b
                +      
                28d94b
                +      
              • 28d94b
                +        Other apply-after-lb ACLs translate to drop; for new
                28d94b
                +        or untracked connections and ct_commit(ct_label=1/1); for
                28d94b
                +        known connections.  Setting ct_label marks a connection
                28d94b
                +        as one that was previously allowed, but should no longer be
                28d94b
                +        allowed due to a policy change.
                28d94b
                +      
                28d94b
                +    
                28d94b
                +
                28d94b
                +    
                  28d94b
                  +      
                • 28d94b
                  +        One priority-65532 flow matching packets with reg0[17]
                  28d94b
                  +        set (either replies to existing sessions or traffic related to
                  28d94b
                  +        existing sessions) and allows these by advancing to the next
                  28d94b
                  +        table.
                  28d94b
                  +      
                  28d94b
                  +    
                  28d94b
                  +
                  28d94b
                  +    
                    28d94b
                    +      
                  • 28d94b
                    +        One priority-0 fallback flow that matches all packets and advances to
                    28d94b
                    +        the next table.
                    28d94b
                    +      
                    28d94b
                    +    
                    28d94b
                    +
                    28d94b
                    +    

                    Ingress Table 18: Stateful

                    28d94b
                    +
                    28d94b
                    +    
                      28d94b
                      +      
                    • 28d94b
                      +        A priority 100 flow is added which commits the packet to the conntrack
                      28d94b
                      +        and sets the most significant 32-bits of ct_label with the
                      28d94b
                      +        reg3 value based on the hint provided by previous tables
                      28d94b
                      +        (with a match for reg0[1] == 1 && reg0[13] == 1).
                      28d94b
                      +        This is used by the ACLs with label to commit the label
                      28d94b
                      +        value to conntrack.
                      28d94b
                      +      
                      28d94b
                      +
                      28d94b
                      +      
                    • 28d94b
                      +        For ACLs without label, a second priority-100 flow commits
                      28d94b
                      +        packets to connection tracker using ct_commit; next;
                      28d94b
                      +        action based on a hint provided by the previous tables (with a match
                      28d94b
                      +        for reg0[1] == 1 && reg0[13] == 0).
                      28d94b
                      +      
                      28d94b
                      +      
                    • 28d94b
                      +        A priority-0 flow that simply moves traffic to the next table.
                      28d94b
                      +      
                      28d94b
                      +    
                      28d94b
                      +
                      28d94b
                           

                      Ingress Table 19: ARP/ND responder

                      28d94b
                       
                      28d94b
                           

                      28d94b
                      @@ -4257,13 +4267,17 @@ outport = P
                      28d94b
                                 For each row in the NAT table with IPv4 address
                      28d94b
                                 A in the 
                      28d94b
                                 table="NAT" db="OVN_Northbound"/> column of
                      28d94b
                      -          <ref table="NAT" db="OVN_Northbound"/> table, a priority-100
                      28d94b
                      -          flow with the match outport === P &&
                      28d94b
                      -          reg0 == A has actions eth.dst = E;
                      28d94b
                      -          next;, where P is the distributed logical router
                      28d94b
                      -          port, E is the Ethernet address if set in the
                      28d94b
                      -          <ref column="external_mac" table="NAT" db="OVN_Northbound"/> column
                      28d94b
                      -          of <ref table="NAT" db="OVN_Northbound"/> table for of type
                      28d94b
                      +          <ref table="NAT" db="OVN_Northbound"/> table, below two flows are
                      28d94b
                      +          programmed:
                      28d94b
                      +        

                      28d94b
                      +
                      28d94b
                      +        

                      28d94b
                      +          A priority-100 flow with the match outport == P
                      28d94b
                      +          && reg0 == A has actions eth.dst =
                      28d94b
                      +          E; next;, where P is the distributed
                      28d94b
                      +          logical router port, E is the Ethernet address if set in
                      28d94b
                      +          the <ref column="external_mac" table="NAT" db="OVN_Northbound"/>
                      28d94b
                      +          column of <ref table="NAT" db="OVN_Northbound"/> table for of type
                      28d94b
                                 dnat_and_snat, otherwise the Ethernet address of the
                      28d94b
                                 distributed logical router port. Note that if the
                      28d94b
                                 <ref column="external_ip" table="NAT" db="OVN_Northbound"/> is not
                      28d94b
                      @@ -4273,9 +4287,18 @@ outport = P
                      28d94b
                                 will be added.
                      28d94b
                               

                      28d94b
                       
                      28d94b
                      +        

                      28d94b
                      +          Corresponding to the above flow, a priority-150 flow with the match
                      28d94b
                      +          inport == P && outport == P
                      28d94b
                      +          && ip4.dst == A has actions
                      28d94b
                      +          drop; to exclude packets that have gone through
                      28d94b
                      +          DNAT/unSNAT stage but failed to convert the destination, to avoid
                      28d94b
                      +          loop.
                      28d94b
                      +        

                      28d94b
                      +
                      28d94b
                               

                      28d94b
                                 For IPv6 NAT entries, same flows are added, but using the register
                      28d94b
                      -          xxreg0 for the match.
                      28d94b
                      +          xxreg0 and field ip6 for the match.
                      28d94b
                               

                      28d94b
                             
                      28d94b
                       
                      28d94b
                      diff --git a/ovn-architecture.7.xml b/ovn-architecture.7.xml
                      28d94b
                      index b2e00d6e4..cb1064f71 100644
                      28d94b
                      --- a/ovn-architecture.7.xml
                      28d94b
                      +++ b/ovn-architecture.7.xml
                      28d94b
                      @@ -2832,8 +2832,7 @@
                      28d94b
                             The maximum number of networks is reduced to 4096.
                      28d94b
                           
                      28d94b
                           
                    • 28d94b
                      -      The maximum number of ports per network is reduced to 4096. (Including
                      28d94b
                      -      multicast group ports.)
                      28d94b
                      +      The maximum number of ports per network is reduced to 2048.
                      28d94b
                           
                      28d94b
                           
                    • 28d94b
                             ACLs matching against logical ingress port identifiers are not supported.
                      28d94b
                      diff --git a/tests/atlocal.in b/tests/atlocal.in
                      28d94b
                      index 0b9a31276..02e9ce9bb 100644
                      28d94b
                      --- a/tests/atlocal.in
                      28d94b
                      +++ b/tests/atlocal.in
                      28d94b
                      @@ -166,6 +166,9 @@ fi
                      28d94b
                       # Set HAVE_TCPDUMP
                      28d94b
                       find_command tcpdump
                      28d94b
                       
                      28d94b
                      +# Set HAVE_XXD
                      28d94b
                      +find_command xxd
                      28d94b
                      +
                      28d94b
                       # Set HAVE_LFTP
                      28d94b
                       find_command lftp
                      28d94b
                       
                      28d94b
                      diff --git a/tests/network-functions.at b/tests/network-functions.at
                      28d94b
                      index c583bc31e..a2481c55c 100644
                      28d94b
                      --- a/tests/network-functions.at
                      28d94b
                      +++ b/tests/network-functions.at
                      28d94b
                      @@ -128,12 +128,18 @@ OVS_START_SHELL_HELPERS
                      28d94b
                       # hex_to_binary HEXDIGITS
                      28d94b
                       #
                      28d94b
                       # Converts the pairs of HEXDIGITS into bytes and prints them on stdout.
                      28d94b
                      -hex_to_binary() {
                      28d94b
                      -    printf $(while test -n "$1"; do
                      28d94b
                      -                 printf '\\%03o' 0x$(expr "$1" : '\(..\)')
                      28d94b
                      -                 set -- "${1##??}"
                      28d94b
                      -             done)
                      28d94b
                      -}
                      28d94b
                      +if test x$HAVE_XXD = xno; then
                      28d94b
                      +    hex_to_binary() {
                      28d94b
                      +        printf $(while test -n "$1"; do
                      28d94b
                      +                     printf '\\%03o' 0x$(expr "$1" : '\(..\)')
                      28d94b
                      +                     set -- "${1##??}"
                      28d94b
                      +                 done)
                      28d94b
                      +    }
                      28d94b
                      +else
                      28d94b
                      +    hex_to_binary() {
                      28d94b
                      +        echo $1 | xxd -r -p
                      28d94b
                      +    }
                      28d94b
                      +fi
                      28d94b
                       
                      28d94b
                       # tcpdump_hex TITLE PACKET
                      28d94b
                       #
                      28d94b
                      diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
                      28d94b
                      index 6bc9ba75d..e2f4fc85c 100644
                      28d94b
                      --- a/tests/ovn-controller.at
                      28d94b
                      +++ b/tests/ovn-controller.at
                      28d94b
                      @@ -2499,3 +2499,30 @@ AT_CHECK([GET_LOCAL_TEMPLATE_VARS], [1], [])
                      28d94b
                       
                      28d94b
                       AT_CLEANUP
                      28d94b
                       ])
                      28d94b
                      +
                      28d94b
                      +OVN_FOR_EACH_NORTHD([
                      28d94b
                      +AT_SETUP([ovn-controller - Requested SNAT Zone in router creation transaction])
                      28d94b
                      +ovn_start
                      28d94b
                      +
                      28d94b
                      +net_add n1
                      28d94b
                      +sim_add hv1
                      28d94b
                      +as hv1
                      28d94b
                      +check ovs-vsctl add-br br-phys
                      28d94b
                      +ovn_attach n1 br-phys 192.168.0.1
                      28d94b
                      +
                      28d94b
                      +dnl This is key. Add the snat-ct-zone when creating the logical router and then
                      28d94b
                      +dnl do not make any further changes to the logical router settings.
                      28d94b
                      +check ovn-nbctl lr-add lr0 -- set Logical_Router lr0 options:snat-ct-zone=666
                      28d94b
                      +check ovn-nbctl lrp-add lr0 lrp-gw 01:00:00:00:00:01 172.16.0.1
                      28d94b
                      +check ovn-nbctl lrp-set-gateway-chassis lrp-gw hv1
                      28d94b
                      +
                      28d94b
                      +check ovn-nbctl --wait=hv sync
                      28d94b
                      +
                      28d94b
                      +lr_uuid=$(fetch_column Datapath_Binding _uuid external_ids:name=lr0)
                      28d94b
                      +ct_zones=$(ovn-appctl -t ovn-controller ct-zone-list)
                      28d94b
                      +zone_num=$(printf "$ct_zones" | grep ${lr_uuid}_snat | cut -d ' ' -f 2)
                      28d94b
                      +
                      28d94b
                      +check test "$zone_num" -eq 666
                      28d94b
                      +
                      28d94b
                      +AT_CLEANUP
                      28d94b
                      +])
                      28d94b
                      diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
                      28d94b
                      index c25d1122c..072102f36 100644
                      28d94b
                      --- a/tests/ovn-northd.at
                      28d94b
                      +++ b/tests/ovn-northd.at
                      28d94b
                      @@ -2232,9 +2232,9 @@ check ovn-nbctl acl-add sw0 to-lport 1002 'outport == "sw0-p1" && ip4.src == 10.
                      28d94b
                       check ovn-nbctl acl-add sw0 to-lport 1002 'outport == "sw0-p1" && ip4.src == 10.0.0.13' allow
                      28d94b
                       check ovn-nbctl acl-add pg0 to-lport 1002 'outport == "pg0" && ip4.src == 10.0.0.11' drop
                      28d94b
                       
                      28d94b
                      -acl1=$(ovn-nbctl --bare --column _uuid,match find acl | grep -B1 '10.0.0.12' | head -1)
                      28d94b
                      -acl2=$(ovn-nbctl --bare --column _uuid,match find acl | grep -B1 '10.0.0.13' | head -1)
                      28d94b
                      -acl3=$(ovn-nbctl --bare --column _uuid,match find acl | grep -B1 '10.0.0.11' | head -1)
                      28d94b
                      +acl1=$(ovn-nbctl --bare --column _uuid,match find acl | grep -F -B1 '10.0.0.12' | head -1)
                      28d94b
                      +acl2=$(ovn-nbctl --bare --column _uuid,match find acl | grep -F -B1 '10.0.0.13' | head -1)
                      28d94b
                      +acl3=$(ovn-nbctl --bare --column _uuid,match find acl | grep -F -B1 '10.0.0.11' | head -1)
                      28d94b
                       check ovn-nbctl set acl $acl1 log=true severity=alert meter=meter_me name=acl_one
                      28d94b
                       check ovn-nbctl set acl $acl2 log=true severity=info  meter=meter_me name=acl_two
                      28d94b
                       check ovn-nbctl set acl $acl3 log=true severity=info  meter=meter_me name=acl_three
                      28d94b
                      @@ -2472,8 +2472,8 @@ AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e
                      28d94b
                         table=7 (ls_in_acl_hint     ), priority=7    , match=(ct.new && !ct.est), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=1    , match=(ip && !ct.est), action=(reg0[[1]] = 1; next;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=1    , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
                      28d94b
                      -  table=8 (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  table=8 (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;)
                      28d94b
                      +  table=8 (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  table=8 (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; reg0[[17]] = 1; next;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                      @@ -2485,7 +2485,8 @@ check ovn-nbctl --wait=sb \
                      28d94b
                           -- ls-lb-add ls lb
                      28d94b
                       
                      28d94b
                       AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e ls_in_acl -e ls_out_acl | sort], [0], [dnl
                      28d94b
                      -  table=14(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +  table=17(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +  table=17(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;)
                      28d94b
                         table=3 (ls_out_acl_hint    ), priority=0    , match=(1), action=(next;)
                      28d94b
                         table=3 (ls_out_acl_hint    ), priority=1    , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
                      28d94b
                         table=3 (ls_out_acl_hint    ), priority=2    , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
                      28d94b
                      @@ -2518,8 +2519,8 @@ AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e
                      28d94b
                         table=8 (ls_in_acl          ), priority=1001 , match=(reg0[[7]] == 1 && (ip)), action=(reg0[[1]] = 1; next;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=1001 , match=(reg0[[8]] == 1 && (ip)), action=(next;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;)
                      28d94b
                      -  table=8 (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  table=8 (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;)
                      28d94b
                      +  table=8 (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  table=8 (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; reg0[[17]] = 1; next;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                       ])
                      28d94b
                      @@ -2528,7 +2529,7 @@ ovn-nbctl --wait=sb clear logical_switch ls acls
                      28d94b
                       ovn-nbctl --wait=sb clear logical_switch ls load_balancer
                      28d94b
                       
                      28d94b
                       AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e ls_in_acl -e ls_out_acl | sort], [0], [dnl
                      28d94b
                      -  table=14(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +  table=17(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
                      28d94b
                         table=3 (ls_out_acl_hint    ), priority=65535, match=(1), action=(next;)
                      28d94b
                         table=4 (ls_out_acl         ), priority=65535, match=(1), action=(next;)
                      28d94b
                         table=7 (ls_in_acl_hint     ), priority=65535, match=(1), action=(next;)
                      28d94b
                      @@ -4360,8 +4361,8 @@ ovn-sbctl dump-flows sw0 > sw0flows
                      28d94b
                       AT_CAPTURE_FILE([sw0flows])
                      28d94b
                       
                      28d94b
                       AT_CHECK([grep -w "ls_in_acl" sw0flows | grep 6553 | sort | sed 's/table=./table=?/'], [0], [dnl
                      28d94b
                      -  table=? (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  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;)
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  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; reg0[[17]] = 1; next;)
                      28d94b
                         table=? (ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                         table=? (ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                       ])
                      28d94b
                      @@ -4380,9 +4381,9 @@ ovn-sbctl dump-flows sw0 > sw0flows
                      28d94b
                       AT_CAPTURE_FILE([sw0flows])
                      28d94b
                       
                      28d94b
                       AT_CHECK([grep -w "ls_in_acl" sw0flows | grep 6553 | sort | sed 's/table=./table=?/'], [0], [dnl
                      28d94b
                      -  table=? (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                         table=? (ls_in_acl          ), priority=65532, match=((ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                      -  table=? (ls_in_acl          ), priority=65532, match=(ct.est && !ct.rel && !ct.new && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;)
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(ct.est && !ct.rel && !ct.new && ct.rpl && ct_mark.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;)
                      28d94b
                         table=? (ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                      @@ -4404,8 +4405,8 @@ ovn-sbctl dump-flows sw0 > sw0flows
                      28d94b
                       AT_CAPTURE_FILE([sw0flows])
                      28d94b
                       
                      28d94b
                       AT_CHECK([grep -w "ls_in_acl" sw0flows | grep 6553 | sort | sed 's/table=./table=?/'], [0], [dnl
                      28d94b
                      -  table=? (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  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;)
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  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; reg0[[17]] = 1; next;)
                      28d94b
                         table=? (ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                         table=? (ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                       ])
                      28d94b
                      @@ -5139,7 +5140,8 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sed 's/table=./table=?/' | sort], [0], [
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       check ovn-sbctl chassis-add gw1 geneve 127.0.0.1 \
                      28d94b
                      -  -- set chassis gw1 other_config:ct-no-masked-label="true"
                      28d94b
                      +  -- set chassis gw1 other_config:ct-no-masked-label="true" \
                      28d94b
                      +  -- set chassis gw1 other_config:ovn-ct-lb-related="true"
                      28d94b
                       
                      28d94b
                       # Create a distributed gw port on lr0
                      28d94b
                       check ovn-nbctl ls-add public
                      28d94b
                      @@ -6685,11 +6687,12 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0],
                      28d94b
                         table=??(ls_in_acl          ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_mark.blocked = 1; }; /* drop */)
                      28d94b
                         table=??(ls_in_acl          ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */)
                      28d94b
                         table=??(ls_in_acl          ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;)
                      28d94b
                      -  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  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;)
                      28d94b
                      +  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  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; reg0[[17]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                         table=??(ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +  table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=1    , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=2    , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
                      28d94b
                      @@ -6730,8 +6733,8 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0],
                      28d94b
                         table=??(ls_in_acl          ), priority=1    , match=(ip && !ct.est), action=(reg0[[1]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=1    , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;)
                      28d94b
                      -  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  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;)
                      28d94b
                      +  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  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; reg0[[17]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                         table=??(ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
                      28d94b
                      @@ -6743,6 +6746,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0],
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=2003 , match=(reg0[[8]] == 1 && (ip4 && icmp)), action=(next;)
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_mark.blocked = 1; }; /* drop */)
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */)
                      28d94b
                      +  table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=1    , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=2    , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
                      28d94b
                      @@ -6787,8 +6791,8 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0],
                      28d94b
                         table=??(ls_in_acl          ), priority=2003 , match=(reg0[[7]] == 1 && (ip4 && icmp)), action=(reg0[[1]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=2003 , match=(reg0[[8]] == 1 && (ip4 && icmp)), action=(next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;)
                      28d94b
                      -  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  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;)
                      28d94b
                      +  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  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; reg0[[17]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                         table=??(ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
                      28d94b
                      @@ -6796,6 +6800,7 @@ AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0],
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=2001 , match=(reg0[[9]] == 1 && (ip4)), action=(/* drop */)
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_mark.blocked = 1; }; /* drop */)
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */)
                      28d94b
                      +  table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=1    , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=2    , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
                      28d94b
                      @@ -7219,11 +7224,12 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/
                      28d94b
                         table=??(ls_in_acl          ), priority=1001 , match=(reg0[[7]] == 1 && (ip4 && tcp)), action=(reg0[[1]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=1001 , match=(reg0[[8]] == 1 && (ip4 && tcp)), action=(next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;)
                      28d94b
                      -  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  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;)
                      28d94b
                      +  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  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; reg0[[17]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                         table=??(ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(drop;)
                      28d94b
                      +  table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=1    , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=2    , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
                      28d94b
                      @@ -7342,13 +7348,14 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/
                      28d94b
                         table=??(ls_in_acl          ), priority=1    , match=(ip && !ct.est), action=(drop;)
                      28d94b
                         table=??(ls_in_acl          ), priority=1    , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;)
                      28d94b
                      -  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  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;)
                      28d94b
                      +  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  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; reg0[[17]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                         table=??(ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(drop;)
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=1001 , match=(reg0[[7]] == 1 && (ip4 && tcp)), action=(reg0[[1]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=1001 , match=(reg0[[8]] == 1 && (ip4 && tcp)), action=(next;)
                      28d94b
                      +  table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=1    , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=2    , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
                      28d94b
                      @@ -7467,11 +7474,12 @@ AT_CHECK([ovn-sbctl dump-flows | grep -E "ls_.*_acl" | sed 's/table=../table=??/
                      28d94b
                         table=??(ls_in_acl          ), priority=1    , match=(ip && !ct.est), action=(drop;)
                      28d94b
                         table=??(ls_in_acl          ), priority=1    , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;)
                      28d94b
                      -  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  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;)
                      28d94b
                      +  table=??(ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  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; reg0[[17]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                         table=??(ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                         table=??(ls_in_acl_after_lb ), priority=0    , match=(1), action=(drop;)
                      28d94b
                      +  table=??(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=0    , match=(1), action=(next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=1    , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
                      28d94b
                         table=??(ls_in_acl_hint     ), priority=2    , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
                      28d94b
                      @@ -7775,7 +7783,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl
                      28d94b
                         table=??(ls_in_check_port_sec), priority=100  , match=(vlan.present), action=(drop;)
                      28d94b
                         table=??(ls_in_check_port_sec), priority=50   , match=(1), action=(reg0[[15]] = check_in_port_sec(); next;)
                      28d94b
                         table=??(ls_in_check_port_sec), priority=70   , match=(inport == "localnetport"), action=(set_queue(10); reg0[[15]] = check_in_port_sec(); next;)
                      28d94b
                      -  table=??(ls_in_check_port_sec), priority=70   , match=(inport == "sw0p1"), action=(reg0[[14]] = 1; next(pipeline=ingress, table=18);)
                      28d94b
                      +  table=??(ls_in_check_port_sec), priority=70   , match=(inport == "sw0p1"), action=(reg0[[14]] = 1; next(pipeline=ingress, table=16);)
                      28d94b
                         table=??(ls_in_check_port_sec), priority=70   , match=(inport == "sw0p2"), action=(set_queue(10); reg0[[15]] = check_in_port_sec(); next;)
                      28d94b
                         table=??(ls_in_apply_port_sec), priority=0    , match=(1), action=(next;)
                      28d94b
                         table=??(ls_in_apply_port_sec), priority=50   , match=(reg0[[15]] == 1), action=(drop;)
                      28d94b
                      @@ -7832,6 +7840,22 @@ AT_CHECK([ovn-sbctl lflow-list | grep -e natted -e ct_lb], [0], [dnl
                      28d94b
                         table=2 (ls_out_pre_stateful), priority=110  , match=(reg0[[2]] == 1), action=(ct_lb;)
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                      +check ovn-nbctl --wait=sb set logical_router lr options:lb_force_snat_ip="42.42.42.1"
                      28d94b
                      +AT_CHECK([ovn-sbctl lflow-list | grep lr_in_dnat], [0], [dnl
                      28d94b
                      +  table=7 (lr_in_dnat         ), priority=110  , match=(ct.est && !ct.rel && ip4 && reg0 == 66.66.66.66 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;)
                      28d94b
                      +  table=7 (lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && ip4 && reg0 == 66.66.66.66), action=(flags.force_snat_for_lb = 1; ct_lb(backends=42.42.42.2);)
                      28d94b
                      +  table=7 (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +])
                      28d94b
                      +check ovn-nbctl remove logical_router lr options lb_force_snat_ip
                      28d94b
                      +
                      28d94b
                      +check ovn-nbctl --wait=sb set load_balancer lb-test options:skip_snat="true"
                      28d94b
                      +AT_CHECK([ovn-sbctl lflow-list | grep lr_in_dnat], [0], [dnl
                      28d94b
                      +  table=7 (lr_in_dnat         ), priority=110  , match=(ct.est && !ct.rel && ip4 && reg0 == 66.66.66.66 && ct_label.natted == 1), action=(flags.skip_snat_for_lb = 1; next;)
                      28d94b
                      +  table=7 (lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && ip4 && reg0 == 66.66.66.66), action=(flags.skip_snat_for_lb = 1; ct_lb(backends=42.42.42.2);)
                      28d94b
                      +  table=7 (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +])
                      28d94b
                      +check ovn-nbctl remove load_balancer lb-test options skip_snat
                      28d94b
                      +
                      28d94b
                       AS_BOX([Chassis upgrades and supports ct_lb_mark - use ct_lb_mark and ct_mark.natted])
                      28d94b
                       check ovn-sbctl set chassis hv other_config:ct-no-masked-label=true
                      28d94b
                       check ovn-nbctl --wait=sb sync
                      28d94b
                      @@ -7865,8 +7889,8 @@ AT_CHECK([ovn-sbctl lflow-list | grep 'ls.*acl.*blocked' ], [0], [dnl
                      28d94b
                         table=7 (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;)
                      28d94b
                         table=7 (ls_in_acl_hint     ), priority=2    , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
                      28d94b
                         table=7 (ls_in_acl_hint     ), priority=1    , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
                      28d94b
                      -  table=8 (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  table=8 (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;)
                      28d94b
                      +  table=8 (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  table=8 (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; reg0[[17]] = 1; next;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=1    , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
                      28d94b
                         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;)
                      28d94b
                      @@ -7887,15 +7911,15 @@ AT_CHECK([ovn-sbctl lflow-list | grep 'ls.*acl.*blocked' ], [0], [dnl
                      28d94b
                         table=7 (ls_in_acl_hint     ), priority=4    , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;)
                      28d94b
                         table=7 (ls_in_acl_hint     ), priority=2    , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;)
                      28d94b
                         table=7 (ls_in_acl_hint     ), priority=1    , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;)
                      28d94b
                      -  table=8 (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  table=8 (ls_in_acl          ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;)
                      28d94b
                      +  table=8 (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(reg0[[17]] = 1; next;)
                      28d94b
                      +  table=8 (ls_in_acl          ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=1    , match=(ip && ct.est && ct_label.blocked == 1), action=(reg0[[1]] = 1; next;)
                      28d94b
                         table=3 (ls_out_acl_hint    ), priority=6    , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;)
                      28d94b
                         table=3 (ls_out_acl_hint    ), priority=4    , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;)
                      28d94b
                         table=3 (ls_out_acl_hint    ), priority=2    , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;)
                      28d94b
                         table=3 (ls_out_acl_hint    ), priority=1    , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;)
                      28d94b
                      -  table=4 (ls_out_acl         ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      +  table=4 (ls_out_acl         ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;)
                      28d94b
                         table=4 (ls_out_acl         ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;)
                      28d94b
                         table=4 (ls_out_acl         ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;)
                      28d94b
                         table=4 (ls_out_acl         ), priority=1    , match=(ip && ct.est && ct_label.blocked == 1), action=(reg0[[1]] = 1; next;)
                      28d94b
                      @@ -7909,15 +7933,15 @@ AT_CHECK([ovn-sbctl lflow-list | grep 'ls.*acl.*blocked' ], [0], [dnl
                      28d94b
                         table=7 (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;)
                      28d94b
                         table=7 (ls_in_acl_hint     ), priority=2    , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
                      28d94b
                         table=7 (ls_in_acl_hint     ), priority=1    , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
                      28d94b
                      -  table=8 (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      -  table=8 (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;)
                      28d94b
                      +  table=8 (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; next;)
                      28d94b
                      +  table=8 (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; reg0[[17]] = 1; next;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                         table=8 (ls_in_acl          ), priority=1    , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
                      28d94b
                         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;)
                      28d94b
                         table=3 (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;)
                      28d94b
                         table=3 (ls_out_acl_hint    ), priority=2    , match=(ct.est && ct_mark.blocked == 1), action=(reg0[[9]] = 1; next;)
                      28d94b
                         table=3 (ls_out_acl_hint    ), priority=1    , match=(ct.est && ct_mark.blocked == 0), action=(reg0[[10]] = 1; next;)
                      28d94b
                      -  table=4 (ls_out_acl         ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      +  table=4 (ls_out_acl         ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(next;)
                      28d94b
                         table=4 (ls_out_acl         ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;)
                      28d94b
                         table=4 (ls_out_acl         ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                         table=4 (ls_out_acl         ), priority=1    , match=(ip && ct.est && ct_mark.blocked == 1), action=(reg0[[1]] = 1; next;)
                      28d94b
                      @@ -8437,3 +8461,156 @@ check_row_count sb:Chassis_Template_Var 0
                      28d94b
                       
                      28d94b
                       AT_CLEANUP
                      28d94b
                       ])
                      28d94b
                      +
                      28d94b
                      +OVN_FOR_EACH_NORTHD_NO_HV([
                      28d94b
                      +AT_SETUP([Load balancer CT related backwards compatibility])
                      28d94b
                      +AT_KEYWORDS([lb])
                      28d94b
                      +ovn_start
                      28d94b
                      +
                      28d94b
                      +check ovn-nbctl                                               \
                      28d94b
                      +  -- ls-add ls                                                \
                      28d94b
                      +  -- lr-add lr -- set logical_router lr options:chassis=local \
                      28d94b
                      +  -- lb-add lb-test 192.168.0.1 192.168.1.10                  \
                      28d94b
                      +  -- ls-lb-add ls lb-test                                     \
                      28d94b
                      +  -- lr-lb-add lr lb-test
                      28d94b
                      +
                      28d94b
                      +m4_define([DUMP_FLOWS_SORTED], [sed 's/table=[[0-9]]\{1,2\}/table=?/' | sort])
                      28d94b
                      +
                      28d94b
                      +AS_BOX([No chassis registered - CT related flows should be installed])
                      28d94b
                      +check ovn-nbctl --wait=sb sync
                      28d94b
                      +ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows0
                      28d94b
                      +
                      28d94b
                      +AT_CHECK([grep -e "lr_in_defrag" -e "lr_in_dnat" lflows0], [0], [dnl
                      28d94b
                      +  table=? (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +  table=? (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 192.168.0.1), action=(reg0 = 192.168.0.1; ct_dnat;)
                      28d94b
                      +  table=? (lr_in_defrag       ), priority=50   , match=(icmp || icmp6), action=(ct_dnat;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=110  , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_mark.natted == 1), action=(next;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(ct_lb_mark(backends=192.168.1.10);)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=70   , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=70   , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;)
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows0 | grep "priority=65532"], [0], [dnl
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  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; reg0[[17]] = 1; next;)
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                      +  table=? (ls_out_acl         ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      +  table=? (ls_out_acl         ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;)
                      28d94b
                      +  table=? (ls_out_acl         ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                      +  table=? (ls_out_acl         ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                      +  table=?(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;)
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +
                      28d94b
                      +AS_BOX([Chassis registered that doesn't support CT related])
                      28d94b
                      +check ovn-sbctl chassis-add hv geneve 127.0.0.1
                      28d94b
                      +check ovn-nbctl --wait=sb sync
                      28d94b
                      +ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows1
                      28d94b
                      +
                      28d94b
                      +AT_CHECK([grep -e "lr_in_defrag" -e "lr_in_dnat" lflows1], [0], [dnl
                      28d94b
                      +  table=? (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +  table=? (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 192.168.0.1), action=(reg0 = 192.168.0.1; ct_dnat;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=110  , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_label.natted == 1), action=(next;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(ct_lb(backends=192.168.1.10);)
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +check ovn-nbctl --wait=sb set logical_router lr options:lb_force_snat_ip="192.168.1.1"
                      28d94b
                      +AT_CHECK([ovn-sbctl lflow-list | grep lr_in_dnat], [0], [dnl
                      28d94b
                      +  table=7 (lr_in_dnat         ), priority=110  , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;)
                      28d94b
                      +  table=7 (lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(flags.force_snat_for_lb = 1; ct_lb(backends=192.168.1.10);)
                      28d94b
                      +  table=7 (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +])
                      28d94b
                      +check ovn-nbctl remove logical_router lr options lb_force_snat_ip
                      28d94b
                      +
                      28d94b
                      +check ovn-nbctl --wait=sb set load_balancer lb-test options:skip_snat="true"
                      28d94b
                      +AT_CHECK([ovn-sbctl lflow-list | grep lr_in_dnat], [0], [dnl
                      28d94b
                      +  table=7 (lr_in_dnat         ), priority=110  , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_label.natted == 1), action=(flags.skip_snat_for_lb = 1; next;)
                      28d94b
                      +  table=7 (lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(flags.skip_snat_for_lb = 1; ct_lb(backends=192.168.1.10);)
                      28d94b
                      +  table=7 (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +])
                      28d94b
                      +check ovn-nbctl remove load_balancer lb-test options skip_snat
                      28d94b
                      +
                      28d94b
                      +AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows1 | grep "priority=65532"], [0], [dnl
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(reg0[[17]] = 1; next;)
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; reg0[[17]] = 1; next;)
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;)
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                      +  table=? (ls_out_acl         ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;)
                      28d94b
                      +  table=? (ls_out_acl         ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;)
                      28d94b
                      +  table=? (ls_out_acl         ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;)
                      28d94b
                      +  table=? (ls_out_acl         ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                      +  table=?(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;)
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +AS_BOX([Chassis upgrades and supports CT related])
                      28d94b
                      +check ovn-sbctl set chassis hv other_config:ct-no-masked-label=true
                      28d94b
                      +check ovn-sbctl set chassis hv other_config:ovn-ct-lb-related=true
                      28d94b
                      +check ovn-nbctl --wait=sb sync
                      28d94b
                      +ovn-sbctl dump-flows | DUMP_FLOWS_SORTED > lflows2
                      28d94b
                      +
                      28d94b
                      +AT_CHECK([grep -e "lr_in_defrag" -e "lr_in_dnat" lflows2], [0], [dnl
                      28d94b
                      +  table=? (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +  table=? (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 192.168.0.1), action=(reg0 = 192.168.0.1; ct_dnat;)
                      28d94b
                      +  table=? (lr_in_defrag       ), priority=50   , match=(icmp || icmp6), action=(ct_dnat;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=110  , match=(ct.est && !ct.rel && ip4 && reg0 == 192.168.0.1 && ct_mark.natted == 1), action=(next;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && ip4 && reg0 == 192.168.0.1), action=(ct_lb_mark(backends=192.168.1.10);)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && !ct.new), action=(ct_commit_nat;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=70   , match=(ct.rel && !ct.est && !ct.new && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; ct_commit_nat;)
                      28d94b
                      +  table=? (lr_in_dnat         ), priority=70   , match=(ct.rel && !ct.est && !ct.new && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;)
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +AT_CHECK([grep -e "ls_in_acl" -e "ls_out_acl" lflows2 | grep "priority=65532"], [0], [dnl
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(reg0[[17]] = 1; ct_commit_nat;)
                      28d94b
                      +  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; reg0[[17]] = 1; next;)
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                      +  table=? (ls_in_acl          ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                      +  table=? (ls_out_acl         ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_mark.blocked == 0), action=(ct_commit_nat;)
                      28d94b
                      +  table=? (ls_out_acl         ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_mark.blocked == 0), action=(next;)
                      28d94b
                      +  table=? (ls_out_acl         ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_mark.blocked == 1)), action=(drop;)
                      28d94b
                      +  table=? (ls_out_acl         ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;)
                      28d94b
                      +  table=?(ls_in_acl_after_lb ), priority=65532, match=(reg0[[17]] == 1), action=(next;)
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +AT_CLEANUP
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +OVN_FOR_EACH_NORTHD_NO_HV([
                      28d94b
                      +AT_SETUP([Chassis-feature compatibitility - remote chassis])
                      28d94b
                      +ovn_start
                      28d94b
                      +
                      28d94b
                      +AS_BOX([Local chassis])
                      28d94b
                      +check ovn-sbctl chassis-add hv1 geneve 127.0.0.1 \
                      28d94b
                      +  -- set chassis hv1 other_config:ct-no-masked-label=true \
                      28d94b
                      +  -- set chassis hv1 other_config:ovn-ct-lb-related=true \
                      28d94b
                      +  -- set chassis hv1 other_config:mac-binding-timestamp=true
                      28d94b
                      +
                      28d94b
                      +check ovn-nbctl --wait=sb sync
                      28d94b
                      +
                      28d94b
                      +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE debug/chassis-features-list], [0], [dnl
                      28d94b
                      +ct_no_masked_label:    true
                      28d94b
                      +ct_lb_related:         true
                      28d94b
                      +mac_binding_timestamp: true
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +AS_BOX([Remote chassis])
                      28d94b
                      +check ovn-sbctl chassis-add hv2 geneve 127.0.0.2 \
                      28d94b
                      +  -- set chassis hv2 other_config:is-remote=true \
                      28d94b
                      +  -- set chassis hv2 other_config:ct-no-masked-label=false \
                      28d94b
                      +  -- set chassis hv2 other_config:ovn-ct-lb-related=false \
                      28d94b
                      +  -- set chassis hv2 other_config:mac-binding-timestamp=false
                      28d94b
                      +
                      28d94b
                      +check ovn-nbctl --wait=sb sync
                      28d94b
                      +
                      28d94b
                      +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE debug/chassis-features-list], [0], [dnl
                      28d94b
                      +ct_no_masked_label:    true
                      28d94b
                      +ct_lb_related:         true
                      28d94b
                      +mac_binding_timestamp: true
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +AT_CLEANUP
                      28d94b
                      +])
                      28d94b
                      diff --git a/tests/ovn.at b/tests/ovn.at
                      28d94b
                      index ad2014de6..f77a4983d 100644
                      28d94b
                      --- a/tests/ovn.at
                      28d94b
                      +++ b/tests/ovn.at
                      28d94b
                      @@ -4461,7 +4461,12 @@ for i in 1 2 3; do
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       # Gracefully terminate daemons
                      28d94b
                      -OVN_CLEANUP([hv1],[hv2],[vtep])
                      28d94b
                      +
                      28d94b
                      +OVN_CLEANUP_SBOX([hv1])
                      28d94b
                      +OVN_CLEANUP_SBOX([hv2])
                      28d94b
                      +OVS_WAIT_UNTIL([test `as vtep ovs-vsctl list-ports vtep_bfd | wc -l` -eq 0])
                      28d94b
                      +OVN_CLEANUP([vtep])
                      28d94b
                      +
                      28d94b
                       OVN_CLEANUP_VSWITCH([hv3])
                      28d94b
                       
                      28d94b
                       AT_CLEANUP
                      28d94b
                      @@ -25064,8 +25069,10 @@ OVN_FOR_EACH_NORTHD([
                      28d94b
                       AT_SETUP([interconnection])
                      28d94b
                       
                      28d94b
                       ovn_init_ic_db
                      28d94b
                      -n_az=5
                      28d94b
                      -n_ts=5
                      28d94b
                      +# The number needs to stay relatively low due to high memory consumption
                      28d94b
                      +# with address sanitizers enabled.
                      28d94b
                      +n_az=3
                      28d94b
                      +n_ts=3
                      28d94b
                       for i in `seq 1 $n_az`; do
                      28d94b
                           ovn_start az$i
                      28d94b
                       done
                      28d94b
                      @@ -28416,24 +28423,39 @@ wait_row_count Port_Binding 1 logical_port=lsp-cont1 chassis=$ch
                      28d94b
                       OVN_CLEANUP([hv1])
                      28d94b
                       AT_CLEANUP
                      28d94b
                       
                      28d94b
                      +# TEST_LR_DROP_TRAFFIC_FOR_OWN_IPS [ DGP | GR ]
                      28d94b
                       # Test dropping traffic destined to router owned IPs.
                      28d94b
                      -OVN_FOR_EACH_NORTHD([
                      28d94b
                      -AT_SETUP([gateway router drop traffic for own IPs])
                      28d94b
                      +m4_define([TEST_LR_DROP_TRAFFIC_FOR_OWN_IPS], [
                      28d94b
                       ovn_start
                      28d94b
                       
                      28d94b
                      -ovn-nbctl lr-add r1 -- set logical_router r1 options:chassis=hv1
                      28d94b
                      -ovn-nbctl ls-add s1
                      28d94b
                      -
                      28d94b
                      -# Connnect r1 to s1.
                      28d94b
                      -ovn-nbctl lrp-add r1 lrp-r1-s1 00:00:00:00:01:01 10.0.1.1/24
                      28d94b
                      -ovn-nbctl lsp-add s1 lsp-s1-r1 -- set Logical_Switch_Port lsp-s1-r1 type=router \
                      28d94b
                      -    options:router-port=lrp-r1-s1 addresses=router
                      28d94b
                      -
                      28d94b
                      -# Create logical port p1 in s1
                      28d94b
                      -ovn-nbctl lsp-add s1 p1 \
                      28d94b
                      +ovn-nbctl lr-add r1 # Gateway router or LR with DGP on the ext side
                      28d94b
                      +ovn-nbctl ls-add ext # simulate external LS
                      28d94b
                      +ovn-nbctl ls-add s2 # simulate internal LS
                      28d94b
                      +
                      28d94b
                      +# Connnect r1 to ext.
                      28d94b
                      +ovn-nbctl lrp-add r1 lrp-r1-ext 00:00:00:00:01:01 10.0.1.1/24
                      28d94b
                      +if test X"$1" = X"DGP"; then
                      28d94b
                      +    ovn-nbctl lrp-set-gateway-chassis lrp-r1-ext hv1 1
                      28d94b
                      +else
                      28d94b
                      +    ovn-nbctl set logical_router r1 options:chassis=hv1
                      28d94b
                      +fi
                      28d94b
                      +ovn-nbctl lsp-add ext lsp-ext-r1 -- set Logical_Switch_Port lsp-ext-r1 type=router \
                      28d94b
                      +    options:router-port=lrp-r1-ext addresses=router
                      28d94b
                      +
                      28d94b
                      +# Connnect r1 to s2.
                      28d94b
                      +ovn-nbctl lrp-add r1 lrp-r1-s2 00:00:00:00:02:01 10.0.2.1/24
                      28d94b
                      +ovn-nbctl lsp-add s2 lsp-s2-r1 -- set Logical_Switch_Port lsp-s2-r1 type=router \
                      28d94b
                      +    options:router-port=lrp-r1-s2 addresses=router
                      28d94b
                      +
                      28d94b
                      +# Create logical port p1 in ext
                      28d94b
                      +ovn-nbctl lsp-add ext p1 \
                      28d94b
                       -- lsp-set-addresses p1 "f0:00:00:00:01:02 10.0.1.2" \
                      28d94b
                       -- lsp-set-port-security p1 "f0:00:00:00:01:02 10.0.1.2"
                      28d94b
                       
                      28d94b
                      +# Create logical port p2 in s2
                      28d94b
                      +ovn-nbctl lsp-add s2 p2 \
                      28d94b
                      +-- lsp-set-addresses p2 "f0:00:00:00:02:02 10.0.2.2"
                      28d94b
                      +
                      28d94b
                       # Create two hypervisor and create OVS ports corresponding to logical ports.
                      28d94b
                       net_add n1
                      28d94b
                       
                      28d94b
                      @@ -28447,6 +28469,12 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
                      28d94b
                           options:rxq_pcap=hv1/vif1-rx.pcap \
                      28d94b
                           ofport-request=1
                      28d94b
                       
                      28d94b
                      +ovs-vsctl -- add-port br-int hv1-vif2 -- \
                      28d94b
                      +    set interface hv1-vif2 external-ids:iface-id=p2 \
                      28d94b
                      +    options:tx_pcap=hv1/vif2-tx.pcap \
                      28d94b
                      +    options:rxq_pcap=hv1/vif2-rx.pcap \
                      28d94b
                      +    ofport-request=2
                      28d94b
                      +
                      28d94b
                       # Pre-populate the hypervisors' ARP tables so that we don't lose any
                      28d94b
                       # packets for ARP resolution (native tunneling doesn't queue packets
                      28d94b
                       # for ARP resolution).
                      28d94b
                      @@ -28457,9 +28485,10 @@ ovn-nbctl --wait=hv sync
                      28d94b
                       
                      28d94b
                       sw_key=$(ovn-sbctl --bare --columns tunnel_key list datapath_binding r1)
                      28d94b
                       
                      28d94b
                      +echo sw_key: $sw_key
                      28d94b
                       AT_CHECK([ovn-sbctl lflow-list | grep lr_in_arp_resolve | grep 10.0.1.1], [1], [])
                      28d94b
                       
                      28d94b
                      -# Send ip packets from p1 to lrp-r1-s1
                      28d94b
                      +# Send ip packets from p1 to lrp-r1-ext
                      28d94b
                       src_mac="f00000000102"
                      28d94b
                       dst_mac="000000000101"
                      28d94b
                       src_ip=`ip_to_hex 10 0 1 2`
                      28d94b
                      @@ -28478,10 +28507,10 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=11, n_packets=1,.*
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       # Use the router IP as SNAT IP.
                      28d94b
                      -ovn-nbctl set logical_router r1 options:lb_force_snat_ip=10.0.1.1
                      28d94b
                      +ovn-nbctl lr-nat-add r1 snat 10.0.1.1 10.8.8.0/24
                      28d94b
                       ovn-nbctl --wait=hv sync
                      28d94b
                       
                      28d94b
                      -# Send ip packets from p1 to lrp-r1-s1
                      28d94b
                      +# Send ip packets from p1 to lrp-r1-ext
                      28d94b
                       src_mac="f00000000102"
                      28d94b
                       dst_mac="000000000101"
                      28d94b
                       src_ip=`ip_to_hex 10 0 1 2`
                      28d94b
                      @@ -28496,11 +28525,53 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep "actions=controller" | grep
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       # The packet should've been dropped in the lr_in_arp_resolve stage.
                      28d94b
                      -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=25, n_packets=1,.* priority=2,ip,metadata=0x${sw_key},nw_dst=10.0.1.1 actions=drop" -c], [0], [dnl
                      28d94b
                      +if test X"$1" = X"DGP"; then
                      28d94b
                      +    prio=150
                      28d94b
                      +    inport=reg14
                      28d94b
                      +    outport=reg15
                      28d94b
                      +else
                      28d94b
                      +    prio=2
                      28d94b
                      +fi
                      28d94b
                      +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=25, n_packets=1,.* priority=$prio,ip,$inport.*$outport.*metadata=0x${sw_key},nw_dst=10.0.1.1 actions=drop" -c], [0], [dnl
                      28d94b
                       1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                      +# Send ip packets from p2 to lrp-r1-ext
                      28d94b
                      +src_mac="f00000000202"
                      28d94b
                      +dst_mac="000000000201"
                      28d94b
                      +src_ip=`ip_to_hex 10 0 2 2`
                      28d94b
                      +dst_ip=`ip_to_hex 10 0 1 1`
                      28d94b
                      +packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
                      28d94b
                      +as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
                      28d94b
                      +
                      28d94b
                      +# Still no packet-ins should reach ovn-controller.
                      28d94b
                      +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep "actions=controller" | grep -v n_packets=0 -c], [1], [dnl
                      28d94b
                      +0
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +if test X"$1" = X"DGP"; then
                      28d94b
                      +    # The packet dst should be resolved once for E/W centralized NAT purpose.
                      28d94b
                      +    AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=25, n_packets=1,.* priority=100,reg0=0xa000101,reg15=.*metadata=0x${sw_key} actions=mod_dl_dst:00:00:00:00:01:01,resubmit" -c], [0], [dnl
                      28d94b
                      +1
                      28d94b
                      +])
                      28d94b
                      +fi
                      28d94b
                      +
                      28d94b
                      +# The packet should've been finally dropped in the lr_in_arp_resolve stage.
                      28d94b
                      +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep -E "table=25, n_packets=2,.* priority=$prio,ip,$inport.*$outport.*metadata=0x${sw_key},nw_dst=10.0.1.1 actions=drop" -c], [0], [dnl
                      28d94b
                      +1
                      28d94b
                      +])
                      28d94b
                       OVN_CLEANUP([hv1])
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +OVN_FOR_EACH_NORTHD([
                      28d94b
                      +AT_SETUP([gateway router drop traffic for own IPs])
                      28d94b
                      +TEST_LR_DROP_TRAFFIC_FOR_OWN_IPS(GR)
                      28d94b
                      +AT_CLEANUP
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +OVN_FOR_EACH_NORTHD([
                      28d94b
                      +AT_SETUP([distributed gateway port drop traffic for own IPs])
                      28d94b
                      +TEST_LR_DROP_TRAFFIC_FOR_OWN_IPS(DGP)
                      28d94b
                       AT_CLEANUP
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                      diff --git a/tests/system-ovn.at b/tests/system-ovn.at
                      28d94b
                      index 99ad14aa5..1e6767846 100644
                      28d94b
                      --- a/tests/system-ovn.at
                      28d94b
                      +++ b/tests/system-ovn.at
                      28d94b
                      @@ -1618,8 +1618,8 @@ OVS_WAIT_UNTIL([
                      28d94b
                       ovn-nbctl --reject lb-add lb3 30.0.0.10:80 ""
                      28d94b
                       ovn-nbctl ls-lb-add foo lb3
                      28d94b
                       # Filter reset segments
                      28d94b
                      -NS_CHECK_EXEC([foo1], [tcpdump -c 1 -neei foo1 ip[[33:1]]=0x14 > rst.pcap 2>/dev/null &])
                      28d94b
                      -sleep 1
                      28d94b
                      +NS_CHECK_EXEC([foo1], [tcpdump -l -c 1 -neei foo1 ip[[33:1]]=0x14 > rst.pcap 2>tcpdump_err &])
                      28d94b
                      +OVS_WAIT_UNTIL([grep "listening" tcpdump_err])
                      28d94b
                       NS_CHECK_EXEC([foo1], [wget -q 30.0.0.10],[4])
                      28d94b
                       
                      28d94b
                       OVS_WAIT_UNTIL([
                      28d94b
                      @@ -1734,13 +1734,11 @@ OVS_START_L7([bar2], [http6])
                      28d94b
                       OVS_START_L7([bar3], [http6])
                      28d94b
                       
                      28d94b
                       dnl Should work with the virtual IP fd03::1 address through NAT
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([foo1], [wget http://[[fd03::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log || (ovs-ofctl -O OpenFlow13 dump-flows br-int && false)])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([foo1], [wget http://[[fd03::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log || (ovs-ofctl -O OpenFlow13 dump-flows br-int && false)])
                      28d94b
                       done
                      28d94b
                      -
                      28d94b
                      -dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::1) | grep -v fe80 | \
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::1) | grep -v fe80 | \
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::1,sport=<cleared>,dport=<cleared>),reply=(src=fd02::2,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::1,sport=<cleared>,dport=<cleared>),reply=(src=fd02::3,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                      @@ -1748,27 +1746,25 @@ tcp,orig=(src=fd01::2,dst=fd03::1,sport=<cleared>,dport=<cleared>),reply=(src=fd
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       dnl Should work with the virtual IP fd03::3 address through NAT
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([foo1], [wget http://[[fd03::3]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([foo1], [wget http://[[fd03::3]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                      -
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::3) | grep -v fe80 | \
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::3) | grep -v fe80 | \
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::3,sport=<cleared>,dport=<cleared>),reply=(src=fd02::2,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::3,sport=<cleared>,dport=<cleared>),reply=(src=fd02::3,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::3,sport=<cleared>,dport=<cleared>),reply=(src=fd02::4,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT([
                      28d94b
                       dnl Test load-balancing that includes L4 ports in NAT.
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([foo1], [wget http://[[fd03::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([foo1], [wget http://[[fd03::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                      -
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::2) | grep -v fe80 | \
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::2) | grep -v fe80 | \
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd02::2,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd02::3,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                      @@ -1784,14 +1780,14 @@ OVS_WAIT_UNTIL([
                      28d94b
                       
                      28d94b
                       AT_CHECK([ovs-appctl dpctl/flush-conntrack])
                      28d94b
                       
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT([
                      28d94b
                       dnl Test load-balancing that includes L4 ports in NAT.
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([foo1], [wget http://[[fd03::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([foo1], [wget http://[[fd03::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::2) | grep -v fe80 | \
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::2) | grep -v fe80 | \
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd02::2,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd02::3,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                      @@ -1933,13 +1929,13 @@ OVS_START_L7([foo3], [http])
                      28d94b
                       OVS_START_L7([foo4], [http])
                      28d94b
                       
                      28d94b
                       dnl Should work with the virtual IP address through NAT
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                      @@ -1947,20 +1943,19 @@ tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(s
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       dnl Test load-balancing that includes L4 ports in NAT.
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([foo1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                      -
                      28d94b
                       OVS_APP_EXIT_AND_WAIT([ovn-controller])
                      28d94b
                       
                      28d94b
                       as ovn-sb
                      28d94b
                      @@ -2044,13 +2039,13 @@ OVS_START_L7([foo3], [http6])
                      28d94b
                       OVS_START_L7([foo4], [http6])
                      28d94b
                       
                      28d94b
                       dnl Should work with the virtual IP address through NAT
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([foo1], [wget http://[[fd03::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([foo1], [wget http://[[fd03::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::1) | grep -v fe80 | \
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::1) | grep -v fe80 | \
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::1,sport=<cleared>,dport=<cleared>),reply=(src=fd01::3,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::1,sport=<cleared>,dport=<cleared>),reply=(src=fd01::4,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                      @@ -2058,20 +2053,19 @@ tcp,orig=(src=fd01::2,dst=fd03::1,sport=<cleared>,dport=<cleared>),reply=(src=fd
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       dnl Test load-balancing that includes L4 ports in NAT.
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([foo1], [wget http://[[fd03::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([foo1], [wget http://[[fd03::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::2) | grep -v fe80 | \
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd03::2) | grep -v fe80 | \
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd01::3,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd01::4,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=fd01::2,dst=fd03::2,sport=<cleared>,dport=<cleared>),reply=(src=fd01::5,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                      -
                      28d94b
                       OVS_APP_EXIT_AND_WAIT([ovn-controller])
                      28d94b
                       
                      28d94b
                       as ovn-sb
                      28d94b
                      @@ -2199,27 +2193,27 @@ OVS_START_L7([bar1], [http])
                      28d94b
                       
                      28d94b
                       check ovs-appctl dpctl/flush-conntrack
                      28d94b
                       dnl Should work with the virtual IP address through NAT
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       check ovs-appctl dpctl/flush-conntrack
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT([
                      28d94b
                       dnl Test load-balancing that includes L4 ports in NAT.
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) |
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) |
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                      @@ -2256,23 +2250,23 @@ OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-flows br-int table=43 | \
                      28d94b
                       grep 'nat(src=20.0.0.2)'])
                      28d94b
                       
                      28d94b
                       check ovs-appctl dpctl/flush-conntrack
                      28d94b
                      +exp_ct1="tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      +tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)"
                      28d94b
                      +exp_ct2="tcp,orig=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      +tcp,orig=(src=172.16.1.2,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)"
                      28d94b
                      +
                      28d94b
                       dnl Test load-balancing that includes L4 ports in NAT.
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT_UNQUOTED([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) |
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      -])
                      28d94b
                      +ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
                      28d94b
                      +ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
                      28d94b
                       
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) |
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      -tcp,orig=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      -tcp,orig=(src=172.16.1.2,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      +test "x$ct1 = x$exp_ct1" && test "x$ct2 = x$exp_ct2"
                      28d94b
                      +], [0], [dnl
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       OVS_WAIT_UNTIL([check_est_flows], [check established flows])
                      28d94b
                      @@ -2298,22 +2292,21 @@ rm -f wget*.log
                      28d94b
                       
                      28d94b
                       check ovs-appctl dpctl/flush-conntrack
                      28d94b
                       dnl Test load-balancing that includes L4 ports in NAT.
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +exp_ct1="tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      +tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)"
                      28d94b
                      +exp_ct2="tcp,orig=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      +tcp,orig=(src=172.16.1.2,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)"
                      28d94b
                      +
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT_UNQUOTED([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) |
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      -])
                      28d94b
                      -
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) |
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      -tcp,orig=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      -tcp,orig=(src=172.16.1.2,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      +ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
                      28d94b
                      +ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
                      28d94b
                      +test "x$ct1 = x$exp_ct1" && test "x$ct2 = x$exp_ct2"
                      28d94b
                      +], [0], [dnl
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       OVS_WAIT_UNTIL([check_est_flows], [check established flows])
                      28d94b
                      @@ -2549,26 +2542,26 @@ OVS_START_L7([foo1], [http6])
                      28d94b
                       OVS_START_L7([bar1], [http6])
                      28d94b
                       
                      28d94b
                       dnl Should work with the virtual IP address through NAT
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget http://[[fd30::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT_UNQUOTED([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget http://[[fd30::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 |
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 |
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=fd72::2,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=fd72::2,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       dnl Test load-balancing that includes L4 ports in NAT.
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget http://[[fd30::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT_UNQUOTED([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget http://[[fd30::2]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::2) | grep -v fe80 |
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::2) | grep -v fe80 |
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=fd72::2,dst=fd30::2,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=fd72::2,dst=fd30::2,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                      @@ -2727,24 +2720,24 @@ OVS_START_L7([foo1], [http])
                      28d94b
                       OVS_START_L7([bar1], [http])
                      28d94b
                       
                      28d94b
                       dnl Should work with the virtual IP address through NAT
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +exp_ct1="tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      +tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)"
                      28d94b
                      +exp_ct2="tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      +tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)"
                      28d94b
                      +
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT_UNQUOTED([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      -])
                      28d94b
                      -
                      28d94b
                      +ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
                      28d94b
                       dnl Force SNAT should have worked.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) |
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      -tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      -tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      +ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
                      28d94b
                      +test "x$ct1 = x$exp_ct1" && test "x$ct2 = x$exp_ct2"
                      28d94b
                      +], [0], [dnl
                      28d94b
                       ])
                      28d94b
                      +
                      28d94b
                       OVS_APP_EXIT_AND_WAIT([ovn-controller])
                      28d94b
                       
                      28d94b
                       as ovn-sb
                      28d94b
                      @@ -2900,24 +2893,24 @@ OVS_START_L7([foo1], [http6])
                      28d94b
                       OVS_START_L7([bar1], [http6])
                      28d94b
                       
                      28d94b
                       dnl Should work with the virtual IP address through NAT
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget http://[[fd30::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +exp_ct1="tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      +tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      +exp_ct2=tcp,orig=(src=fd72::3,dst=fd11::2,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      +tcp,orig=(src=fd72::3,dst=fd12::2,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)"
                      28d94b
                      +
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT_UNQUOTED([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget http://[[fd30::1]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 |
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      -tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      -tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      -])
                      28d94b
                      -
                      28d94b
                      +ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
                      28d94b
                       dnl Force SNAT should have worked.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::2) | grep -v fe80 |
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      -tcp,orig=(src=fd72::3,dst=fd11::2,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      -tcp,orig=(src=fd72::3,dst=fd12::2,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      +ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::2) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
                      28d94b
                      +test "x$ct1 = x$exp_ct1" && test "x$ct2 = x$exp_ct2"
                      28d94b
                      +], [0], [dnl
                      28d94b
                       ])
                      28d94b
                      +
                      28d94b
                       OVS_APP_EXIT_AND_WAIT([ovn-controller])
                      28d94b
                       
                      28d94b
                       as ovn-sb
                      28d94b
                      @@ -3111,39 +3104,32 @@ OVS_START_L7([foo16], [http6])
                      28d94b
                       OVS_START_L7([bar16], [http6])
                      28d94b
                       
                      28d94b
                       dnl Should work with the virtual IP address through NAT
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      -done
                      28d94b
                      -
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request ${i}_6
                      28d94b
                      -    NS_CHECK_EXEC([alice16], [wget http://[[fd30::1]] -t 5 -T 1 --retry-connrefused -v -o wget${i}_6.log])
                      28d94b
                      +exp_ct1="tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      +tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)"
                      28d94b
                      +exp_ct2="tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      +tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)"
                      28d94b
                      +exp_ct3="tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      +tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)"
                      28d94b
                      +exp_ct4="tcp,orig=(src=fd72::3,dst=fd11::2,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      +tcp,orig=(src=fd72::3,dst=fd12::2,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)"
                      28d94b
                      +
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT_UNQUOTED([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +    NS_EXEC([alice16], [wget http://[[fd30::1]] -t 5 -T 1 --retry-connrefused -v -o wget${i}_6.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      -])
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 |
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      -tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      -tcp,orig=(src=fd72::3,dst=fd30::1,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd72::3,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=10,protoinfo=(state=<cleared>)
                      28d94b
                      -])
                      28d94b
                      +ct1=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
                      28d94b
                      +ct2=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd30::1) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
                      28d94b
                       
                      28d94b
                       dnl Force SNAT should have worked.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) |
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      -tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      -tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      -])
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::2) | grep -v fe80 |
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      -tcp,orig=(src=fd72::3,dst=fd11::2,sport=<cleared>,dport=<cleared>),reply=(src=fd11::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      -tcp,orig=(src=fd72::3,dst=fd12::2,sport=<cleared>,dport=<cleared>),reply=(src=fd12::2,dst=fd20::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
                      28d94b
                      +ct3=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
                      28d94b
                      +ct4=$(ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd20::2) | grep -v fe80 | sed -e 's/zone=[[0-9]]*/zone=<cleared>/')
                      28d94b
                      +test "x$ct1 = x$exp_ct1" && test "x$ct2 = x$exp_ct2" && test "x$ct3 = x$exp_ct3" && test "x$ct4 = x$exp_ct4"
                      28d94b
                      +], [0], [dnl
                      28d94b
                       ])
                      28d94b
                      +
                      28d94b
                       OVS_APP_EXIT_AND_WAIT([ovn-controller])
                      28d94b
                       
                      28d94b
                       as ovn-sb
                      28d94b
                      @@ -3262,26 +3248,26 @@ OVS_START_L7([foo1], [http])
                      28d94b
                       OVS_START_L7([bar1], [http])
                      28d94b
                       
                      28d94b
                       dnl Should work with the virtual IP address through NAT
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget 172.16.1.10 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT_UNQUOTED([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget 172.16.1.10 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.10) |
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.10) |
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       dnl Test load-balancing that includes L4 ports in NAT.
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget 172.16.1.11:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT_UNQUOTED([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget 172.16.1.11:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.11) |
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.11) |
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                      @@ -3405,26 +3391,26 @@ OVS_START_L7([foo1], [http6])
                      28d94b
                       OVS_START_L7([bar1], [http6])
                      28d94b
                       
                      28d94b
                       dnl Should work with the virtual IP address through NAT
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget http://[[fd72::10]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT_UNQUOTED([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget http://[[fd72::10]] -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd72::10) | grep -v fe80 |
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd72::10) | grep -v fe80 |
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=fd72::2,dst=fd72::10,sport=<cleared>,dport=<cleared>),reply=(src=fd01::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=fd72::2,dst=fd72::10,sport=<cleared>,dport=<cleared>),reply=(src=fd02::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       dnl Test load-balancing that includes L4 ports in NAT.
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    NS_CHECK_EXEC([alice1], [wget http://[[fd72::11]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT_UNQUOTED([
                      28d94b
                      +for i in `seq 1 10`; do
                      28d94b
                      +    NS_EXEC([alice1], [wget http://[[fd72::11]]:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                       done
                      28d94b
                       
                      28d94b
                       dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd72::11) | grep -v fe80 |
                      28d94b
                      +ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd72::11) | grep -v fe80 |
                      28d94b
                       sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=fd72::2,dst=fd72::11,sport=<cleared>,dport=<cleared>),reply=(src=fd01::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=fd72::2,dst=fd72::11,sport=<cleared>,dport=<cleared>),reply=(src=fd02::2,dst=fd72::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                      @@ -3598,8 +3584,8 @@ icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       # Try to ping external network
                      28d94b
                      -NS_CHECK_EXEC([ext-net], [tcpdump -n -c 3 -i ext-veth dst 172.16.1.3 and icmp > ext-net.pcap &])
                      28d94b
                      -sleep 1
                      28d94b
                      +NS_CHECK_EXEC([ext-net], [tcpdump -l -n -c 3 -i ext-veth dst 172.16.1.3 and icmp > ext-net.pcap 2>tcpdump_err &])
                      28d94b
                      +OVS_WAIT_UNTIL([grep "listening" tcpdump_err])
                      28d94b
                       AT_CHECK([ovn-nbctl lr-nat-del R1 snat])
                      28d94b
                       NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.1 | FORMAT_PING], \
                      28d94b
                       [0], [dnl
                      28d94b
                      @@ -4507,17 +4493,15 @@ OVS_WAIT_UNTIL(
                      28d94b
                           [ovn-sbctl dump-flows sw0 | grep ct_lb_mark | grep priority=120 | grep "ip4.dst == 10.0.0.10" > lflows.txt
                      28d94b
                            test 1 = `cat lflows.txt | grep "ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80)" | wc -l`]
                      28d94b
                       )
                      28d94b
                      -
                      28d94b
                       # From sw0-p2 send traffic to vip - 10.0.0.10
                      28d94b
                      -for i in `seq 1 20`; do
                      28d94b
                      -    echo Request $i
                      28d94b
                      -    ovn-sbctl list service_monitor
                      28d94b
                      -    NS_CHECK_EXEC([sw0-p2], [wget 10.0.0.10 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      -done
                      28d94b
                      +#dnl Each server should have at least one connection.
                      28d94b
                      +OVS_WAIT_FOR_OUTPUT([
                      28d94b
                      +    for i in `seq 1 10`; do
                      28d94b
                      +        NS_EXEC([sw0-p2], [wget 10.0.0.10 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
                      28d94b
                      +    done
                      28d94b
                       
                      28d94b
                      -dnl Each server should have at least one connection.
                      28d94b
                      -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.0.0.10) | \
                      28d94b
                      -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                      +    ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.0.0.10) | \
                      28d94b
                      +      sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
                      28d94b
                       tcp,orig=(src=10.0.0.4,dst=10.0.0.10,sport=<cleared>,dport=<cleared>),reply=(src=10.0.0.3,dst=10.0.0.4,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       tcp,orig=(src=10.0.0.4,dst=10.0.0.10,sport=<cleared>,dport=<cleared>),reply=(src=20.0.0.3,dst=10.0.0.4,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
                      28d94b
                       ])
                      28d94b
                      @@ -4649,10 +4633,12 @@ ovn-nbctl lb-add lb-ipv4-tcp     88.88.88.88:8080 42.42.42.1:4041 tcp
                      28d94b
                       ovn-nbctl lb-add lb-ipv4-tcp-dup 88.88.88.89:8080 42.42.42.1:4041 tcp
                      28d94b
                       ovn-nbctl lb-add lb-ipv4-udp     88.88.88.88:4040 42.42.42.1:2021 udp
                      28d94b
                       ovn-nbctl lb-add lb-ipv4-udp-dup 88.88.88.89:4040 42.42.42.1:2021 udp
                      28d94b
                      +ovn-nbctl lb-add lb-ipv4 88.88.88.90 42.42.42.1
                      28d94b
                       ovn-nbctl ls-lb-add sw lb-ipv4-tcp
                      28d94b
                       ovn-nbctl ls-lb-add sw lb-ipv4-tcp-dup
                      28d94b
                       ovn-nbctl ls-lb-add sw lb-ipv4-udp
                      28d94b
                       ovn-nbctl ls-lb-add sw lb-ipv4-udp-dup
                      28d94b
                      +ovn-nbctl ls-lb-add sw lb-ipv4
                      28d94b
                       
                      28d94b
                       ovn-nbctl lr-add rtr
                      28d94b
                       ovn-nbctl lrp-add rtr rtr-sw 00:00:00:00:01:00 42.42.42.254/24
                      28d94b
                      @@ -4668,28 +4654,39 @@ ADD_VETH(lsp, lsp, br-int, "42.42.42.1/24", "00:00:00:00:00:01", \
                      28d94b
                       ovn-nbctl --wait=hv -t 3 sync
                      28d94b
                       
                      28d94b
                       # Start IPv4 TCP server on lsp.
                      28d94b
                      -NS_CHECK_EXEC([lsp], [timeout 2s nc -k -l 42.42.42.1 4041 &], [0])
                      28d94b
                      +NETNS_DAEMONIZE([lsp], [nc -l -k 42.42.42.1 4041], [lsp0.pid])
                      28d94b
                       
                      28d94b
                       # Check that IPv4 TCP hairpin connection succeeds on both VIPs.
                      28d94b
                       NS_CHECK_EXEC([lsp], [nc 88.88.88.88 8080 -z], [0], [ignore], [ignore])
                      28d94b
                       NS_CHECK_EXEC([lsp], [nc 88.88.88.89 8080 -z], [0], [ignore], [ignore])
                      28d94b
                      +NS_CHECK_EXEC([lsp], [nc 88.88.88.90 4041 -z], [0], [ignore], [ignore])
                      28d94b
                       
                      28d94b
                       # Capture IPv4 UDP hairpinned packets.
                      28d94b
                       filter="dst 42.42.42.1 and dst port 2021 and udp"
                      28d94b
                      -NS_CHECK_EXEC([lsp], [tcpdump -nn -c 2 -i lsp ${filter} > lsp.pcap &])
                      28d94b
                      -
                      28d94b
                      -sleep 1
                      28d94b
                      +NS_CHECK_EXEC([lsp], [tcpdump -l -nn -c 3 -i lsp ${filter} > lsp.pcap 2>tcpdump_err &])
                      28d94b
                      +OVS_WAIT_UNTIL([grep "listening" tcpdump_err])
                      28d94b
                       
                      28d94b
                       # Generate IPv4 UDP hairpin traffic.
                      28d94b
                       NS_CHECK_EXEC([lsp], [echo a | nc -u 88.88.88.88 4040 &], [0])
                      28d94b
                       NS_CHECK_EXEC([lsp], [echo a | nc -u 88.88.88.89 4040 &], [0])
                      28d94b
                      +NS_CHECK_EXEC([lsp], [echo a | nc -u 88.88.88.90 2021 &], [0])
                      28d94b
                       
                      28d94b
                       # Check hairpin traffic.
                      28d94b
                       OVS_WAIT_UNTIL([
                      28d94b
                           total_pkts=$(cat lsp.pcap | wc -l)
                      28d94b
                      -    test "${total_pkts}" = "2"
                      28d94b
                      +    test "${total_pkts}" = "3"
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                      +ovn-nbctl pg-add pg0 lsp
                      28d94b
                      +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1004 "ip4 && ip4.dst == 10.0.0.2" drop
                      28d94b
                      +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip4 && tcp" allow-related
                      28d94b
                      +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip4 && udp" allow
                      28d94b
                      +ovn-nbctl --wait=hv sync
                      28d94b
                      +
                      28d94b
                      +## Check that IPv4 TCP hairpin connection succeeds on both VIPs.
                      28d94b
                      +NS_CHECK_EXEC([lsp], [nc 88.88.88.88 8080 -z], [0], [ignore], [ignore])
                      28d94b
                      +NS_CHECK_EXEC([lsp], [nc 88.88.88.89 8080 -z], [0], [ignore], [ignore])
                      28d94b
                      +
                      28d94b
                       OVS_APP_EXIT_AND_WAIT([ovn-controller])
                      28d94b
                       
                      28d94b
                       as ovn-sb
                      28d94b
                      @@ -4736,10 +4733,12 @@ ovn-nbctl lb-add lb-ipv6-tcp     [[8800::0088]]:8080 [[4200::1]]:4041 tcp
                      28d94b
                       ovn-nbctl lb-add lb-ipv6-tcp-dup [[8800::0089]]:8080 [[4200::1]]:4041 tcp
                      28d94b
                       ovn-nbctl lb-add lb-ipv6-udp     [[8800::0088]]:4040 [[4200::1]]:2021 udp
                      28d94b
                       ovn-nbctl lb-add lb-ipv6-udp-dup [[8800::0089]]:4040 [[4200::1]]:2021 udp
                      28d94b
                      +ovn-nbctl lb-add lb-ipv6 8800::0090 4200::1
                      28d94b
                       ovn-nbctl ls-lb-add sw lb-ipv6-tcp
                      28d94b
                       ovn-nbctl ls-lb-add sw lb-ipv6-tcp-dup
                      28d94b
                       ovn-nbctl ls-lb-add sw lb-ipv6-udp
                      28d94b
                       ovn-nbctl ls-lb-add sw lb-ipv6-udp-dup
                      28d94b
                      +ovn-nbctl ls-lb-add sw lb-ipv6
                      28d94b
                       
                      28d94b
                       ovn-nbctl lr-add rtr
                      28d94b
                       ovn-nbctl lrp-add rtr rtr-sw 00:00:00:00:01:00 4200::00ff/64
                      28d94b
                      @@ -4754,28 +4753,39 @@ OVS_WAIT_UNTIL([test "$(ip netns exec lsp ip a | grep 4200::1 | grep tentative)"
                      28d94b
                       ovn-nbctl --wait=hv -t 3 sync
                      28d94b
                       
                      28d94b
                       # Start IPv6 TCP server on lsp.
                      28d94b
                      -NS_CHECK_EXEC([lsp], [timeout 2s nc -k -l 4200::1 4041 &], [0])
                      28d94b
                      +NETNS_DAEMONIZE([lsp], [nc -l -k 4200::1 4041], [lsp0.pid])
                      28d94b
                       
                      28d94b
                       # Check that IPv6 TCP hairpin connection succeeds on both VIPs.
                      28d94b
                       NS_CHECK_EXEC([lsp], [nc 8800::0088 8080 -z], [0], [ignore], [ignore])
                      28d94b
                       NS_CHECK_EXEC([lsp], [nc 8800::0089 8080 -z], [0], [ignore], [ignore])
                      28d94b
                      +NS_CHECK_EXEC([lsp], [nc 8800::0090 4041 -z], [0], [ignore], [ignore])
                      28d94b
                       
                      28d94b
                       # Capture IPv6 UDP hairpinned packets.
                      28d94b
                       filter="dst 4200::1 and dst port 2021 and udp"
                      28d94b
                      -NS_CHECK_EXEC([lsp], [tcpdump -nn -c 2 -i lsp $filter > lsp.pcap &])
                      28d94b
                      -
                      28d94b
                      -sleep 1
                      28d94b
                      +NS_CHECK_EXEC([lsp], [tcpdump -l -nn -c 3 -i lsp $filter > lsp.pcap 2>tcpdump_err &])
                      28d94b
                      +OVS_WAIT_UNTIL([grep "listening" tcpdump_err])
                      28d94b
                       
                      28d94b
                       # Generate IPv6 UDP hairpin traffic.
                      28d94b
                       NS_CHECK_EXEC([lsp], [echo a | nc -u 8800::0088 4040 &], [0])
                      28d94b
                       NS_CHECK_EXEC([lsp], [echo a | nc -u 8800::0089 4040 &], [0])
                      28d94b
                      +NS_CHECK_EXEC([lsp], [echo a | nc -u 8800::0090 2021 &], [0])
                      28d94b
                       
                      28d94b
                       # Check hairpin traffic.
                      28d94b
                       OVS_WAIT_UNTIL([
                      28d94b
                           total_pkts=$(cat lsp.pcap | wc -l)
                      28d94b
                      -    test "${total_pkts}" = "2"
                      28d94b
                      +    test "${total_pkts}" = "3"
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                      +ovn-nbctl pg-add pg0 lsp
                      28d94b
                      +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip6 && tcp" allow-related
                      28d94b
                      +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip6 && udp" allow
                      28d94b
                      +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1000 "ip6" drop
                      28d94b
                      +ovn-nbctl --wait=hv sync
                      28d94b
                      +
                      28d94b
                      +# Check that IPv6 TCP hairpin connection succeeds on both VIPs.
                      28d94b
                      +NS_CHECK_EXEC([lsp], [nc 8800::0088 8080 -z], [0], [ignore], [ignore])
                      28d94b
                      +NS_CHECK_EXEC([lsp], [nc 8800::0089 8080 -z], [0], [ignore], [ignore])
                      28d94b
                      +
                      28d94b
                       OVS_APP_EXIT_AND_WAIT([ovn-controller])
                      28d94b
                       
                      28d94b
                       as ovn-sb
                      28d94b
                      @@ -4938,7 +4948,7 @@ OVS_WAIT_UNTIL([
                      28d94b
                           ip netns exec sw0-p1-rej nc -u 10.0.0.4 90 < foo
                      28d94b
                           c=$(cat sw0-p1-rej-icmp.pcap | grep \
                      28d94b
                       "10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 90 unreachable" | uniq | wc -l)
                      28d94b
                      -    test $c -eq 1
                      28d94b
                      +    test $c -ge 1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       rm -f *.pcap
                      28d94b
                      @@ -4950,7 +4960,7 @@ OVS_WAIT_UNTIL([
                      28d94b
                           ip netns exec sw0-p1-rej nc -u 10.0.0.4 94 < foo
                      28d94b
                           c=$(cat sw0-p1-rej-icmp.pcap | grep \
                      28d94b
                       "10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 94 unreachable" | uniq | wc -l)
                      28d94b
                      -    test $c -eq 1
                      28d94b
                      +    test $c -ge 1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       # Now test for IPv6 UDP.
                      28d94b
                      @@ -4962,7 +4972,7 @@ OVS_WAIT_UNTIL([
                      28d94b
                           c=$(cat sw0-p2-rej-icmp6.pcap | grep \
                      28d94b
                       "IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \
                      28d94b
                       aef0::3 udp port 90" | uniq | wc -l)
                      28d94b
                      -    test $c -eq 1
                      28d94b
                      +    test $c -ge 1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       rm -f *.pcap
                      28d94b
                      @@ -4975,7 +4985,7 @@ OVS_WAIT_UNTIL([
                      28d94b
                           c=$(cat sw0-p2-rej-icmp6.pcap | grep \
                      28d94b
                       "IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \
                      28d94b
                       aef0::3 udp port 94" | uniq | wc -l)
                      28d94b
                      -    test $c -eq 1
                      28d94b
                      +    test $c -ge 1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       # Delete all the ACLs of pg0 and add the ACL with a generic match with reject action.
                      28d94b
                      @@ -5000,7 +5010,7 @@ OVS_WAIT_UNTIL([
                      28d94b
                           ip netns exec sw0-p1-rej nc -u 10.0.0.4 90 < foo
                      28d94b
                           c=$(cat sw0-p1-rej-icmp.pcap | grep \
                      28d94b
                       "10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 90 unreachable" | uniq | wc -l)
                      28d94b
                      -    test $c -eq 1
                      28d94b
                      +    test $c -ge 1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       rm -f *.pcap
                      28d94b
                      @@ -5012,7 +5022,7 @@ OVS_WAIT_UNTIL([
                      28d94b
                           c=$(cat sw0-p2-rej-icmp6.pcap | grep \
                      28d94b
                       "IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \
                      28d94b
                       aef0::3 udp port 90" | uniq | wc -l)
                      28d94b
                      -    test $c -eq 1
                      28d94b
                      +    test $c -ge 1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       
                      28d94b
                      @@ -5179,7 +5189,7 @@ OVS_WAIT_UNTIL([
                      28d94b
                           ip netns exec sw0-p1-rej nc -u 10.0.0.4 90 < foo
                      28d94b
                           c=$(cat sw0-p1-rej-icmp.pcap | grep \
                      28d94b
                       "10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 90 unreachable" | uniq | wc -l)
                      28d94b
                      -    test $c -eq 1
                      28d94b
                      +    test $c -ge 1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       rm -f *.pcap
                      28d94b
                      @@ -5191,7 +5201,7 @@ OVS_WAIT_UNTIL([
                      28d94b
                           ip netns exec sw0-p1-rej nc -u 10.0.0.4 94 < foo
                      28d94b
                           c=$(cat sw0-p1-rej-icmp.pcap | grep \
                      28d94b
                       "10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 94 unreachable" | uniq | wc -l)
                      28d94b
                      -    test $c -eq 1
                      28d94b
                      +    test $c -ge 1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       # Now test for IPv6 UDP.
                      28d94b
                      @@ -5203,7 +5213,7 @@ OVS_WAIT_UNTIL([
                      28d94b
                           c=$(cat sw0-p2-rej-icmp6.pcap | grep \
                      28d94b
                       "IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \
                      28d94b
                       aef0::3 udp port 90" | uniq | wc -l)
                      28d94b
                      -    test $c -eq 1
                      28d94b
                      +    test $c -ge 1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       rm -f *.pcap
                      28d94b
                      @@ -5216,7 +5226,7 @@ OVS_WAIT_UNTIL([
                      28d94b
                           c=$(cat sw0-p2-rej-icmp6.pcap | grep \
                      28d94b
                       "IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \
                      28d94b
                       aef0::3 udp port 94" | uniq | wc -l)
                      28d94b
                      -    test $c -eq 1
                      28d94b
                      +    test $c -ge 1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       # Delete all the ACLs of pg0 and add the ACL with a generic match with reject action.
                      28d94b
                      @@ -5241,7 +5251,7 @@ OVS_WAIT_UNTIL([
                      28d94b
                           ip netns exec sw0-p1-rej nc -u 10.0.0.4 90 < foo
                      28d94b
                           c=$(cat sw0-p1-rej-icmp.pcap | grep \
                      28d94b
                       "10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 90 unreachable" | uniq | wc -l)
                      28d94b
                      -    test $c -eq 1
                      28d94b
                      +    test $c -ge 1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       rm -f *.pcap
                      28d94b
                      @@ -5253,7 +5263,7 @@ OVS_WAIT_UNTIL([
                      28d94b
                           c=$(cat sw0-p2-rej-icmp6.pcap | grep \
                      28d94b
                       "IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \
                      28d94b
                       aef0::3 udp port 90" | uniq | wc -l)
                      28d94b
                      -    test $c -eq 1
                      28d94b
                      +    test $c -ge 1
                      28d94b
                       ])
                      28d94b
                       
                      28d94b
                       
                      28d94b
                      @@ -9277,13 +9287,15 @@ test_related_traffic() {
                      28d94b
                       
                      28d94b
                           check ovs-appctl dpctl/flush-conntrack
                      28d94b
                       
                      28d94b
                      -    NETNS_DAEMONIZE([client], [tcpdump -U -i client -w client.pcap], [tcpdump0.pid])
                      28d94b
                      -    NETNS_DAEMONIZE([server], [tcpdump -U -i server -w server.pcap], [tcpdump1.pid])
                      28d94b
                      +    NETNS_DAEMONIZE([client], [tcpdump -l -U -i client -w client.pcap 2>client_err], [tcpdump0.pid])
                      28d94b
                      +    NETNS_DAEMONIZE([server], [tcpdump -l -U -i server -w server.pcap 2>server_err], [tcpdump1.pid])
                      28d94b
                       
                      28d94b
                           # Setup a dummy UDP listeners so we don't get "port unreachable".
                      28d94b
                           NETNS_DAEMONIZE([client], [nc -l -u 1], [nc0.pid])
                      28d94b
                           NETNS_DAEMONIZE([server], [nc -l -u 2], [nc1.pid])
                      28d94b
                      -    sleep 1
                      28d94b
                      +
                      28d94b
                      +    OVS_WAIT_UNTIL([grep "listening" client_err])
                      28d94b
                      +    OVS_WAIT_UNTIL([grep "listening" server_err])
                      28d94b
                       
                      28d94b
                           # Send UDP client -> server
                      28d94b
                           check ovs-ofctl packet-out br-int "in_port=ovs-client,packet=$client_udp,actions=resubmit(,0)"
                      28d94b
                      @@ -9479,7 +9491,8 @@ name: 'vport' value: '666'
                      28d94b
                       # Start IPv4 TCP server on vm1.
                      28d94b
                       NETNS_DAEMONIZE([vm1], [nc -k -l 42.42.42.2 4242], [nc-vm1.pid])
                      28d94b
                       
                      28d94b
                      -# Make sure connecting to the VIP works.
                      28d94b
                      +# Make sure connecting to the VIP works (hairpin, via ls and via lr).
                      28d94b
                      +NS_CHECK_EXEC([vm1], [nc 66.66.66.66 666 -z], [0], [ignore], [ignore])
                      28d94b
                       NS_CHECK_EXEC([vm2], [nc 66.66.66.66 666 -z], [0], [ignore], [ignore])
                      28d94b
                       NS_CHECK_EXEC([vm3], [nc 66.66.66.66 666 -z], [0], [ignore], [ignore])
                      28d94b
                       
                      28d94b
                      @@ -9572,9 +9585,263 @@ name: 'vport' value: '666'
                      28d94b
                       # Start IPv6 TCP server on vm1.
                      28d94b
                       NETNS_DAEMONIZE([vm1], [nc -k -l 4242::2 4242], [nc-vm1.pid])
                      28d94b
                       
                      28d94b
                      -# Make sure connecting to the VIP works.
                      28d94b
                      +# Make sure connecting to the VIP works (hairpin, via ls and via lr).
                      28d94b
                      +NS_CHECK_EXEC([vm1], [nc 6666::1 666 -z], [0], [ignore], [ignore])
                      28d94b
                       NS_CHECK_EXEC([vm2], [nc 6666::1 666 -z], [0], [ignore], [ignore])
                      28d94b
                       NS_CHECK_EXEC([vm3], [nc 6666::1 666 -z], [0], [ignore], [ignore])
                      28d94b
                       
                      28d94b
                       AT_CLEANUP
                      28d94b
                       ])
                      28d94b
                      +
                      28d94b
                      +###########################################################
                      28d94b
                      +## ls1 -- cluster-router -- join - gr1 -- public1 -- ln1 ##
                      28d94b
                      +###########################################################
                      28d94b
                      +OVN_FOR_EACH_NORTHD([
                      28d94b
                      +AT_SETUP([Gateway router with dynamic_neigh_routers])
                      28d94b
                      +
                      28d94b
                      +CHECK_CONNTRACK()
                      28d94b
                      +CHECK_CONNTRACK_NAT()
                      28d94b
                      +ovn_start
                      28d94b
                      +OVS_TRAFFIC_VSWITCHD_START()
                      28d94b
                      +ADD_BR([br-int])
                      28d94b
                      +ADD_BR([br-ex], [set Bridge br-ex fail-mode=standalone])
                      28d94b
                      +
                      28d94b
                      +check ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=provider:br-ex
                      28d94b
                      +
                      28d94b
                      +# Set external-ids in br-int needed for ovn-controller
                      28d94b
                      +ovs-vsctl \
                      28d94b
                      +        -- set Open_vSwitch . external-ids:system-id=hv1 \
                      28d94b
                      +        -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
                      28d94b
                      +        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
                      28d94b
                      +        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
                      28d94b
                      +        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
                      28d94b
                      +
                      28d94b
                      +# Start ovn-controller
                      28d94b
                      +start_daemon ovn-controller
                      28d94b
                      +
                      28d94b
                      +# Add routers
                      28d94b
                      +check ovn-nbctl lr-add gr1
                      28d94b
                      +check ovn-nbctl lr-add cluster-router
                      28d94b
                      +
                      28d94b
                      +# Add switches
                      28d94b
                      +check ovn-nbctl ls-add join
                      28d94b
                      +check ovn-nbctl ls-add public1
                      28d94b
                      +check ovn-nbctl ls-add ls1
                      28d94b
                      +
                      28d94b
                      +# Add ls1 ports
                      28d94b
                      +check ovn-nbctl lsp-add ls1 ls1p1 \
                      28d94b
                      +    -- lsp-set-addresses ls1p1 "00:00:00:00:01:11 10.244.2.11"
                      28d94b
                      +
                      28d94b
                      +check ovn-nbctl lsp-add ls1 ls1-to-cluster-router \
                      28d94b
                      +    -- lsp-set-type ls1-to-cluster-router router \
                      28d94b
                      +    -- lsp-set-options ls1-to-cluster-router router-port=cluster-router-to-ls1 \
                      28d94b
                      +    -- lsp-set-addresses ls1-to-cluster-router router
                      28d94b
                      +
                      28d94b
                      +# Add cluster-router ports
                      28d94b
                      +check ovn-nbctl lrp-add cluster-router cluster-router-to-ls1 "00:00:00:0f:01:01" 10.244.2.1/24 \
                      28d94b
                      +    -- lrp-add cluster-router cluster-router-to-join "00:00:00:0f:02:01" 100.64.0.1/16 \
                      28d94b
                      +    -- lrp-set-gateway-chassis cluster-router-to-ls1 hv1 10 \
                      28d94b
                      +    -- --policy=src-ip lr-route-add cluster-router 10.244.2.0/24 100.64.0.3
                      28d94b
                      +
                      28d94b
                      +# Add join ports
                      28d94b
                      +check ovn-nbctl lsp-add join join-to-cluster-router \
                      28d94b
                      +    -- lsp-set-type join-to-cluster-router router \
                      28d94b
                      +    -- lsp-set-options join-to-cluster-router router-port=cluster-router-to-join \
                      28d94b
                      +    -- lsp-set-addresses join-to-cluster-router router \
                      28d94b
                      +    -- lsp-add join join-to-gr1 \
                      28d94b
                      +    -- lsp-set-type join-to-gr1 router \
                      28d94b
                      +    -- lsp-set-options join-to-gr1 router-port=gr1-to-join \
                      28d94b
                      +    -- lsp-set-addresses join-to-gr1 router
                      28d94b
                      +
                      28d94b
                      +check ovn-nbctl set logical_router gr1 options:lb_force_snat_ip=router_ip \
                      28d94b
                      +    -- set logical_router gr1 options:snat-ct-zone=0 \
                      28d94b
                      +    -- set logical_router gr1 options:dynamic_neigh_routers=true
                      28d94b
                      +
                      28d94b
                      +# Add gr1 ports and set natting
                      28d94b
                      +check ovn-nbctl lrp-add gr1 gr1-to-join "00:00:00:0f:02:03" 100.64.0.3/16 \
                      28d94b
                      +    -- lr-route-add gr1 10.244.0.0/16 100.64.0.1 \
                      28d94b
                      +    -- lr-nat-add gr1 snat 10.89.189.12 10.244.0.0/16 \
                      28d94b
                      +    -- lrp-add gr1 gr1-to-public1 "0a:0a:b6:fc:03:12" 10.89.189.12/24 \
                      28d94b
                      +    -- set logical_router gr1 options:chassis=hv1
                      28d94b
                      +
                      28d94b
                      +# Add public1 ports
                      28d94b
                      +check ovn-nbctl lsp-add public1 public1-to-gr1 \
                      28d94b
                      +    -- lsp-set-type public1-to-gr1 router \
                      28d94b
                      +    -- lsp-set-options public1-to-gr1 router-port=gr1-to-public1 \
                      28d94b
                      +    -- lsp-set-addresses public1-to-gr1 router \
                      28d94b
                      +    -- lsp-add public1 ln1 \
                      28d94b
                      +    -- lsp-set-type ln1 localnet \
                      28d94b
                      +    -- lsp-set-options ln1 network_name=provider \
                      28d94b
                      +    -- lsp-set-addresses ln1 unknown
                      28d94b
                      +
                      28d94b
                      +check ovn-nbctl --wait=hv sync
                      28d94b
                      +
                      28d94b
                      +ADD_NAMESPACES(ns_ls1p1)
                      28d94b
                      +ADD_VETH(ls1p1, ns_ls1p1, br-int, "10.244.2.11/24", "00:00:00:00:01:11", "10.244.2.1")
                      28d94b
                      +
                      28d94b
                      +ADD_NAMESPACES(ns_ext1)
                      28d94b
                      +ADD_VETH(ln1, ns_ext1, br-ex, "10.89.189.1/24", "0a:0a:b6:fc:03:01")
                      28d94b
                      +
                      28d94b
                      +NS_CHECK_EXEC([ns_ls1p1], [ping -q -c 3 -i 0.3 -w 2 10.89.189.1 | FORMAT_PING], \
                      28d94b
                      +[0], [dnl
                      28d94b
                      +3 packets transmitted, 3 received, 0% packet loss, time 0ms
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +OVS_APP_EXIT_AND_WAIT([ovn-controller])
                      28d94b
                      +
                      28d94b
                      +as ovn-sb
                      28d94b
                      +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
                      28d94b
                      +
                      28d94b
                      +as ovn-nb
                      28d94b
                      +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
                      28d94b
                      +
                      28d94b
                      +as northd
                      28d94b
                      +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE])
                      28d94b
                      +
                      28d94b
                      +as
                      28d94b
                      +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
                      28d94b
                      +/connection dropped.*/d"])
                      28d94b
                      +AT_CLEANUP
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +OVN_FOR_EACH_NORTHD([
                      28d94b
                      +AT_SETUP([ACL default_acl_drop])
                      28d94b
                      +AT_KEYWORDS([acl default_acl_drop])
                      28d94b
                      +
                      28d94b
                      +CHECK_CONNTRACK()
                      28d94b
                      +ovn_start
                      28d94b
                      +
                      28d94b
                      +OVS_TRAFFIC_VSWITCHD_START()
                      28d94b
                      +ADD_BR([br-int])
                      28d94b
                      +
                      28d94b
                      +# Set external-ids in br-int needed for ovn-controller
                      28d94b
                      +ovs-vsctl \
                      28d94b
                      +        -- set Open_vSwitch . external-ids:system-id=hv1 \
                      28d94b
                      +        -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
                      28d94b
                      +        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
                      28d94b
                      +        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
                      28d94b
                      +        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
                      28d94b
                      +
                      28d94b
                      +# Start ovn-controller
                      28d94b
                      +start_daemon ovn-controller
                      28d94b
                      +
                      28d94b
                      +ovn-nbctl ls-add sw
                      28d94b
                      +
                      28d94b
                      +# Logical port 'vm1' in switch 'sw'.
                      28d94b
                      +ADD_NAMESPACES(vm1)
                      28d94b
                      +ADD_VETH(vm1, vm1, br-int, "10.0.0.1/24", "f0:00:00:01:02:03", \
                      28d94b
                      +         "10.0.0.254")
                      28d94b
                      +check ovn-nbctl lsp-add sw vm1 \
                      28d94b
                      +-- lsp-set-addresses vm1 "f0:00:00:01:02:03 10.0.0.1"
                      28d94b
                      +
                      28d94b
                      +# Logical port 'vm2' in switch 'sw'.
                      28d94b
                      +ADD_NAMESPACES(vm2)
                      28d94b
                      +ADD_VETH(vm2, vm2, br-int, "10.0.0.2/24", "f0:00:00:01:02:05", \
                      28d94b
                      +"10.0.0.254")
                      28d94b
                      +check ovn-nbctl lsp-add sw vm2 \
                      28d94b
                      +-- lsp-set-addresses vm2 "f0:00:00:01:02:05 10.0.0.2"
                      28d94b
                      +
                      28d94b
                      +# Wait for ovn-controller to catch up.
                      28d94b
                      +wait_for_ports_up
                      28d94b
                      +check ovn-nbctl --wait=hv sync
                      28d94b
                      +
                      28d94b
                      +AS_BOX([from-lport acl, default_acl_drop false])
                      28d94b
                      +check ovn-nbctl acl-del sw
                      28d94b
                      +check ovn-nbctl set NB_Global . options:default_acl_drop=false \
                      28d94b
                      +    -- acl-add sw from-lport 20 "ip4 && icmp" allow-related \
                      28d94b
                      +    -- acl-add sw from-lport 10 "ip4" drop
                      28d94b
                      +check ovn-nbctl --wait=hv sync
                      28d94b
                      +
                      28d94b
                      +# 'vm1' should be able to ping 'vm2' directly.
                      28d94b
                      +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.2 | FORMAT_PING], \
                      28d94b
                      +[0], [dnl
                      28d94b
                      +3 packets transmitted, 3 received, 0% packet loss, time 0ms
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +AS_BOX([from-lport acl, default_acl_drop true])
                      28d94b
                      +check ovn-nbctl acl-del sw
                      28d94b
                      +check ovn-nbctl set NB_Global . options:default_acl_drop=true \
                      28d94b
                      +    -- acl-add sw from-lport 20 "ip4 && icmp" allow-related \
                      28d94b
                      +    -- acl-add sw from-lport 10 "arp" allow \
                      28d94b
                      +    -- --apply-after-lb acl-add sw from-lport 1 1 allow \
                      28d94b
                      +    -- acl-add sw to-lport 1 1 allow
                      28d94b
                      +check ovn-nbctl --wait=hv sync
                      28d94b
                      +
                      28d94b
                      +# 'vm1' should be able to ping 'vm2' directly.
                      28d94b
                      +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.2 | FORMAT_PING], \
                      28d94b
                      +[0], [dnl
                      28d94b
                      +3 packets transmitted, 3 received, 0% packet loss, time 0ms
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +AS_BOX([from-lport acl, after LB, default_acl_drop false])
                      28d94b
                      +check ovn-nbctl acl-del sw
                      28d94b
                      +check ovn-nbctl set NB_Global . options:default_acl_drop=false \
                      28d94b
                      +    -- --apply-after-lb acl-add sw from-lport 20 "ip4 && icmp" allow-related \
                      28d94b
                      +    -- --apply-after-lb acl-add sw from-lport 10 "ip4" drop
                      28d94b
                      +check ovn-nbctl --wait=hv sync
                      28d94b
                      +
                      28d94b
                      +# 'vm1' should be able to ping 'vm2' directly.
                      28d94b
                      +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.2 | FORMAT_PING], \
                      28d94b
                      +[0], [dnl
                      28d94b
                      +3 packets transmitted, 3 received, 0% packet loss, time 0ms
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +AS_BOX([from-lport acl, after LB, default_acl_drop true])
                      28d94b
                      +check ovn-nbctl acl-del sw
                      28d94b
                      +check ovn-nbctl set NB_Global . options:default_acl_drop=true \
                      28d94b
                      +    -- acl-add sw from-lport 1 1 allow \
                      28d94b
                      +    -- --apply-after-lb acl-add sw from-lport 20 "ip4 && icmp" allow-related \
                      28d94b
                      +    -- --apply-after-lb acl-add sw from-lport 20 "arp" allow-related \
                      28d94b
                      +    -- acl-add sw to-lport 1 1 allow
                      28d94b
                      +check ovn-nbctl --wait=hv sync
                      28d94b
                      +
                      28d94b
                      +# 'vm1' should be able to ping 'vm2' directly.
                      28d94b
                      +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.2 | FORMAT_PING], \
                      28d94b
                      +[0], [dnl
                      28d94b
                      +3 packets transmitted, 3 received, 0% packet loss, time 0ms
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +AS_BOX([to-lport acl, default_acl_drop false])
                      28d94b
                      +check ovn-nbctl acl-del sw
                      28d94b
                      +check ovn-nbctl set NB_Global . options:default_acl_drop=false \
                      28d94b
                      +    -- acl-add sw to-lport 20 "ip4 && icmp" allow-related \
                      28d94b
                      +    -- acl-add sw to-lport 10 "ip4" drop
                      28d94b
                      +check ovn-nbctl --wait=hv sync
                      28d94b
                      +
                      28d94b
                      +# 'vm1' should be able to ping 'vm2' directly.
                      28d94b
                      +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.2 | FORMAT_PING], \
                      28d94b
                      +[0], [dnl
                      28d94b
                      +3 packets transmitted, 3 received, 0% packet loss, time 0ms
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +AS_BOX([to-lport acl, default_acl_drop true])
                      28d94b
                      +check ovn-nbctl acl-del sw
                      28d94b
                      +check ovn-nbctl set NB_Global . options:default_acl_drop=true \
                      28d94b
                      +    -- acl-add sw from-lport 1 1 allow \
                      28d94b
                      +    -- --apply-after-lb acl-add sw from-lport 1 1 allow \
                      28d94b
                      +    -- acl-add sw to-lport 20 "ip4 && icmp" allow-related \
                      28d94b
                      +    -- acl-add sw to-lport 20 "arp" allow
                      28d94b
                      +check ovn-nbctl --wait=hv sync
                      28d94b
                      +
                      28d94b
                      +# 'vm1' should be able to ping 'vm2' directly.
                      28d94b
                      +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.2 | FORMAT_PING], \
                      28d94b
                      +[0], [dnl
                      28d94b
                      +3 packets transmitted, 3 received, 0% packet loss, time 0ms
                      28d94b
                      +])
                      28d94b
                      +
                      28d94b
                      +OVS_APP_EXIT_AND_WAIT([ovn-controller])
                      28d94b
                      +
                      28d94b
                      +as ovn-sb
                      28d94b
                      +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
                      28d94b
                      +
                      28d94b
                      +as ovn-nb
                      28d94b
                      +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
                      28d94b
                      +
                      28d94b
                      +as northd
                      28d94b
                      +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE])
                      28d94b
                      +
                      28d94b
                      +as
                      28d94b
                      +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
                      28d94b
                      +/connection dropped.*/d"])
                      28d94b
                      +AT_CLEANUP
                      28d94b
                      +])
                      28d94b
                      diff --git a/utilities/ovn-dbctl.c b/utilities/ovn-dbctl.c
                      28d94b
                      index a850c2f31..5edb82e7f 100644
                      28d94b
                      --- a/utilities/ovn-dbctl.c
                      28d94b
                      +++ b/utilities/ovn-dbctl.c
                      28d94b
                      @@ -109,6 +109,15 @@ static void server_loop(const struct ovn_dbctl_options *dbctl_options,
                      28d94b
                                               struct ovsdb_idl *idl, int argc, char *argv[]);
                      28d94b
                       static void ovn_dbctl_exit(int status);
                      28d94b
                       
                      28d94b
                      +static void
                      28d94b
                      +destroy_argv(int argc, char **argv)
                      28d94b
                      +{
                      28d94b
                      +    for (int i = 0; i < argc; i++) {
                      28d94b
                      +        free(argv[i]);
                      28d94b
                      +    }
                      28d94b
                      +    free(argv);
                      28d94b
                      +}
                      28d94b
                      +
                      28d94b
                       int
                      28d94b
                       ovn_dbctl_main(int argc, char *argv[],
                      28d94b
                                      const struct ovn_dbctl_options *dbctl_options)
                      28d94b
                      @@ -151,6 +160,7 @@ ovn_dbctl_main(int argc, char *argv[],
                      28d94b
                           char *error_s = ovs_cmdl_parse_all(argc, argv_, get_all_options(),
                      28d94b
                                                              &parsed_options, &n_parsed_options);
                      28d94b
                           if (error_s) {
                      28d94b
                      +        destroy_argv(argc, argv_);
                      28d94b
                               ctl_fatal("%s", error_s);
                      28d94b
                           }
                      28d94b
                       
                      28d94b
                      @@ -179,6 +189,7 @@ ovn_dbctl_main(int argc, char *argv[],
                      28d94b
                           bool daemon_mode = false;
                      28d94b
                           if (get_detach()) {
                      28d94b
                               if (argc != optind) {
                      28d94b
                      +            destroy_argv(argc, argv_);
                      28d94b
                                   ctl_fatal("non-option arguments not supported with --detach "
                      28d94b
                                             "(use --help for help)");
                      28d94b
                               }
                      28d94b
                      @@ -204,11 +215,8 @@ ovn_dbctl_main(int argc, char *argv[],
                      28d94b
                               if (error) {
                      28d94b
                                   ovsdb_idl_destroy(idl);
                      28d94b
                                   idl = the_idl = NULL;
                      28d94b
                      +            destroy_argv(argc, argv_);
                      28d94b
                       
                      28d94b
                      -            for (int i = 0; i < argc; i++) {
                      28d94b
                      -                free(argv_[i]);
                      28d94b
                      -            }
                      28d94b
                      -            free(argv_);
                      28d94b
                                   ctl_fatal("%s", error);
                      28d94b
                               }
                      28d94b
                       
                      28d94b
                      @@ -237,21 +245,15 @@ cleanup:
                      28d94b
                               }
                      28d94b
                               free(commands);
                      28d94b
                               if (error) {
                      28d94b
                      -            for (int i = 0; i < argc; i++) {
                      28d94b
                      -                free(argv_[i]);
                      28d94b
                      -            }
                      28d94b
                      -            free(argv_);
                      28d94b
                      +            destroy_argv(argc, argv_);
                      28d94b
                                   ctl_fatal("%s", error);
                      28d94b
                               }
                      28d94b
                           }
                      28d94b
                       
                      28d94b
                           ovsdb_idl_destroy(idl);
                      28d94b
                           idl = the_idl = NULL;
                      28d94b
                      +    destroy_argv(argc, argv_);
                      28d94b
                       
                      28d94b
                      -    for (int i = 0; i < argc; i++) {
                      28d94b
                      -        free(argv_[i]);
                      28d94b
                      -    }
                      28d94b
                      -    free(argv_);
                      28d94b
                           exit(EXIT_SUCCESS);
                      28d94b
                       }
                      28d94b
                       
                      28d94b
                      @@ -1238,40 +1240,53 @@ dbctl_client(const struct ovn_dbctl_options *dbctl_options,
                      28d94b
                       
                      28d94b
                           ctl_timeout_setup(timeout);
                      28d94b
                       
                      28d94b
                      +    char *cmd_result = NULL;
                      28d94b
                      +    char *cmd_error = NULL;
                      28d94b
                           struct jsonrpc *client;
                      28d94b
                      +    int exit_status;
                      28d94b
                      +    char *error_str;
                      28d94b
                      +
                      28d94b
                           int error = unixctl_client_create(socket_name, &client);
                      28d94b
                           if (error) {
                      28d94b
                      -        ctl_fatal("%s: could not connect to %s daemon (%s); "
                      28d94b
                      -                  "unset %s to avoid using daemon",
                      28d94b
                      -                  socket_name, program_name, ovs_strerror(error),
                      28d94b
                      -                  dbctl_options->daemon_env_var_name);
                      28d94b
                      +        error_str = xasprintf("%s: could not connect to %s daemon (%s); "
                      28d94b
                      +                              "unset %s to avoid using daemon",
                      28d94b
                      +                              socket_name, program_name, ovs_strerror(error),
                      28d94b
                      +                              dbctl_options->daemon_env_var_name);
                      28d94b
                      +        goto log_error;
                      28d94b
                           }
                      28d94b
                       
                      28d94b
                      -    char *cmd_result;
                      28d94b
                      -    char *cmd_error;
                      28d94b
                           error = unixctl_client_transact(client, "run",
                      28d94b
                                                           args.n, args.names,
                      28d94b
                                                           &cmd_result, &cmd_error);
                      28d94b
                           if (error) {
                      28d94b
                      -        ctl_fatal("%s: transaction error (%s)",
                      28d94b
                      -                  socket_name, ovs_strerror(error));
                      28d94b
                      +        error_str = xasprintf("%s: transaction error (%s)",
                      28d94b
                      +                              socket_name, ovs_strerror(error));
                      28d94b
                      +        goto log_error;
                      28d94b
                           }
                      28d94b
                      -    svec_destroy(&args);
                      28d94b
                       
                      28d94b
                      -    int exit_status;
                      28d94b
                           if (cmd_error) {
                      28d94b
                      -        exit_status = EXIT_FAILURE;
                      28d94b
                               fprintf(stderr, "%s: %s", program_name, cmd_error);
                      28d94b
                      -    } else {
                      28d94b
                      -        exit_status = EXIT_SUCCESS;
                      28d94b
                      -        fputs(cmd_result, stdout);
                      28d94b
                      +        goto error;
                      28d94b
                           }
                      28d94b
                      +
                      28d94b
                      +    exit_status = EXIT_SUCCESS;
                      28d94b
                      +    fputs(cmd_result, stdout);
                      28d94b
                      +    goto cleanup;
                      28d94b
                      +
                      28d94b
                      +log_error:
                      28d94b
                      +    VLOG_ERR("%s", error_str);
                      28d94b
                      +    ovs_error(0, "%s", error_str);
                      28d94b
                      +    free(error_str);
                      28d94b
                      +
                      28d94b
                      +error:
                      28d94b
                      +    exit_status = EXIT_FAILURE;
                      28d94b
                      +
                      28d94b
                      +cleanup:
                      28d94b
                           free(cmd_result);
                      28d94b
                           free(cmd_error);
                      28d94b
                           jsonrpc_close(client);
                      28d94b
                      -    for (int i = 0; i < argc; i++) {
                      28d94b
                      -        free(argv[i]);
                      28d94b
                      -    }
                      28d94b
                      -    free(argv);
                      28d94b
                      +    svec_destroy(&args);
                      28d94b
                      +    destroy_argv(argc, argv);
                      28d94b
                      +
                      28d94b
                           exit(exit_status);
                      28d94b
                       }
                      28d94b
                      diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml
                      28d94b
                      index 92e10c012..72d4088f0 100644
                      28d94b
                      --- a/utilities/ovn-nbctl.8.xml
                      28d94b
                      +++ b/utilities/ovn-nbctl.8.xml
                      28d94b
                      @@ -814,7 +814,7 @@
                      28d94b
                               Attaches the mirror m to the logical port port.
                      28d94b
                             
                      28d94b
                       
                      28d94b
                      -      
                      lsp-dettach-mirror port m
                      28d94b
                      +      
                      lsp-detach-mirror port m
                      28d94b
                             
                      28d94b
                               Detaches the mirror m from the logical port port.
                      28d94b
                             
                      28d94b
                      diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
                      28d94b
                      index 07ebac5e5..e5766ed67 100644
                      28d94b
                      --- a/utilities/ovn-trace.c
                      28d94b
                      +++ b/utilities/ovn-trace.c
                      28d94b
                      @@ -1486,9 +1486,8 @@ ovntrace_node_prune_hard(struct ovs_list *nodes)
                      28d94b
                       }
                      28d94b
                       
                      28d94b
                       static void
                      28d94b
                      -execute_load(const struct ovnact_load *load,
                      28d94b
                      -             const struct ovntrace_datapath *dp, struct flow *uflow,
                      28d94b
                      -             struct ovs_list *super OVS_UNUSED)
                      28d94b
                      +execute_load(const struct ovnact *ovnact, const struct ovntrace_datapath *dp,
                      28d94b
                      +             struct flow *uflow, struct ovs_list *super OVS_UNUSED)
                      28d94b
                       {
                      28d94b
                           const struct ovnact_encode_params ep = {
                      28d94b
                               .lookup_port = ovntrace_lookup_port,
                      28d94b
                      @@ -1498,7 +1497,7 @@ execute_load(const struct ovnact_load *load,
                      28d94b
                           uint64_t stub[512 / 8];
                      28d94b
                           struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub);
                      28d94b
                       
                      28d94b
                      -    ovnacts_encode(&load->ovnact, sizeof *load, &ep, &ofpacts);
                      28d94b
                      +    ovnacts_encode(ovnact, OVNACT_ALIGN(ovnact->len), &ep, &ofpacts);
                      28d94b
                       
                      28d94b
                           struct ofpact *a;
                      28d94b
                           OFPACT_FOR_EACH (a, ofpacts.data, ofpacts.size) {
                      28d94b
                      @@ -1506,12 +1505,11 @@ execute_load(const struct ovnact_load *load,
                      28d94b
                       
                      28d94b
                               if (!mf_is_register(sf->field->id)) {
                      28d94b
                                   struct ds s = DS_EMPTY_INITIALIZER;
                      28d94b
                      -            ovnacts_format(&load->ovnact, OVNACT_LOAD_SIZE, &s);
                      28d94b
                      -            ds_chomp(&s, ';');
                      28d94b
                       
                      28d94b
                      -            char *friendly = ovntrace_make_names_friendly(ds_cstr(&s);;
                      28d94b
                      -            ovntrace_node_append(super, OVNTRACE_NODE_MODIFY, "%s", friendly);
                      28d94b
                      -            free(friendly);
                      28d94b
                      +            ovnacts_format(ovnact, OVNACT_ALIGN(ovnact->len), &s);
                      28d94b
                      +            ds_chomp(&s, ';');
                      28d94b
                      +            ovntrace_node_append(super, OVNTRACE_NODE_MODIFY, "%s",
                      28d94b
                      +                                 ds_cstr(&s);;
                      28d94b
                       
                      28d94b
                                   ds_destroy(&s);
                      28d94b
                               }
                      28d94b
                      @@ -3057,7 +3055,7 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
                      28d94b
                           const struct ovnact *a;
                      28d94b
                           OVNACT_FOR_EACH (a, ovnacts, ovnacts_len) {
                      28d94b
                               ds_clear(&s);
                      28d94b
                      -        ovnacts_format(a, sizeof *a * (ovnact_next(a) - a), &s);
                      28d94b
                      +        ovnacts_format(a, OVNACT_ALIGN(a->len), &s);
                      28d94b
                               char *friendly = ovntrace_make_names_friendly(ds_cstr(&s);;
                      28d94b
                               ovntrace_node_append(super, OVNTRACE_NODE_ACTION, "%s", friendly);
                      28d94b
                               free(friendly);
                      28d94b
                      @@ -3072,7 +3070,7 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
                      28d94b
                                   break;
                      28d94b
                       
                      28d94b
                               case OVNACT_LOAD:
                      28d94b
                      -            execute_load(ovnact_get_LOAD(a), dp, uflow, super);
                      28d94b
                      +            execute_load(a, dp, uflow, super);
                      28d94b
                                   break;
                      28d94b
                       
                      28d94b
                               case OVNACT_MOVE: