On Wed, Feb 24, 2021 at 2:37 PM Numan Siddique <[email protected]> wrote:
>
> On Tue, Feb 23, 2021 at 6:50 PM Dumitru Ceara <[email protected]> wrote:
> >
> > If two load balancer VIPs share the same backend, both sets of hairpin
> > reply learn() flows should be generated.  In order to ensure that,
> > also match on the original destination IP and port tuple.  These are
> > now stored in OVS registers by ovn-northd in stage ls-in-stateful.
> >
> > An alternative solution would be to add an additional match on
> > ct_nw_dst() and ct_tp_dst() in the hairpin detection flows but it's
> > better to avoid that because these matches are usually not offloadable
> > to hardware.
> >
> > To ensure backwards compatibility though, if ovn-controller detects
> > that ovn-northd doesn't store the original destination tuple
> > information in OVS registers, ovn-controller falls back to using
> > ct_nw_dst() and ct_tp_dst().
> >
> > Reported-by: Tim Rozet <[email protected]>
> > Reported-at: https://bugzilla.redhat.com/1931599
> > Fixes: 022ea339c8e2 ("lflow: Use learn() action to generate LB hairpin 
> > reply flows.")
> > Signed-off-by: Dumitru Ceara <[email protected]>
>
> Hi Dumitru,
>
> Thanks for the fix.
>
> A couple of minor nits below.
> With those addressed.
>
> Acked-by: Numan Siddique <[email protected]>
>

I would also suggest to enhance the test in ovn.at to pause ovn-northd,
clear the lb option - 'hairpin_orig_tuple' and make sure that flows
have the match with the ct_* fields.

Thanks
Numan

> Numan
>
> > ---
> >  controller/lflow.c           |   56 +++++-
> >  include/ovn/logical-fields.h |    6 +
> >  lib/lb.c                     |    3
> >  lib/lb.h                     |    3
> >  northd/ovn-northd.8.xml      |   21 ++
> >  northd/ovn-northd.c          |   93 +++++++++-
> >  ovn-sb.xml                   |    6 +
> >  tests/ofproto-macros.at      |    2
> >  tests/ovn-northd.at          |   28 ++-
> >  tests/ovn.at                 |  377 
> > +++++++++++++++++++++++++++++++-----------
> >  tests/system-ovn.at          |   40 +++-
> >  11 files changed, 486 insertions(+), 149 deletions(-)
> >
> > diff --git a/controller/lflow.c b/controller/lflow.c
> > index 8468cb4..104fbeb 100644
> > --- a/controller/lflow.c
> > +++ b/controller/lflow.c
> > @@ -1228,6 +1228,12 @@ add_lb_vip_hairpin_reply_action(struct in6_addr 
> > *vip6, ovs_be32 vip,
> >      ofpact_finish_LEARN(ofpacts, &ol);
> >  }
> >
> > +/* Adds flows to detect hairpin sessions.
> > + *
> > + * For backwards compatibilty with older ovn-northd versions, uses
> > + * ct_nw_dst(), ct_ipv6_dst(), ct_tp_dst(), otherwise uses the
> > + * original destination tuple stored by ovn-northd.
> > + */
> >  static void
> >  add_lb_vip_hairpin_flows(struct ovn_controller_lb *lb,
> >                           struct ovn_lb_vip *lb_vip,
> > @@ -1243,30 +1249,58 @@ add_lb_vip_hairpin_flows(struct ovn_controller_lb 
> > *lb,
> >      put_load(&value, sizeof value, MFF_LOG_FLAGS,
> >               MLF_LOOKUP_LB_HAIRPIN_BIT, 1, &ofpacts);
> >
> > +    /* Matching on ct_nw_dst()/ct_ipv6_dst()/ct_tp_dst() requires matching
> > +     * on ct_state first.
> > +     */
> > +    if (!lb->hairpin_orig_tuple) {
> > +        uint32_t ct_state = OVS_CS_F_TRACKED | OVS_CS_F_DST_NAT;
> > +        match_set_ct_state_masked(&hairpin_match, ct_state, ct_state);
> > +    }
> > +
> >      if (IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)) {
> >          ovs_be32 bip4 = in6_addr_get_mapped_ipv4(&lb_backend->ip);
> > -        ovs_be32 vip4 = lb->hairpin_snat_ips.n_ipv4_addrs
> > +        ovs_be32 vip4 = in6_addr_get_mapped_ipv4(&lb_vip->vip);
> > +        ovs_be32 snat_vip4 = lb->hairpin_snat_ips.n_ipv4_addrs
> >                          ? lb->hairpin_snat_ips.ipv4_addrs[0].addr
> > -                        : in6_addr_get_mapped_ipv4(&lb_vip->vip);
> > +                        : vip4;
> >
> >          match_set_dl_type(&hairpin_match, htons(ETH_TYPE_IP));
> >          match_set_nw_src(&hairpin_match, bip4);
> >          match_set_nw_dst(&hairpin_match, bip4);
> >
> > -        add_lb_vip_hairpin_reply_action(NULL, vip4, lb_proto,
> > +        if (!lb->hairpin_orig_tuple) {
> > +            match_set_ct_nw_dst(&hairpin_match, vip4);
> > +        } else {
> > +            match_set_reg(&hairpin_match,
> > +                          MFF_LOG_LB_ORIG_DIP_IPV4 - MFF_LOG_REG0,
> > +                          ntohl(vip4));
> > +        }
> > +
> > +        add_lb_vip_hairpin_reply_action(NULL, snat_vip4, lb_proto,
> >                                          lb_backend->port,
> >                                          lb->slb->header_.uuid.parts[0],
> >                                          &ofpacts);
> >      } else {
> >          struct in6_addr *bip6 = &lb_backend->ip;
> > -        struct in6_addr *vip6 = lb->hairpin_snat_ips.n_ipv6_addrs
> > -                                ? &lb->hairpin_snat_ips.ipv6_addrs[0].addr
> > -                                : &lb_vip->vip;
> > +        struct in6_addr *snat_vip6 =
> > +            lb->hairpin_snat_ips.n_ipv6_addrs
> > +            ? &lb->hairpin_snat_ips.ipv6_addrs[0].addr
> > +            : &lb_vip->vip;
> >          match_set_dl_type(&hairpin_match, htons(ETH_TYPE_IPV6));
> >          match_set_ipv6_src(&hairpin_match, bip6);
> >          match_set_ipv6_dst(&hairpin_match, bip6);
> >
> > -        add_lb_vip_hairpin_reply_action(vip6, 0, lb_proto,
> > +        if (!lb->hairpin_orig_tuple) {
> > +            match_set_ct_ipv6_dst(&hairpin_match, &lb_vip->vip);
> > +        } else {
> > +            ovs_be128 vip6_value;
> > +
> > +            memcpy(&vip6_value, &lb_vip->vip, sizeof vip6_value);
> > +            match_set_xxreg(&hairpin_match, MFF_LOG_LB_ORIG_DIP_IPV6,
> > +                            ntoh128(vip6_value));
> > +        }
> > +
> > +        add_lb_vip_hairpin_reply_action(snat_vip6, 0, lb_proto,
> >                                          lb_backend->port,
> >                                          lb->slb->header_.uuid.parts[0],
> >                                          &ofpacts);
> > @@ -1275,6 +1309,14 @@ add_lb_vip_hairpin_flows(struct ovn_controller_lb 
> > *lb,
> >      if (lb_backend->port) {
> >          match_set_nw_proto(&hairpin_match, lb_proto);
> >          match_set_tp_dst(&hairpin_match, htons(lb_backend->port));
> > +        if (!lb->hairpin_orig_tuple) {
> > +            match_set_ct_nw_proto(&hairpin_match, lb_proto);
> > +            match_set_ct_tp_dst(&hairpin_match, htons(lb_vip->vip_port));
> > +        } else {
> > +            match_set_reg_masked(&hairpin_match,
> > +                                 MFF_LOG_LB_ORIG_TP_DPORT - MFF_REG0,
> > +                                 lb_vip->vip_port, UINT16_MAX);
> > +        }
> >      }
> >
> >      /* In the original direction, only match on traffic that was already
> > diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h
> > index 9d8d07f..243fb83 100644
> > --- a/include/ovn/logical-fields.h
> > +++ b/include/ovn/logical-fields.h
> > @@ -44,7 +44,11 @@ enum ovn_controller_event {
> >  /* Logical registers.
> >   *
> >   * Make sure these don't overlap with the logical fields! */
> > -#define MFF_LOG_REG0 MFF_REG0
> > +#define MFF_LOG_REG0             MFF_REG0
> > +#define MFF_LOG_LB_ORIG_DIP_IPV4 MFF_REG1
> > +#define MFF_LOG_LB_ORIG_TP_DPORT MFF_REG2
> > +#define MFF_LOG_LB_ORIG_DIP_IPV6 1
>
> I think it's better to define MFF_LOG_LB_ORIG_DIP_IPV6 as
> #define MFF_LOG_LB_ORIG_DIP_IPV6 MFF_XXREG1
>
>
> > +
> >  #define MFF_N_LOG_REGS 10
> >
> >  void ovn_init_symtab(struct shash *symtab);
> > diff --git a/lib/lb.c b/lib/lb.c
> > index e11ac00..f305e9a 100644
> > --- a/lib/lb.c
> > +++ b/lib/lb.c
> > @@ -312,6 +312,9 @@ ovn_controller_lb_create(const struct 
> > sbrec_load_balancer *sbrec_lb)
> >       */
> >      lb->n_vips = n_vips;
> >
> > +    lb->hairpin_orig_tuple = smap_get_bool(&sbrec_lb->options,
> > +                                           "hairpin_orig_tuple",
> > +                                           false);
> >      ovn_lb_get_hairpin_snat_ip(&sbrec_lb->header_.uuid, &sbrec_lb->options,
> >                                 &lb->hairpin_snat_ips);
> >      return lb;
> > diff --git a/lib/lb.h b/lib/lb.h
> > index dfce51c..9a78c72 100644
> > --- a/lib/lb.h
> > +++ b/lib/lb.h
> > @@ -95,6 +95,9 @@ struct ovn_controller_lb {
> >
> >      struct ovn_lb_vip *vips;
> >      size_t n_vips;
> > +    bool hairpin_orig_tuple; /* True if ovn-northd stores the original
> > +                              * destination tuple in registers.
> > +                              */
> >
> >      struct lport_addresses hairpin_snat_ips; /* IP (v4 and/or v6) to be 
> > used
> >                                                * as source for hairpinned
> > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
> > index ca8f02e..deffe8c 100644
> > --- a/northd/ovn-northd.8.xml
> > +++ b/northd/ovn-northd.8.xml
> > @@ -755,7 +755,11 @@
> >          of <var>VIP</var>. If health check is enabled, then <var>args</var>
> >          will only contain those endpoints whose service monitor status 
> > entry
> >          in <code>OVN_Southbound</code> db is either <code>online</code> or
> > -        empty.
> > +        empty.  For IPv4 traffic the flow also loads the original 
> > destination
> > +        IP and transport port in registers <code>reg1</code> and
> > +        <code>reg2</code>.  For IPv6 traffic the flow also loads the 
> > original
> > +        destination IP and transport port in registers <code>xxreg1</code> 
> > and
> > +        <code>reg2</code>.
> >        </li>
> >        <li>
> >          For all the configured load balancing rules for a switch in
> > @@ -767,6 +771,11 @@
> >          VIP</var></code>. The action on this flow is <code>
> >          ct_lb(<var>args</var>)</code>, where <var>args</var> contains comma
> >          separated IP addresses of the same address family as 
> > <var>VIP</var>.
> > +        For IPv4 traffic the flow also loads the original destination
> > +        IP and transport port in registers <code>reg1</code> and
> > +        <code>reg2</code>.  For IPv6 traffic the flow also loads the 
> > original
> > +        destination IP and transport port in registers <code>xxreg1</code> 
> > and
> > +        <code>reg2</code>.
> >        </li>
> >
> >        <li>
> > @@ -784,9 +793,15 @@
> >          the previous tables (with a match for <code>reg0[1] == 1</code>).
> >        </li>
> >        <li>
> > -        A priority-100 flow sends the packets to connection tracker using
> > +        Priority-100 flows that send the packets to connection tracker 
> > using
> >          <code>ct_lb;</code> as the action based on a hint provided by the
> > -        previous tables (with a match for <code>reg0[2] == 1</code>).
> > +        previous tables (with a match for <code>reg0[2] == 1</code> and
> > +        on supported load balancer protocols and address families).
> > +        For IPv4 traffic the flows also load the original destination
> > +        IP and transport port in registers <code>reg1</code> and
> > +        <code>reg2</code>.  For IPv6 traffic the flows also load the 
> > original
> > +        destination IP and transport port in registers <code>xxreg1</code> 
> > and
> > +        <code>reg2</code>.
> >        </li>
> >        <li>
> >          A priority-0 flow that simply moves traffic to the next table.
> > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> > index dcdb777..18e4cac 100644
> > --- a/northd/ovn-northd.c
> > +++ b/northd/ovn-northd.c
> > @@ -228,6 +228,10 @@ enum ovn_stage {
> >  #define REGBIT_ACL_HINT_BLOCK     "reg0[10]"
> >  #define REGBIT_LKUP_FDB           "reg0[11]"
> >
> > +#define REG_ORIG_DIP_IPV4         "reg1"
> > +#define REG_ORIG_DIP_IPV6         "xxreg1"
> > +#define REG_ORIG_TP_DPORT         "reg2[0..15]"
> > +
> >  /* Register definitions for switches and routers. */
> >
> >  /* Indicate that this packet has been recirculated using egress
> > @@ -261,12 +265,28 @@ enum ovn_stage {
> >   * OVS register usage:
> >   *
> >   * Logical Switch pipeline:
> > - * +---------+----------------------------------------------+
> > - * | R0      |     REGBIT_{CONNTRACK/DHCP/DNS/HAIRPIN}      |
> > - * |         | REGBIT_ACL_HINT_{ALLOW_NEW/ALLOW/DROP/BLOCK} |
> > - * +---------+----------------------------------------------+
> > - * | R1 - R9 |                   UNUSED                     |
> > - * +---------+----------------------------------------------+
> > + * 
> > +----+----------------------------------------------+---+------------------+
> > + * | R0 |     REGBIT_{CONNTRACK/DHCP/DNS/HAIRPIN}      |   |               
> >    |
> > + * |    | REGBIT_ACL_HINT_{ALLOW_NEW/ALLOW/DROP/BLOCK} | X |               
> >    |
> > + * +----+----------------------------------------------+ X |               
> >    |
> > + * | R1 |         ORIG_DIP_IPV4 (>= IN_STATEFUL)       | R |               
> >    |
> > + * +----+----------------------------------------------+ E |               
> >    |
> > + * | R2 |         ORIG_TP_DPORT (>= IN_STATEFUL)       | G |               
> >    |
> > + * +----+----------------------------------------------+ 0 |               
> >    |
> > + * | R3 |                   UNUSED                     |   |               
> >    |
> > + * 
> > +----+----------------------------------------------+---+------------------+
> > + * | R4 |                   UNUSED                     |   |               
> >    |
> > + * +----+----------------------------------------------+ X |   
> > ORIG_DIP_IPV6  |
> > + * | R5 |                   UNUSED                     | X | (>= 
> > IN_STATEFUL) |
> > + * +----+----------------------------------------------+ R |               
> >    |
> > + * | R6 |                   UNUSED                     | E |               
> >    |
> > + * +----+----------------------------------------------+ G |               
> >    |
> > + * | R7 |                   UNUSED                     | 1 |               
> >    |
> > + * 
> > +----+----------------------------------------------+---+------------------+
> > + * | R8 |                   UNUSED                     |
> > + * +----+----------------------------------------------+
> > + * | R9 |                   UNUSED                     |
> > + * +----+----------------------------------------------+
> >   *
> >   * Logical Router pipeline:
> >   * 
> > +-----+--------------------------+---+-----------------+---+---------------+
> > @@ -3423,10 +3443,18 @@ build_ovn_lbs(struct northd_context *ctx, struct 
> > hmap *datapaths,
> >      /* Create SB Load balancer records if not present and sync
> >       * the SB load balancer columns. */
> >      HMAP_FOR_EACH (lb, hmap_node, lbs) {
> > +        struct smap options;
> > +
> Small nit: The smap declaration can be moved down after continue.
>
>
> >          if (!lb->n_dps) {
> >              continue;
> >          }
> >
> > +        /* Store the fact that northd provides the original (destination 
> > IP +
> > +         * transport port) tuple.
> > +         */
> > +        smap_clone(&options, &lb->nlb->options);
> > +        smap_replace(&options, "hairpin_orig_tuple", "true");
> > +
> >          if (!lb->slb) {
> >              sbrec_lb = sbrec_load_balancer_insert(ctx->ovnsb_txn);
> >              lb->slb = sbrec_lb;
> > @@ -3440,10 +3468,11 @@ build_ovn_lbs(struct northd_context *ctx, struct 
> > hmap *datapaths,
> >          sbrec_load_balancer_set_name(lb->slb, lb->nlb->name);
> >          sbrec_load_balancer_set_vips(lb->slb, &lb->nlb->vips);
> >          sbrec_load_balancer_set_protocol(lb->slb, lb->nlb->protocol);
> > -        sbrec_load_balancer_set_options(lb->slb, &lb->nlb->options);
> > +        sbrec_load_balancer_set_options(lb->slb, &options);
> >          sbrec_load_balancer_set_datapaths(
> >              lb->slb, (struct sbrec_datapath_binding **)lb->dps,
> >              lb->n_dps);
> > +        smap_destroy(&options);
> >      }
> >
> >      /* Set the list of associated load balanacers to a logical switch
> > @@ -5864,11 +5893,20 @@ build_lb_rules(struct ovn_datapath *od, struct hmap 
> > *lflows,
> >          struct ovn_lb_vip *lb_vip = &lb->vips[i];
> >          struct ovn_northd_lb_vip *lb_vip_nb = &lb->vips_nb[i];
> >
> > +        struct ds action = DS_EMPTY_INITIALIZER;
> >          const char *ip_match = NULL;
> > +
> > +        /* Store the original destination IP to be used when generating
> > +         * hairpin flows.
> > +         */
> >          if (IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)) {
> >              ip_match = "ip4";
> > +            ds_put_format(&action, REG_ORIG_DIP_IPV4 " = %s; ",
> > +                          lb_vip->vip_str);
> >          } else {
> >              ip_match = "ip6";
> > +            ds_put_format(&action, REG_ORIG_DIP_IPV6 " = %s; ",
> > +                          lb_vip->vip_str);
> >          }
> >
> >          const char *proto = NULL;
> > @@ -5881,10 +5919,15 @@ build_lb_rules(struct ovn_datapath *od, struct hmap 
> > *lflows,
> >                      proto = "sctp";
> >                  }
> >              }
> > +
> > +            /* Store the original destination port to be used when 
> > generating
> > +             * hairpin flows.
> > +             */
> > +            ds_put_format(&action, REG_ORIG_TP_DPORT " = %"PRIu16"; ",
> > +                          lb_vip->vip_port);
> >          }
> >
> >          /* New connections in Ingress table. */
> > -        struct ds action = DS_EMPTY_INITIALIZER;
> >          build_lb_vip_actions(lb_vip, lb_vip_nb, &action,
> >                               lb->selection_fields, true);
> >
> > @@ -5932,9 +5975,39 @@ build_stateful(struct ovn_datapath *od, struct hmap 
> > *lflows, struct hmap *lbs)
> >       * REGBIT_CONNTRACK_COMMIT is set for new connections and
> >       * REGBIT_CONNTRACK_NAT is set for established connections. So they
> >       * don't overlap.
> > +     *
> > +     * In the ingress pipeline, also store the original destination IP and
> > +     * transport port to be used when detecting hairpin packets.
> >       */
> > -    ovn_lflow_add(lflows, od, S_SWITCH_IN_STATEFUL, 100,
> > -                  REGBIT_CONNTRACK_NAT" == 1", "ct_lb;");
> > +    const char *lb_protocols[] = {"tcp", "udp", "sctp"};
> > +    struct ds actions = DS_EMPTY_INITIALIZER;
> > +    struct ds match = DS_EMPTY_INITIALIZER;
> > +
> > +    for (size_t i = 0; i < ARRAY_SIZE(lb_protocols); i++) {
> > +        ds_clear(&match);
> > +        ds_clear(&actions);
> > +        ds_put_format(&match, REGBIT_CONNTRACK_NAT" == 1 && ip4 && %s",
> > +                      lb_protocols[i]);
> > +        ds_put_format(&actions, REG_ORIG_DIP_IPV4 " = ip4.dst; "
> > +                                REG_ORIG_TP_DPORT " = %s.dst; ct_lb;",
> > +                      lb_protocols[i]);
> > +        ovn_lflow_add(lflows, od, S_SWITCH_IN_STATEFUL, 100,
> > +                      ds_cstr(&match), ds_cstr(&actions));
> > +
> > +        ds_clear(&match);
> > +        ds_clear(&actions);
> > +        ds_put_format(&match, REGBIT_CONNTRACK_NAT" == 1 && ip6 && %s",
> > +                      lb_protocols[i]);
> > +        ds_put_format(&actions, REG_ORIG_DIP_IPV6 " = ip6.dst; "
> > +                                REG_ORIG_TP_DPORT " = %s.dst; ct_lb;",
> > +                      lb_protocols[i]);
> > +        ovn_lflow_add(lflows, od, S_SWITCH_IN_STATEFUL, 100,
> > +                      ds_cstr(&match), ds_cstr(&actions));
> > +    }
> > +
> > +    ds_destroy(&actions);
> > +    ds_destroy(&match);
> > +
> >      ovn_lflow_add(lflows, od, S_SWITCH_OUT_STATEFUL, 100,
> >                    REGBIT_CONNTRACK_NAT" == 1", "ct_lb;");
> >
> > diff --git a/ovn-sb.xml b/ovn-sb.xml
> > index 35000ed..30752c3 100644
> > --- a/ovn-sb.xml
> > +++ b/ovn-sb.xml
> > @@ -4306,6 +4306,12 @@ tcp.flags = RST;
> >        load balancing.  This value is automatically populated by
> >        <code>ovn-northd</code>.
> >      </column>
> > +    <column name="options" key="hairpin_orig_tuple">
> You can also add - type='{"type": "boolean"}'
>
> Thanks
> Numan
>
> > +      This value is automatically set to <code>true</code> by
> > +      <code>ovn-northd</code> when original destination IP and transport 
> > port
> > +      of the load balanced packets are stored in registers
> > +      <code>reg1, reg2, xxreg1</code>.
> > +    </column>
> >      </group>
> >
> >      <group title="Common Columns">
> > diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at
> > index ff65d60..3d7ac08 100644
> > --- a/tests/ofproto-macros.at
> > +++ b/tests/ofproto-macros.at
> > @@ -40,7 +40,7 @@ s/dir\/[0-9]*\/br0.mgmt/dir\/XXXX\/br0.mgmt/
> >  # Strips out uninteresting parts of ovs-ofctl output, including 
> > n_packets=..
> >  # n_bytes=..
> >  ofctl_strip_all () {
> > -    ofctl_strip | strip_n_packets | strip_n_bytes | strip_cookie
> > +    ofctl_strip | strip_n_packets | strip_n_bytes | strip_cookie | sort
> >  }
> >
> >  # Filter (multiline) vconn debug messages from ovs-vswitchd.log.
> > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> > index ad0f9f5..379d279 100644
> > --- a/tests/ovn-northd.at
> > +++ b/tests/ovn-northd.at
> > @@ -1078,7 +1078,7 @@ check ovn-nbctl --wait=sb ls-lb-add sw0 lb1
> >  AT_CAPTURE_FILE([sbflows])
> >  OVS_WAIT_FOR_OUTPUT(
> >    [ovn-sbctl dump-flows sw0 | tee sbflows | grep 'priority=120.*ct_lb' | 
> > sed 's/table=..//'], 0, [dnl
> > -  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), 
> > action=(ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> > +  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; 
> > ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> >  ])
> >
> >  AS_BOX([Delete the Load_Balancer_Health_Check])
> > @@ -1088,7 +1088,7 @@ wait_row_count Service_Monitor 0
> >  AT_CAPTURE_FILE([sbflows2])
> >  OVS_WAIT_FOR_OUTPUT(
> >    [ovn-sbctl dump-flows sw0 | tee sbflows2 | grep 'priority=120.*ct_lb' | 
> > sed 's/table=..//'], [0],
> > -[  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), 
> > action=(ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> > +[  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; 
> > ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> >  ])
> >
> >  AS_BOX([Create the Load_Balancer_Health_Check again.])
> > @@ -1100,7 +1100,7 @@ check ovn-nbctl --wait=sb sync
> >
> >  ovn-sbctl dump-flows sw0 | grep ct_lb | grep priority=120 > lflows.txt
> >  AT_CHECK([cat lflows.txt | sed 's/table=..//'], [0], [dnl
> > -  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), 
> > action=(ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> > +  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; 
> > ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> >  ])
> >
> >  AS_BOX([Get the uuid of both the service_monitor])
> > @@ -1110,7 +1110,7 @@ sm_sw1_p1=$(fetch_column Service_Monitor _uuid 
> > logical_port=sw1-p1)
> >  AT_CAPTURE_FILE([sbflows3])
> >  OVS_WAIT_FOR_OUTPUT(
> >    [ovn-sbctl dump-flows sw0 | tee sbflows 3 | grep 'priority=120.*ct_lb' | 
> > sed 's/table=..//'], [0],
> > -[  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), 
> > action=(ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> > +[  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; 
> > ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> >  ])
> >
> >  AS_BOX([Set the service monitor for sw1-p1 to offline])
> > @@ -1121,7 +1121,7 @@ check ovn-nbctl --wait=sb sync
> >  AT_CAPTURE_FILE([sbflows4])
> >  OVS_WAIT_FOR_OUTPUT(
> >    [ovn-sbctl dump-flows sw0 | tee sbflows4 | grep 'priority=120.*ct_lb' | 
> > sed 's/table=..//'], [0],
> > -[  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80);)
> > +[  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; 
> > ct_lb(backends=10.0.0.3:80);)
> >  ])
> >
> >  AS_BOX([Set the service monitor for sw0-p1 to offline])
> > @@ -1150,7 +1150,7 @@ check ovn-nbctl --wait=sb sync
> >  AT_CAPTURE_FILE([sbflows7])
> >  OVS_WAIT_FOR_OUTPUT(
> >    [ovn-sbctl dump-flows sw0 | tee sbflows7 | grep ct_lb | grep 
> > priority=120 | sed 's/table=..//'], 0,
> > -[  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), 
> > action=(ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> > +[  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; 
> > ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> >  ])
> >
> >  AS_BOX([Set the service monitor for sw1-p1 to error])
> > @@ -1161,7 +1161,7 @@ check ovn-nbctl --wait=sb sync
> >  ovn-sbctl dump-flows sw0 | grep "ip4.dst == 10.0.0.10 && tcp.dst == 80" \
> >  | grep priority=120 > lflows.txt
> >  AT_CHECK([cat lflows.txt | sed 's/table=..//'], [0], [dnl
> > -  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80);)
> > +  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; 
> > ct_lb(backends=10.0.0.3:80);)
> >  ])
> >
> >  AS_BOX([Add one more vip to lb1])
> > @@ -1187,8 +1187,8 @@ AT_CAPTURE_FILE([sbflows9])
> >  OVS_WAIT_FOR_OUTPUT(
> >    [ovn-sbctl dump-flows sw0 | tee sbflows9 | grep ct_lb | grep 
> > priority=120 | sed 's/table=..//' | sort],
> >    0,
> > -[  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80);)
> > -  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.40 && tcp.dst == 1000), action=(ct_lb(backends=10.0.0.3:1000);)
> > +[  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; 
> > ct_lb(backends=10.0.0.3:80);)
> > +  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.40 && tcp.dst == 1000), action=(reg1 = 10.0.0.40; reg2[[0..15]] = 
> > 1000; ct_lb(backends=10.0.0.3:1000);)
> >  ])
> >
> >  AS_BOX([Set the service monitor for sw1-p1 to online])
> > @@ -1201,8 +1201,8 @@ AT_CAPTURE_FILE([sbflows10])
> >  OVS_WAIT_FOR_OUTPUT(
> >    [ovn-sbctl dump-flows sw0 | tee sbflows10 | grep ct_lb | grep 
> > priority=120 | sed 's/table=..//' | sort],
> >    0,
> > -[  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), 
> > action=(ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> > -  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.40 && tcp.dst == 1000), 
> > action=(ct_lb(backends=10.0.0.3:1000,20.0.0.3:80);)
> > +[  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; 
> > ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> > +  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.40 && tcp.dst == 1000), action=(reg1 = 10.0.0.40; reg2[[0..15]] = 
> > 1000; ct_lb(backends=10.0.0.3:1000,20.0.0.3:80);)
> >  ])
> >
> >  AS_BOX([Associate lb1 to sw1])
> > @@ -1211,8 +1211,8 @@ AT_CAPTURE_FILE([sbflows11])
> >  OVS_WAIT_FOR_OUTPUT(
> >    [ovn-sbctl dump-flows sw1 | tee sbflows11 | grep ct_lb | grep 
> > priority=120 | sed 's/table=..//' | sort],
> >    0, [dnl
> > -  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), 
> > action=(ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> > -  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.40 && tcp.dst == 1000), 
> > action=(ct_lb(backends=10.0.0.3:1000,20.0.0.3:80);)
> > +  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; 
> > ct_lb(backends=10.0.0.3:80,20.0.0.3:80);)
> > +  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.40 && tcp.dst == 1000), action=(reg1 = 10.0.0.40; reg2[[0..15]] = 
> > 1000; ct_lb(backends=10.0.0.3:1000,20.0.0.3:80);)
> >  ])
> >
> >  AS_BOX([Now create lb2 same as lb1 but udp protocol.])
> > @@ -2176,7 +2176,7 @@ check_column "$lb0_uuid $lb1_uuid" 
> > sb:datapath_binding load_balancers external_i
> >  echo
> >  echo "__file__:__line__: Set hairpin_snat_ip on lb1 and check that SB DB 
> > is updated."
> >  check ovn-nbctl --wait=sb set Load_Balancer lb1 
> > options:hairpin_snat_ip="42.42.42.42 4242::4242"
> > -check_column "$lb1_uuid" sb:load_balancer _uuid name=lb1 
> > options='{hairpin_snat_ip="42.42.42.42 4242::4242"}'
> > +check_column "$lb1_uuid" sb:load_balancer _uuid name=lb1 
> > options='{hairpin_orig_tuple="true", hairpin_snat_ip="42.42.42.42 
> > 4242::4242"}'
> >
> >  echo
> >  echo "__file__:__line__: Delete load balancer lb1 an check that datapath 
> > sw1's load_balancers are updated accordingly."
> > diff --git a/tests/ovn.at b/tests/ovn.at
> > index 737c109..b061f88 100644
> > --- a/tests/ovn.at
> > +++ b/tests/ovn.at
> > @@ -19776,7 +19776,7 @@ AT_CAPTURE_FILE([sbflows])
> >  OVS_WAIT_FOR_OUTPUT(
> >    [ovn-sbctl dump-flows > sbflows
> >     ovn-sbctl dump-flows sw0 | grep ct_lb | grep priority=120 | sed 
> > 's/table=..//'], 0,
> > -  [  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), 
> > action=(ct_lb(backends=10.0.0.3:80,20.0.0.3:80; 
> > hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");)
> > +  [  (ls_in_stateful     ), priority=120  , match=(ct.new && ip4.dst == 
> > 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; 
> > ct_lb(backends=10.0.0.3:80,20.0.0.3:80; 
> > hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");)
> >  ])
> >
> >  AT_CAPTURE_FILE([sbflows2])
> > @@ -20967,16 +20967,26 @@ ovs-vsctl -- add-port br-int hv1-vif1 -- \
> >
> >  # One logical switch with IPv4 and IPv6 load balancers that hairpin the
> >  # traffic.
> > +# Also create "duplicate" load balancers, i.e., different VIPs using the 
> > same
> > +# backends.
> >  ovn-nbctl ls-add sw
> >  ovn-nbctl lsp-add sw lsp -- lsp-set-addresses lsp 00:00:00:00:00:01
> > -ovn-nbctl lb-add lb-ipv4-tcp 88.88.88.88:8080 42.42.42.1:4041 tcp
> > -ovn-nbctl lb-add lb-ipv4-udp 88.88.88.88:4040 42.42.42.1:2021 udp
> > -ovn-nbctl lb-add lb-ipv6-tcp [[8800::0088]]:8080 [[4200::1]]:4041 tcp
> > -ovn-nbctl lb-add lb-ipv6-udp [[8800::0088]]:4040 [[4200::1]]:2021 udp
> > +ovn-nbctl lb-add lb-ipv4-tcp     88.88.88.88:8080 42.42.42.1:4041 tcp
> > +ovn-nbctl lb-add lb-ipv4-tcp-dup 88.88.88.89:8080 42.42.42.1:4041 tcp
> > +ovn-nbctl lb-add lb-ipv4-udp     88.88.88.88:4040 42.42.42.1:2021 udp
> > +ovn-nbctl lb-add lb-ipv4-udp-dup 88.88.88.89:4040 42.42.42.1:2021 udp
> > +ovn-nbctl lb-add lb-ipv6-tcp     [[8800::0088]]:8080 [[4200::1]]:4041 tcp
> > +ovn-nbctl lb-add lb-ipv6-tcp-dup [[8800::0089]]:8080 [[4200::1]]:4041 tcp
> > +ovn-nbctl lb-add lb-ipv6-udp     [[8800::0088]]:4040 [[4200::1]]:2021 udp
> > +ovn-nbctl lb-add lb-ipv6-udp-dup [[8800::0089]]:4040 [[4200::1]]:2021 udp
> >  ovn-nbctl ls-lb-add sw lb-ipv4-tcp
> > +ovn-nbctl ls-lb-add sw lb-ipv4-tcp-dup
> >  ovn-nbctl ls-lb-add sw lb-ipv4-udp
> > +ovn-nbctl ls-lb-add sw lb-ipv4-udp-dup
> >  ovn-nbctl ls-lb-add sw lb-ipv6-tcp
> > +ovn-nbctl ls-lb-add sw lb-ipv6-tcp-dup
> >  ovn-nbctl ls-lb-add sw lb-ipv6-udp
> > +ovn-nbctl ls-lb-add sw lb-ipv6-udp-dup
> >
> >  ovn-nbctl lr-add rtr
> >  ovn-nbctl lrp-add rtr rtr-sw 00:00:00:00:01:00 42.42.42.254/24 
> > 4200::00ff/64
> > @@ -20994,7 +21004,7 @@ AT_CAPTURE_FILE([sbflows])
> >
> >  AS_BOX([IPv4 TCP Hairpin])
> >
> > -# Inject IPv4 TCP packet from lsp.
> > +# Inject IPv4 TCP packets from lsp.
> >  tcp_payload=$(build_tcp_syn 84d0 1f90 05a7)
> >  hp_tcp_payload=$(build_tcp_syn 84d0 0fc9 156e)
> >  send_ipv4_pkt hv1 hv1-vif1 000000000001 000000000100 \
> > @@ -21004,12 +21014,22 @@ send_ipv4_pkt hv1 hv1-vif1 000000000001 
> > 000000000100 \
> >      $(ip_to_hex 88 88 88 88) ${hp_tcp_payload} \
> >      expected
> >
> > +tcp_payload=$(build_tcp_syn 84d1 1f90 05a5)
> > +hp_tcp_payload=$(build_tcp_syn 84d1 0fc9 156c)
> > +send_ipv4_pkt hv1 hv1-vif1 000000000001 000000000100 \
> > +    $(ip_to_hex 42 42 42 1) $(ip_to_hex 88 88 88 89) \
> > +    06 0028 \
> > +    ${tcp_payload} \
> > +    $(ip_to_hex 88 88 88 89) ${hp_tcp_payload} \
> > +    expected
> > +
> >  # Check that traffic is hairpinned.
> >  OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
> >
> >  # Check learned hairpin reply flows.
> >  OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=69 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> >   table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.88,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >  ])
> >
> >  # Change LB Hairpin SNAT IP.
> > @@ -21017,7 +21037,8 @@ OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows 
> > br-int table=69 | ofctl_strip_a
> >  as hv1 ovs-appctl dpctl/flush-conntrack
> >
> >  ovn-nbctl --wait=hv set load_balancer lb-ipv4-tcp 
> > options:hairpin_snat_ip="88.88.88.87"
> > -# Inject IPv4 TCP packet from lsp.
> > +# Inject IPv4 TCP packets from lsp.
> > +tcp_payload=$(build_tcp_syn 84d0 1f90 05a7)
> >  hp_tcp_payload=$(build_tcp_syn 84d0 0fc9 156f)
> >  send_ipv4_pkt hv1 hv1-vif1 000000000001 000000000100 \
> >      $(ip_to_hex 42 42 42 1) $(ip_to_hex 88 88 88 88) \
> > @@ -21026,17 +21047,27 @@ send_ipv4_pkt hv1 hv1-vif1 000000000001 
> > 000000000100 \
> >      $(ip_to_hex 88 88 88 87) ${hp_tcp_payload} \
> >      expected
> >
> > +tcp_payload=$(build_tcp_syn 84d1 1f90 05a5)
> > +hp_tcp_payload=$(build_tcp_syn 84d1 0fc9 156c)
> > +send_ipv4_pkt hv1 hv1-vif1 000000000001 000000000100 \
> > +    $(ip_to_hex 42 42 42 1) $(ip_to_hex 88 88 88 89) \
> > +    06 0028 \
> > +    ${tcp_payload} \
> > +    $(ip_to_hex 88 88 88 89) ${hp_tcp_payload} \
> > +    expected
> > +
> >  # Check that traffic is hairpinned.
> >  OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
> >
> >  # Check learned hairpin reply flows.
> >  OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=69 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> >   table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >  ])
> >
> >  AS_BOX([IPv4 UDP Hairpin])
> >
> > -# Inject IPv4 UDP packet from lsp.
> > +# Inject IPv4 UDP packets from lsp.
> >  udp_payload=$(build_udp 84d0 0fc8 6666)
> >  hp_udp_payload=$(build_udp 84d0 07e5 6e49)
> >  send_ipv4_pkt hv1 hv1-vif1 000000000001 000000000100 \
> > @@ -21046,20 +21077,32 @@ send_ipv4_pkt hv1 hv1-vif1 000000000001 
> > 000000000100 \
> >      $(ip_to_hex 88 88 88 88) ${hp_udp_payload} \
> >      expected
> >
> > +udp_payload=$(build_udp 84d1 0fc8 6664)
> > +hp_udp_payload=$(build_udp 84d1 07e5 6e47)
> > +send_ipv4_pkt hv1 hv1-vif1 000000000001 000000000100 \
> > +    $(ip_to_hex 42 42 42 1) $(ip_to_hex 88 88 88 89) \
> > +    11 001e \
> > +    ${udp_payload} \
> > +    $(ip_to_hex 88 88 88 89) ${hp_udp_payload} \
> > +    expected
> > +
> >  # Check that traffic is hairpinned.
> >  OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
> >
> >  # Check learned hairpin reply flows.
> >  OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=69 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> >   table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >   table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.88,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >  ])
> >
> >  # Change LB Hairpin SNAT IP.
> >  # Also flush conntrack to avoid reusing an existing entry.
> >  as hv1 ovs-appctl dpctl/flush-conntrack
> >  ovn-nbctl --wait=hv set load_balancer lb-ipv4-udp 
> > options:hairpin_snat_ip="88.88.88.87"
> > -# Inject IPv4 UDP packet from lsp.
> > +# Inject IPv4 UDP packets from lsp.
> > +udp_payload=$(build_udp 84d0 0fc8 6666)
> >  hp_udp_payload=$(build_udp 84d0 07e5 6e4a)
> >  send_ipv4_pkt hv1 hv1-vif1 000000000001 000000000100 \
> >      $(ip_to_hex 42 42 42 1) $(ip_to_hex 88 88 88 88) \
> > @@ -21068,18 +21111,29 @@ send_ipv4_pkt hv1 hv1-vif1 000000000001 
> > 000000000100 \
> >      $(ip_to_hex 88 88 88 87) ${hp_udp_payload} \
> >      expected
> >
> > +udp_payload=$(build_udp 84d1 0fc8 6664)
> > +hp_udp_payload=$(build_udp 84d1 07e5 6e47)
> > +send_ipv4_pkt hv1 hv1-vif1 000000000001 000000000100 \
> > +    $(ip_to_hex 42 42 42 1) $(ip_to_hex 88 88 88 89) \
> > +    11 001e \
> > +    ${udp_payload} \
> > +    $(ip_to_hex 88 88 88 89) ${hp_udp_payload} \
> > +    expected
> > +
> >  # Check that traffic is hairpinned.
> >  OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
> >
> >  # Check learned hairpin reply flows.
> >  OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=69 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> >   table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >   table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >  ])
> >
> >  AS_BOX([IPv6 TCP Hairpin])
> >
> > -# Inject IPv6 TCP packet from lsp.
> > +# Inject IPv6 TCP packets from lsp.
> >  tcp_payload=$(build_tcp_syn 84d0 1f90 3ff9)
> >  hp_tcp_payload=$(build_tcp_syn 84d0 0fc9 4fc0)
> >  send_ipv6_pkt hv1 hv1-vif1 000000000001 000000000100 \
> > @@ -21089,14 +21143,26 @@ send_ipv6_pkt hv1 hv1-vif1 000000000001 
> > 000000000100 \
> >      88000000000000000000000000000088 ${hp_tcp_payload} \
> >      expected
> >
> > +tcp_payload=$(build_tcp_syn 84d1 1f90 3ff7)
> > +hp_tcp_payload=$(build_tcp_syn 84d1 0fc9 4fbe)
> > +send_ipv6_pkt hv1 hv1-vif1 000000000001 000000000100 \
> > +    42000000000000000000000000000001 88000000000000000000000000000089 \
> > +    06 0014 \
> > +    ${tcp_payload} \
> > +    88000000000000000000000000000089 ${hp_tcp_payload} \
> > +    expected
> > +
> >  # Check that traffic is hairpinned.
> >  OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
> >
> >  # Check learned hairpin reply flows.
> >  OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=69 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> >   table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > - table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >   table=69, 
> > tcp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::88,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >  ])
> >
> >  # Change LB Hairpin SNAT IP.
> > @@ -21104,7 +21170,8 @@ OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows 
> > br-int table=69 | ofctl_strip_a
> >  as hv1 ovs-appctl dpctl/flush-conntrack
> >  ovn-nbctl --wait=hv set load_balancer lb-ipv6-tcp 
> > options:hairpin_snat_ip="8800::0087"
> >
> > -# Inject IPv6 TCP packet from lsp.
> > +# Inject IPv6 TCP packets from lsp.
> > +tcp_payload=$(build_tcp_syn 84d0 1f90 3ff9)
> >  hp_tcp_payload=$(build_tcp_syn 84d0 0fc9 4fc1)
> >  send_ipv6_pkt hv1 hv1-vif1 000000000001 000000000100 \
> >      42000000000000000000000000000001 88000000000000000000000000000088 \
> > @@ -21113,19 +21180,31 @@ send_ipv6_pkt hv1 hv1-vif1 000000000001 
> > 000000000100 \
> >      88000000000000000000000000000087 ${hp_tcp_payload} \
> >      expected
> >
> > +tcp_payload=$(build_tcp_syn 84d1 1f90 3ff7)
> > +hp_tcp_payload=$(build_tcp_syn 84d1 0fc9 4fbe)
> > +send_ipv6_pkt hv1 hv1-vif1 000000000001 000000000100 \
> > +    42000000000000000000000000000001 88000000000000000000000000000089 \
> > +    06 0014 \
> > +    ${tcp_payload} \
> > +    88000000000000000000000000000089 ${hp_tcp_payload} \
> > +    expected
> > +
> >  # Check that traffic is hairpinned.
> >  OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
> >
> >  # Check learned hairpin reply flows.
> >  OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=69 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> >   table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > - table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >   table=69, 
> > tcp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::87,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >  ])
> >
> >  AS_BOX([IPv6 UDP Hairpin])
> >
> > -# Inject IPv6 UDP packet from lsp.
> > +# Inject IPv6 UDP packets from lsp.
> >  udp_payload=$(build_udp 84d0 0fc8 a0b8)
> >  hp_udp_payload=$(build_udp 84d0 07e5 a89b)
> >  send_ipv6_pkt hv1 hv1-vif1 000000000001 000000000100 \
> > @@ -21135,15 +21214,28 @@ send_ipv6_pkt hv1 hv1-vif1 000000000001 
> > 000000000100 \
> >      88000000000000000000000000000088 ${hp_udp_payload} \
> >      expected
> >
> > +udp_payload=$(build_udp 84d1 0fc8 a0b6)
> > +hp_udp_payload=$(build_udp 84d1 07e5 a899)
> > +send_ipv6_pkt hv1 hv1-vif1 000000000001 000000000100 \
> > +    42000000000000000000000000000001 88000000000000000000000000000089 \
> > +    11 000a \
> > +    ${udp_payload} \
> > +    88000000000000000000000000000089 ${hp_udp_payload} \
> > +    expected
> > +
> >  # Check that traffic is hairpinned.
> >  OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
> >
> >  # Check learned hairpin reply flows.
> >  OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=69 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> >   table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > - table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >   table=69, 
> > tcp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::87,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >   table=69, 
> > udp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::88,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::89,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >  ])
> >
> >  # Change LB Hairpin SNAT IP.
> > @@ -21151,7 +21243,8 @@ OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows 
> > br-int table=69 | ofctl_strip_a
> >  as hv1 ovs-appctl dpctl/flush-conntrack
> >  ovn-nbctl --wait=hv set load_balancer lb-ipv6-udp 
> > options:hairpin_snat_ip="8800::0087"
> >
> > -# Inject IPv6 UDP packet from lsp.
> > +# Inject IPv6 UDP packets from lsp.
> > +udp_payload=$(build_udp 84d0 0fc8 a0b8)
> >  hp_udp_payload=$(build_udp 84d0 07e5 a89b)
> >  send_ipv6_pkt hv1 hv1-vif1 000000000001 000000000100 \
> >      42000000000000000000000000000001 88000000000000000000000000000088 \
> > @@ -21160,38 +21253,64 @@ send_ipv6_pkt hv1 hv1-vif1 000000000001 
> > 000000000100 \
> >      88000000000000000000000000000087 ${hp_udp_payload} \
> >      expected
> >
> > +udp_payload=$(build_udp 84d1 0fc8 a0b6)
> > +hp_udp_payload=$(build_udp 84d1 07e5 a899)
> > +send_ipv6_pkt hv1 hv1-vif1 000000000001 000000000100 \
> > +    42000000000000000000000000000001 88000000000000000000000000000089 \
> > +    11 000a \
> > +    ${udp_payload} \
> > +    88000000000000000000000000000089 ${hp_udp_payload} \
> > +    expected
> > +
> >  # Check learned hairpin reply flows.
> >  OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=69 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> >   table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > - table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >   table=69, 
> > tcp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::87,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >   table=69, 
> > udp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::89,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >  ])
> >
> >  AS_BOX([Delete VIP])
> >  check ovn-nbctl --wait=hv set Load_Balancer lb-ipv4-tcp 
> > vips='"88.88.88.88:8080"=""'
> >  OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=69 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> > - table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >   table=69, 
> > tcp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::87,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp,metadata=0x1,nw_src=42.42.42.1,nw_dst=88.88.88.89,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >   table=69, 
> > udp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::89,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >  ])
> >
> >  AS_BOX([Delete LB])
> > -check ovn-nbctl --wait=hv \
> > -    -- lb-del lb-ipv4-tcp \
> > -    -- lb-del lb-ipv4-udp
> > +check ovn-nbctl --wait=hv     \
> > +    -- lb-del lb-ipv4-tcp     \
> > +    -- lb-del lb-ipv4-tcp-dup \
> > +    -- lb-del lb-ipv4-udp     \
> > +    -- lb-del lb-ipv4-udp-dup
> >
> >  OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=69 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> >   table=69, 
> > tcp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::87,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > tcp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::89,tp_src=4041 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >   table=69, 
> > udp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::89,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >  ])
> >
> > -check ovn-nbctl --wait=hv lb-del lb-ipv6-tcp
> > +check ovn-nbctl --wait=hv     \
> > +    -- lb-del lb-ipv6-tcp     \
> > +    -- lb-del lb-ipv6-tcp-dup
> >  OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=69 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> >   table=69, 
> > udp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::87,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> > + table=69, 
> > udp6,metadata=0x1,ipv6_src=4200::1,ipv6_dst=8800::89,tp_src=2021 
> > actions=load:0x1->NXM_NX_REG10[[7]]
> >  ])
> >
> > -check ovn-nbctl --wait=hv lb-del lb-ipv6-udp
> > +check ovn-nbctl --wait=hv     \
> > +    -- lb-del lb-ipv6-udp     \
> > +    -- lb-del lb-ipv6-udp-dup
> >  OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=69 | 
> > ofctl_strip_all | grep -v NXST], [1], [dnl
> >  ])
> >
> > @@ -23572,15 +23691,15 @@ OVS_WAIT_UNTIL(
> >      [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) 
> > -eq 1]
> >  )
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> >  ])
> >
> >  AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69], [0], [dnl
> >  NXST_FLOW reply (xid=0x8):
> >  ])
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> >  ])
> >
> > @@ -23599,17 +23718,17 @@ OVS_WAIT_UNTIL(
> >      [test $(as hv1 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) 
> > -eq 3]
> >  )
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> >  ])
> >
> >  AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69], [0], [dnl
> >  NXST_FLOW reply (xid=0x8):
> >  ])
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90))
> >  ])
> > @@ -23631,16 +23750,16 @@ OVS_WAIT_UNTIL(
> >      [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) 
> > -eq 3]
> >  )
> >
> > -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> >  ])
> >
> >  AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], 
> > [1], [dnl
> >  ])
> >
> > -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90))
> >  ])
> > @@ -23655,33 +23774,33 @@ OVS_WAIT_UNTIL(
> >      [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) 
> > -eq 4]
> >  )
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> >  ])
> >
> >  AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], 
> > [1], [dnl
> >  ])
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90))
> >  ])
> >
> > -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> >  ])
> >
> >  AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], 
> > [1], [dnl
> >  ])
> >
> > -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90))
> > @@ -23697,36 +23816,36 @@ OVS_WAIT_UNTIL(
> >      [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) 
> > -eq 5]
> >  )
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> >  ])
> >
> >  AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], 
> > [1], [dnl
> >  ])
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90))
> >  ])
> >
> > -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> >  ])
> >
> >  AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], 
> > [1], [dnl
> >  ])
> >
> > -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> > @@ -23743,19 +23862,19 @@ OVS_WAIT_UNTIL(
> >      [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) 
> > -eq 6]
> >  )
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> >  ])
> >
> >  AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], 
> > [1], [dnl
> >  ])
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> > @@ -23763,19 +23882,19 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int 
> > table=70 | ofctl_strip_all | grep -
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90))
> >  ])
> >
> > -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> >  ])
> >
> >  AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], 
> > [1], [dnl
> >  ])
> >
> > -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> > @@ -23795,19 +23914,40 @@ OVS_WAIT_UNTIL(
> >      [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) 
> > -eq 6]
> >  )
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +])
> > +
> > +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], 
> > [1], [dnl
> > +])
> > +
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> > + table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,metadata=0x2
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> > + table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> > + table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> > + table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> > + table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90))
> > +])
> > +
> > +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x58585858,reg2=0x1f90/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,reg1=0x5858585a,reg2=0x1f90/0xffff,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> >  ])
> >
> >  AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], 
> > [1], [dnl
> >  ])
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,metadata=0x2
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> > @@ -23816,19 +23956,53 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int 
> > table=70 | ofctl_strip_all | grep -
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90))
> >  ])
> >
> > -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +# Check backwards compatibility with ovn-northd versions that don't store 
> > the
> > +# original destination tuple.
> > +#
> > +# ovn-controller should fall back to matching on ct_nw_dst()/ct_tp_dst().
> > +as northd-backup ovn-appctl -t ovn-northd pause
> > +as northd ovn-appctl -t ovn-northd pause
> > +
> > +check ovn-sbctl \
> > +    -- remove load_balancer lb-ipv4-tcp options hairpin_orig_tuple \
> > +    -- remove load_balancer lb-ipv6-tcp options hairpin_orig_tuple \
> > +    -- remove load_balancer lb-ipv4-udp options hairpin_orig_tuple \
> > +    -- remove load_balancer lb-ipv6-udp options hairpin_orig_tuple
> > +
> > +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=68 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_state=+trk+dnat,ct_label=0x2/0x2,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_state=+trk+dnat,ct_label=0x2/0x2,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_state=+trk+dnat,ct_label=0x2/0x2,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_state=+trk+dnat,ct_label=0x2/0x2,ct_nw_dst=88.88.88.88,ct_nw_proto=6,ct_tp_dst=8080,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_state=+trk+dnat,ct_label=0x2/0x2,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_state=+trk+dnat,ct_label=0x2/0x2,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +])
> > +
> > +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], 
> > [1], [dnl
> > +])
> > +
> > +OVS_WAIT_FOR_OUTPUT([as hv1 ovs-ofctl dump-flows br-int table=70 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> > + table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> > + table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,metadata=0x2
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> > + table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> > + table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> > + table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.88,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.88))
> > + table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90))
> > +])
> > +
> > +OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=68 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_state=+trk+dnat,ct_label=0x2/0x2,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_state=+trk+dnat,ct_label=0x2/0x2,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_state=+trk+dnat,ct_label=0x2/0x2,ct_nw_dst=88.88.88.88,ct_nw_proto=17,ct_tp_dst=4040,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_state=+trk+dnat,ct_label=0x2/0x2,ct_nw_dst=88.88.88.88,ct_nw_proto=6,ct_tp_dst=8080,tcp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_state=+trk+dnat,ct_label=0x2/0x2,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,nw_src=42.42.42.42,nw_dst=42.42.42.42,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_state=+trk+dnat,ct_label=0x2/0x2,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,nw_src=52.52.52.52,nw_dst=52.52.52.52,tp_dst=4042
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.90,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> >  ])
> >
> >  AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69 | grep -v NXST], 
> > [1], [dnl
> >  ])
> >
> > -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > +OVS_WAIT_FOR_OUTPUT([as hv2 ovs-ofctl dump-flows br-int table=70 | 
> > ofctl_strip_all | grep -v NXST], [0], [dnl
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,metadata=0x2
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> > @@ -23837,6 +24011,11 @@ AT_CHECK([as hv2 ovs-ofctl dump-flows br-int 
> > table=70 | ofctl_strip_all | grep -
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_nw_dst=88.88.88.90,ct_nw_proto=6,ct_tp_dst=8080,tcp,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=88.88.88.90))
> >  ])
> >
> > +# Resume ovn-northd.
> > +as northd ovn-appctl -t ovn-northd resume
> > +as northd-backup ovn-appctl -t ovn-northd resume
> > +check ovn-nbctl --wait=hv sync
> > +
> >  as hv2 ovs-vsctl del-port hv2-vif1
> >  OVS_WAIT_UNTIL([test x$(ovn-nbctl lsp-get-up sw0-p2) = xdown])
> >
> > @@ -23869,17 +24048,17 @@ OVS_WAIT_UNTIL(
> >      [test $(as hv2 ovs-ofctl dump-flows br-int table=68 | grep -c -v NXST) 
> > -eq 0]
> >  )
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > - table=68, 
> > priority=100,ct_label=0x2/0x2,udp6,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=68 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,tcp6,reg2=0x1f90/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=4041
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=6,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp,reg1=0x58585858,reg2=0xfc8/0xffff,nw_src=42.42.42.1,nw_dst=42.42.42.1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],ip_dst=88.88.88.88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> > + table=68, 
> > priority=100,ct_label=0x2/0x2,udp6,reg2=0xfc8/0xffff,reg4=0x88000000,reg5=0,reg6=0,reg7=0x88,ipv6_src=4200::1,ipv6_dst=4200::1,tp_dst=2021
> >  
> > actions=load:0x1->NXM_NX_REG10[[7]],learn(table=69,delete_learned,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],ipv6_dst=8800::88,nw_proto=17,NXM_OF_UDP_SRC[[]]=NXM_OF_UDP_DST[[]],load:0x1->NXM_NX_REG10[[7]])
> >  ])
> >
> >  AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=69], [0], [dnl
> >  NXST_FLOW reply (xid=0x8):
> >  ])
> >
> > -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST | sort], [0], [dnl
> > +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=70 | ofctl_strip_all | 
> > grep -v NXST], [0], [dnl
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=17,ct_tp_dst=4040,udp6,metadata=0x2
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> >   table=70, 
> > priority=100,ct_state=+trk+dnat,ct_ipv6_dst=8800::88,ct_nw_proto=6,ct_tp_dst=8080,tcp6,metadata=0x1
> >  actions=ct(commit,zone=NXM_NX_REG12[[0..15]],nat(src=8800::88))
> > diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> > index 05ccd86..f292344 100644
> > --- a/tests/system-ovn.at
> > +++ b/tests/system-ovn.at
> > @@ -4335,10 +4335,14 @@ start_daemon ovn-controller
> >  # One logical switch with IPv4 load balancers that hairpin the traffic.
> >  ovn-nbctl ls-add sw
> >  ovn-nbctl lsp-add sw lsp -- lsp-set-addresses lsp 00:00:00:00:00:01
> > -ovn-nbctl lb-add lb-ipv4-tcp 88.88.88.88:8080 42.42.42.1:4041 tcp
> > -ovn-nbctl lb-add lb-ipv4-udp 88.88.88.88:4040 42.42.42.1:2021 udp
> > +ovn-nbctl lb-add lb-ipv4-tcp     88.88.88.88:8080 42.42.42.1:4041 tcp
> > +ovn-nbctl lb-add lb-ipv4-tcp-dup 88.88.88.89:8080 42.42.42.1:4041 tcp
> > +ovn-nbctl lb-add lb-ipv4-udp     88.88.88.88:4040 42.42.42.1:2021 udp
> > +ovn-nbctl lb-add lb-ipv4-udp-dup 88.88.88.89:4040 42.42.42.1:2021 udp
> >  ovn-nbctl ls-lb-add sw lb-ipv4-tcp
> > +ovn-nbctl ls-lb-add sw lb-ipv4-tcp-dup
> >  ovn-nbctl ls-lb-add sw lb-ipv4-udp
> > +ovn-nbctl ls-lb-add sw lb-ipv4-udp-dup
> >
> >  ovn-nbctl lr-add rtr
> >  ovn-nbctl lrp-add rtr rtr-sw 00:00:00:00:01:00 42.42.42.254/24
> > @@ -4354,24 +4358,26 @@ ADD_VETH(lsp, lsp, br-int, "42.42.42.1/24", 
> > "00:00:00:00:00:01", \
> >  ovn-nbctl --wait=hv -t 3 sync
> >
> >  # Start IPv4 TCP server on lsp.
> > -NS_CHECK_EXEC([lsp], [timeout 2s nc -l 42.42.42.1 4041 &], [0])
> > +NS_CHECK_EXEC([lsp], [timeout 2s nc -k -l 42.42.42.1 4041 &], [0])
> >
> > -# Check that IPv4 TCP hairpin connection succeeds.
> > +# Check that IPv4 TCP hairpin connection succeeds on both VIPs.
> >  NS_CHECK_EXEC([lsp], [nc 88.88.88.88 8080 -z], [0])
> > +NS_CHECK_EXEC([lsp], [nc 88.88.88.89 8080 -z], [0])
> >
> >  # Capture IPv4 UDP hairpinned packets.
> > -filter="src 88.88.88.88 and dst 42.42.42.1 and dst port 2021 and udp"
> > -NS_CHECK_EXEC([lsp], [tcpdump -n -c 1 -i lsp ${filter} > lsp.pcap &])
> > +filter="dst 42.42.42.1 and dst port 2021 and udp"
> > +NS_CHECK_EXEC([lsp], [tcpdump -n -c 2 -i lsp ${filter} > lsp.pcap &])
> >
> >  sleep 1
> >
> >  # Generate IPv4 UDP hairpin traffic.
> >  NS_CHECK_EXEC([lsp], [nc -u 88.88.88.88 4040 -z &], [0])
> > +NS_CHECK_EXEC([lsp], [nc -u 88.88.88.89 4040 -z &], [0])
> >
> >  # Check hairpin traffic.
> >  OVS_WAIT_UNTIL([
> >      total_pkts=$(cat lsp.pcap | wc -l)
> > -    test "${total_pkts}" = "1"
> > +    test "${total_pkts}" = "2"
> >  ])
> >
> >  OVS_APP_EXIT_AND_WAIT([ovn-controller])
> > @@ -4414,10 +4420,14 @@ start_daemon ovn-controller
> >  # One logical switch with IPv6 load balancers that hairpin the traffic.
> >  ovn-nbctl ls-add sw
> >  ovn-nbctl lsp-add sw lsp -- lsp-set-addresses lsp 00:00:00:00:00:01
> > -ovn-nbctl lb-add lb-ipv6-tcp [[8800::0088]]:8080 [[4200::1]]:4041 tcp
> > -ovn-nbctl lb-add lb-ipv6-udp [[8800::0088]]:4040 [[4200::1]]:2021 udp
> > +ovn-nbctl lb-add lb-ipv6-tcp     [[8800::0088]]:8080 [[4200::1]]:4041 tcp
> > +ovn-nbctl lb-add lb-ipv6-tcp-dup [[8800::0089]]:8080 [[4200::1]]:4041 tcp
> > +ovn-nbctl lb-add lb-ipv6-udp     [[8800::0088]]:4040 [[4200::1]]:2021 udp
> > +ovn-nbctl lb-add lb-ipv6-udp-dup [[8800::0089]]:4040 [[4200::1]]:2021 udp
> >  ovn-nbctl ls-lb-add sw lb-ipv6-tcp
> > +ovn-nbctl ls-lb-add sw lb-ipv6-tcp-dup
> >  ovn-nbctl ls-lb-add sw lb-ipv6-udp
> > +ovn-nbctl ls-lb-add sw lb-ipv6-udp-dup
> >
> >  ovn-nbctl lr-add rtr
> >  ovn-nbctl lrp-add rtr rtr-sw 00:00:00:00:01:00 4200::00ff/64
> > @@ -4432,24 +4442,26 @@ OVS_WAIT_UNTIL([test "$(ip netns exec lsp ip a | 
> > grep 4200::1 | grep tentative)"
> >  ovn-nbctl --wait=hv -t 3 sync
> >
> >  # Start IPv6 TCP server on lsp.
> > -NS_CHECK_EXEC([lsp], [timeout 2s nc -l 4200::1 4041 &], [0])
> > +NS_CHECK_EXEC([lsp], [timeout 2s nc -k -l 4200::1 4041 &], [0])
> >
> > -# Check that IPv6 TCP hairpin connection succeeds.
> > +# Check that IPv6 TCP hairpin connection succeeds on both VIPs.
> >  NS_CHECK_EXEC([lsp], [nc 8800::0088 8080 -z], [0])
> > +NS_CHECK_EXEC([lsp], [nc 8800::0089 8080 -z], [0])
> >
> >  # Capture IPv4 UDP hairpinned packets.
> > -filter="src 8800::0088 and dst 4200::1 and dst port 2021 and udp"
> > -NS_CHECK_EXEC([lsp], [tcpdump -n -c 1 -i lsp $filter > lsp.pcap &])
> > +filter="dst 4200::1 and dst port 2021 and udp"
> > +NS_CHECK_EXEC([lsp], [tcpdump -n -c 2 -i lsp $filter > lsp.pcap &])
> >
> >  sleep 1
> >
> >  # Generate IPv6 UDP hairpin traffic.
> >  NS_CHECK_EXEC([lsp], [nc -u 8800::0088 4040 -z &], [0])
> > +NS_CHECK_EXEC([lsp], [nc -u 8800::0089 4040 -z &], [0])
> >
> >  # Check hairpin traffic.
> >  OVS_WAIT_UNTIL([
> >      total_pkts=$(cat lsp.pcap | wc -l)
> > -    test "${total_pkts}" = "1"
> > +    test "${total_pkts}" = "2"
> >  ])
> >
> >  OVS_APP_EXIT_AND_WAIT([ovn-controller])
> >
> > _______________________________________________
> > dev mailing list
> > [email protected]
> > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to