Excellent, thanks for the updated patch!

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

On 8/23/21 4:37 PM, Mark Gray wrote:
When adding a load balancer to a logical router, two flows are added to
the ingress DNAT table. One flow is for established connections and one is
for new connections. They have the following form:

ct.est && ip4 && reg0 == 10.0.0.10 && ct_label.natted == 1 && tcp

As the established flow does not specify the VIP port, if two load
balancers are added with the same VIP but different VIP ports, then
two conflicting flows will be added. For example,

ct.est && ip4 && reg0 == 10.0.0.10 && ct_label.natted == 1 && tcp
ct.est && ip4 && reg0 == 10.0.0.10 && ct_label.natted == 1 && tcp

This normally does not give an issue as both flows will have the same
action: next.

However, if the logical router specifies "force_snat_for_lb" and one
load balancer specifies "skip_snat" then both flows will have the
same match but different, conflicting actions: "flags.force_snat_for_lb = 1; 
next;"
and "flags.skip_snat_for_lb = 1; next;". This can cause unintended
consequences.

This commit adds the VIP port to the DNAT flow. It also updates
the defrag table to save that port in a register (before it gets
DNATted).

Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1995326
Signed-off-by: Mark Gray <[email protected]>
---

Notes:
     v2: Addressed Mark's comments
         - Change registers

  northd/ovn-northd.8.xml |  52 +++++++-------
  northd/ovn-northd.c     |  32 ++++++---
  northd/ovn_northd.dl    |  38 ++++++----
  tests/ovn-northd.at     | 150 ++++++++++++++++++++--------------------
  tests/ovn.at            |   6 +-
  5 files changed, 154 insertions(+), 124 deletions(-)

diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index 9b69e4e5750e..eebf0d717999 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -2855,15 +2855,18 @@ icmp6 {
        If load balancing rules with virtual IP addresses and ports are
        configured in <code>OVN_Northbound</code> database for a Gateway router,
        a priority-110 flow is added for each configured virtual IP address
-      <var>VIP</var> and protocol <var>PROTO</var>. For IPv4 <var>VIPs</var>
-      the flow matches <code>ip &amp;&amp; ip4.dst == <var>VIP</var> &amp;&amp;
-      <var>PROTO</var></code>. For IPv6 <var>VIPs</var>, the flow matches
+      <var>VIP</var>, protocol <var>PROTO</var> and port <var>PORT</var>.
+      For IPv4 <var>VIPs</var> the flow matches
+      <code>ip &amp;&amp; ip4.dst == <var>VIP</var> &amp;&amp;
+      <var>PROTO</var> &amp;&amp; <var>PROTO</var>.dst ==
+      <var>PORT</var></code>. For IPv6 <var>VIPs</var>, the flow matches
        <code>ip &amp;&amp; ip6.dst == <var>VIP</var> &amp;&amp;
-      <var>PROTO</var></code>. The flow applies the action <code>reg0 =
-      <var>VIP</var>; ct_dnat;</code> (or <code>xxreg0</code> for IPv6) to send
-      IP packets to the connection tracker for packet de-fragmentation and to
-      dnat the destination IP for the committed connection before sending it to
-      the next table.
+      <var>PROTO</var> &amp;&amp; <var>PROTO</var>.dst ==
+      <var>PORT</var></code>. The flow applies the action <code>reg0 =
+      <var>VIP</var>; reg9[16..31] = <var>PROTO</var>.dst; ct_dnat;</code>
+      (or <code>xxreg0</code> for IPv6) to send IP packets to the connection
+      tracker for packet de-fragmentation and to dnat the destination IP for
+      the committed connection before sending it to the next table.
      </p>
<p>
@@ -2913,14 +2916,14 @@ icmp6 {
            includes a L4 port <var>PORT</var> of protocol <var>P</var> and IPv4
            or IPv6 address <var>VIP</var>, a priority-120 flow that matches on
            <code>ct.new &amp;&amp; ip &amp;&amp; reg0 == <var>VIP</var>
-          &amp;&amp; <var>P</var> &amp;&amp; <var>P</var>.dst == <var>PORT
-          </var></code> (<code>xxreg0 == <var>VIP</var></code> in the IPv6
-          case) with an action of <code>ct_lb(<var>args</var>)</code>,
-          where <var>args</var> contains comma separated IPv4 or IPv6 addresses
-          (and optional port numbers) to load balance to.  If the router is
-          configured to force SNAT any load-balanced packets, the above action
-          will be replaced by <code>flags.force_snat_for_lb = 1;
-          ct_lb(<var>args</var>);</code>.
+          &amp;&amp; <var>P</var> &amp;&amp; reg9[16..31] == </code>
+          <code><var>PORT</var></code> (<code>xxreg0 == <var>VIP</var></code>
+          in the IPv6 case) with an action of
+          <code>ct_lb(<var>args</var>)</code>, where <var>args</var> contains
+          comma separated IPv4 or IPv6 addresses (and optional port numbers) to
+          load balance to.  If the router is configured to force SNAT any
+          load-balanced packets, the above action will be replaced by
+          <code>flags.force_snat_for_lb = 1; ct_lb(<var>args</var>);</code>.
            If the load balancing rule is configured with <code>skip_snat</code>
            set to true, the above action will be replaced by
            <code>flags.skip_snat_for_lb = 1; ct_lb(<var>args</var>);</code>.
@@ -2945,14 +2948,15 @@ icmp6 {
            <var>PORT</var> of protocol <var>P</var> and IPv4 or IPv6 address
            <var>VIP</var>, a priority-120 flow that matches on
            <code>ct.est &amp;&amp; ip4 &amp;&amp; reg0 == <var>VIP</var>
-          &amp;&amp; <var>P</var> &amp;&amp; <var>P</var>.dst == <var>PORT
-          </var></code> (<code>ip6</code> and <code>xxreg0 == <var>VIP</var>
-          </code> in the IPv6 case) with an action of <code>next;</code>. If
-          the router is configured to force SNAT any load-balanced packets, the
-          above action will be replaced by <code>flags.force_snat_for_lb = 1;
-          next;</code>. If the load balancing rule is configured with
-          <code>skip_snat</code> set to true, the above action will be replaced
-          by <code>flags.skip_snat_for_lb = 1; next;</code>.
+          &amp;&amp; <var>P</var> &amp;&amp; reg9[16..31] == </code>
+          <code><var>PORT</var></code> (<code>ip6</code> and
+          <code>xxreg0 == <var>VIP</var></code> in the IPv6 case) with an
+          action of <code>next;</code>. If the router is configured to force
+          SNAT any load-balanced packets, the above action will be replaced by
+          <code>flags.force_snat_for_lb = 1; next;</code>. If the load
+          balancing rule is configured with <code>skip_snat</code> set to true,
+          the above action will be replaced by
+          <code>flags.skip_snat_for_lb = 1; next;</code>.
          </p>
<p>
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 3d8e21a4fe8a..7de04683ffd6 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -274,6 +274,8 @@ enum ovn_stage {
  #define REG_SRC_IPV4 "reg1"
  #define REG_SRC_IPV6 "xxreg1"
+#define REG_ORIG_TP_DPORT_ROUTER "reg9[16..31]"
+
  /* Register used for setting a label for ACLs in a Logical Switch. */
  #define REG_LABEL "reg3"
@@ -344,6 +346,9 @@ enum ovn_stage {
   * | R9  |   PKT_LARGER/            | 4 |                 |
   * |     |   LOOKUP_NEIGHBOR_RESULT/|   |                 |
   * |     |   SKIP_LOOKUP_NEIGHBOR}  |   |                 |
+ * |     |                          |   |                 |
+ * |     | REG_ORIG_TP_DPORT_ROUTER |   |                 |
+ * |     |                          |   |                 |
   * +-----+--------------------------+---+-----------------+
   *
   */
@@ -9147,9 +9152,11 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip,
       * an action of "next;".
       */
      if (IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)) {
-        ds_put_format(match, "ip4 && reg0 == %s", lb_vip->vip_str);
+        ds_put_format(match, "ip4 && "REG_NEXT_HOP_IPV4" == %s",
+                      lb_vip->vip_str);
      } else {
-        ds_put_format(match, "ip6 && xxreg0 == %s", lb_vip->vip_str);
+        ds_put_format(match, "ip6 && "REG_NEXT_HOP_IPV6" == %s",
+                      lb_vip->vip_str);
      }
enum lb_snat_type snat_type = NO_FORCE_SNAT;
@@ -9164,11 +9171,13 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip 
*lb_vip,
      int prio = 110;
      if (lb_vip->vip_port) {
          prio = 120;
-        new_match = xasprintf("ct.new && %s && %s && %s.dst == %d",
-                              ds_cstr(match), lb->proto, lb->proto,
-                              lb_vip->vip_port);
-        est_match = xasprintf("ct.est && %s && ct_label.natted == 1 && %s",
-                              ds_cstr(match), lb->proto);
+        new_match = xasprintf("ct.new && %s && %s && "
+                              REG_ORIG_TP_DPORT_ROUTER" == %d",
+                              ds_cstr(match), lb->proto, lb_vip->vip_port);
+        est_match = xasprintf("ct.est && %s && %s && "
+                              REG_ORIG_TP_DPORT_ROUTER" == %d && "
+                              "ct_label.natted == 1",
+                              ds_cstr(match), lb->proto, lb_vip->vip_port);
      } else {
          new_match = xasprintf("ct.new && %s", ds_cstr(match));
          est_match = xasprintf("ct.est && %s && ct_label.natted == 1",
@@ -9399,19 +9408,24 @@ build_lrouter_defrag_flows_for_lb(struct ovn_northd_lb 
*lb,
if (IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)) {
              ds_put_format(match, "ip && ip4.dst == %s", lb_vip->vip_str);
-            ds_put_format(&defrag_actions, "reg0 = %s; ct_dnat;",
+            ds_put_format(&defrag_actions, REG_NEXT_HOP_IPV4" = %s; ",
                            lb_vip->vip_str);
          } else {
              ds_put_format(match, "ip && ip6.dst == %s", lb_vip->vip_str);
-            ds_put_format(&defrag_actions, "xxreg0 = %s; ct_dnat;",
+            ds_put_format(&defrag_actions, REG_NEXT_HOP_IPV6" = %s; ",
                            lb_vip->vip_str);
          }
if (lb_vip->vip_port) {
              ds_put_format(match, " && %s", lb->proto);
              prio = 110;
+
+            ds_put_format(&defrag_actions, REG_ORIG_TP_DPORT_ROUTER
+                          " = %s.dst; ", lb->proto);
          }
+ ds_put_format(&defrag_actions, "ct_dnat;");
+
          for (size_t j = 0; j < lb->n_nb_lr; j++) {
              ovn_lflow_add_with_hint(lflows, lb->nb_lr[j], S_ROUTER_IN_DEFRAG,
                                      prio, ds_cstr(match),
diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl
index 9cf4c373bbb3..bd450f9e9eef 100644
--- a/northd/ovn_northd.dl
+++ b/northd/ovn_northd.dl
@@ -1596,6 +1596,9 @@ function s_ROUTER_OUT_DELIVERY():       Intern<Stage> { Stage{ 
Egress,  4, "lr_o
   * | R9  |   PKT_LARGER/            | 4 |                 |
   * |     |   LOOKUP_NEIGHBOR_RESULT/|   |                 |
   * |     |   SKIP_LOOKUP_NEIGHBOR}  |   |                 |
+ * |     |                          |   |                 |
+ * |     | REG_ORIG_TP_DPORT_ROUTER |   |                 |
+ * |     |                          |   |                 |
   * +-----+--------------------------+---+-----------------+
   *
   */
@@ -1645,6 +1648,8 @@ function rEG_INPORT_ETH_ADDR() : string = "xreg0[0..47]"
  function rEG_ECMP_GROUP_ID()  : string = "reg8[0..15]"
  function rEG_ECMP_MEMBER_ID() : string = "reg8[16..31]"
+function rEG_ORIG_TP_DPORT_ROUTER() : string = "reg9[16..31]"
+
  /* Register used for setting a label for ACLs in a Logical Switch. */
  function rEG_LABEL() : string = "reg3"
@@ -3147,7 +3152,8 @@ function get_match_for_lb_key(ip_address: v46_ip,
                                port: bit<16>,
                                protocol: Option<string>,
                                redundancy: bool,
-                              use_nexthop_reg: bool): string = {
+                              use_nexthop_reg: bool,
+                              use_dest_tp_reg: bool): string = {
      var port_match = if (port != 0) {
          var proto = if (protocol == Some{"udp"}) {
              "udp"
@@ -3155,7 +3161,11 @@ function get_match_for_lb_key(ip_address: v46_ip,
              "tcp"
          };
          if (redundancy) { " && ${proto}" } else { "" } ++
-        " && ${proto}.dst == ${port}"
+        if (use_dest_tp_reg) {
+            " && ${rEG_ORIG_TP_DPORT_ROUTER()} == ${port}"
+        } else {
+            " && ${proto}.dst == ${port}"
+        }
      } else {
          ""
      };
@@ -3268,7 +3278,7 @@ Flow(.logical_datapath = sw._uuid,
      } else {
          None
      },
-    var __match = "ct.new && " ++ get_match_for_lb_key(lbvip.vip_addr, 
lbvip.vip_port, lb.protocol, false, false).
+    var __match = "ct.new && " ++ get_match_for_lb_key(lbvip.vip_addr, 
lbvip.vip_port, lb.protocol, false, false, false).
/* Ingress Pre-Hairpin/Nat-Hairpin/Hairpin tabled (Priority 0).
   * Packets that don't need hairpinning should continue processing.
@@ -6731,7 +6741,14 @@ for (RouterLBVIP(
              } in
          var __match = match1 ++ match2 in
          var xx = ip_address.xxreg() in
-        var __actions = i"${xx}${rEG_NEXT_HOP()} = ${ip_address}; ct_dnat;" in
+        var actions1 = "${xx}${rEG_NEXT_HOP()} = ${ip_address}; " in
+        var actions2 =
+            if (port != 0) {
+                "${rEG_ORIG_TP_DPORT_ROUTER()} = ${proto}.dst; ct_dnat;"
+            } else {
+                "ct_dnat;"
+            } in
+        var __actions = actions1 ++ actions2 in
          /* One of these flows must be created for each unique LB VIP address.
           * We create one for each VIP:port pair; flows with the same IP and
           * different port numbers will produce identical flows that will
@@ -6740,7 +6757,7 @@ for (RouterLBVIP(
               .stage            = s_ROUTER_IN_DEFRAG(),
               .priority         = prio,
               .__match          = __match.intern(),
-             .actions          = __actions,
+             .actions          = __actions.intern(),
               .stage_hint       = 0,
               .io_port          = None,
               .controller_meter = None);
@@ -6754,7 +6771,7 @@ for (RouterLBVIP(
          var match1 = "${ipX} && ${xx}${rEG_NEXT_HOP()} == ${ip_address}" in
          (var prio, var match2) =
              if (port != 0) {
-                (120, " && ${proto} && ${proto}.dst == ${port}")
+                (120, " && ${proto} && ${rEG_ORIG_TP_DPORT_ROUTER()} == 
${port}")
              } else {
                  (110, "")
              } in
@@ -6766,12 +6783,7 @@ for (RouterLBVIP(
          var snat_for_lb = snat_for_lb(r.options, lb) in
          {
              /* A match and actions for established connections. */
-            var est_match = "ct.est && " ++ match1 ++ " && ct_label.natted == 
1" ++
-                if (port != 0) {
-                    " && ${proto}"
-                } else {
-                    ""
-                } ++
+            var est_match = "ct.est && " ++ match1 ++ match2 ++ " && 
ct_label.natted == 1" ++
                  match ((l3dgw_ports.nth(0), backends != "" or 
lb.options.get_bool_def("reject", false))) {
                      (Some {var gw_port}, true) -> " && 
is_chassis_resident(${json_string_escape(chassis_redirect_name(gw_port.name))})",
                      _ -> ""
@@ -6879,7 +6891,7 @@ Flow(.logical_datapath = r._uuid,
      r.load_balancer.contains(lb._uuid),
      var __match
          = "ct.new && " ++
-          get_match_for_lb_key(lbvip.vip_addr, lbvip.vip_port, lb.protocol, 
true, true) ++
+          get_match_for_lb_key(lbvip.vip_addr, lbvip.vip_port, lb.protocol, 
true, true, true) ++
            match (r.l3dgw_ports.nth(0)) {
                Some{gw_port} -> " && 
is_chassis_resident(${json_string_escape(chassis_redirect_name(gw_port.name))})",
                _ -> ""
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 93bb0e1da2f0..c7acd9a6ef0d 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -3269,13 +3269,13 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], 
[dnl
AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl
    table=5 (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;)
  ])
AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
    table=6 (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 
&& ct_label.natted == 1 && tcp), action=(next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && tcp.dst == 80), action=(ct_lb(backends=10.0.0.4:8080);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 && 
tcp && reg9[[16..31]] == 80 && ct_label.natted == 1), action=(next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && reg9[[16..31]] == 80), action=(ct_lb(backends=10.0.0.4:8080);)
  ])
AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl
@@ -3302,13 +3302,13 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], 
[dnl
AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl
    table=5 (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;)
  ])
AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
    table=6 (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.4:8080);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 && 
tcp && reg9[[16..31]] == 80 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.4:8080);)
  ])
AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl
@@ -3345,13 +3345,13 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], 
[dnl
AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl
    table=5 (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;)
  ])
AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
    table=6 (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.4:8080);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 && 
tcp && reg9[[16..31]] == 80 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.4:8080);)
  ])
AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl
@@ -3402,13 +3402,13 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], 
[dnl
AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl
    table=5 (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;)
  ])
AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
    table=6 (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.4:8080);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 && 
tcp && reg9[[16..31]] == 80 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.4:8080);)
  ])
AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl
@@ -3446,12 +3446,12 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], 
[dnl
AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl
    table=5 (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.20 
&& tcp), action=(reg0 = 10.0.0.20; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.20 
&& tcp), action=(reg0 = 10.0.0.20; reg9[[16..31]] = tcp.dst; ct_dnat;)
  ])
AT_CHECK([grep "lr_in_dnat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.20 
&& ct_label.natted == 1 && tcp), action=(flags.skip_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.20 
&& tcp && tcp.dst == 80), action=(flags.skip_snat_for_lb = 1; ct_lb(backends=10.0.0.40:8080);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.20 && 
tcp && reg9[[16..31]] == 80 && ct_label.natted == 1), action=(flags.skip_snat_for_lb = 1; next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.20 
&& tcp && reg9[[16..31]] == 80), action=(flags.skip_snat_for_lb = 1; 
ct_lb(backends=10.0.0.40:8080);)
  ])
AT_CHECK([grep "lr_out_snat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl
@@ -4561,9 +4561,9 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl
  AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl
    table=5 (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
    table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.200), action=(reg0 = 172.168.0.200; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.100 
&& tcp), action=(reg0 = 172.168.0.100; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& udp), action=(reg0 = 172.168.0.210; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.100 
&& tcp), action=(reg0 = 172.168.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& udp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = udp.dst; ct_dnat;)
  ])
AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -4571,12 +4571,12 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
    table=6 (lr_in_dnat         ), priority=100  , match=(ip && ip4.dst == 172.168.0.20 && inport == 
"lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);)
    table=6 (lr_in_dnat         ), priority=110  , match=(ct.est && ip4 && reg0 == 172.168.0.200 
&& ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;)
    table=6 (lr_in_dnat         ), priority=110  , match=(ct.new && ip4 && reg0 == 172.168.0.200 
&& is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.80,10.0.0.81);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 && 
ct_label.natted == 1 && tcp && is_chassis_resident("cr-lr0-public")), action=(next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.100 && 
ct_label.natted == 1 && tcp && is_chassis_resident("cr-lr0-public")), action=(next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 && 
ct_label.natted == 1 && udp && is_chassis_resident("cr-lr0-public")), action=(next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 && tcp 
&& tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.4:8080);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.100 && tcp 
&& tcp.dst == 8082 && is_chassis_resident("cr-lr0-public")), 
action=(ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp 
&& udp.dst == 60 && is_chassis_resident("cr-lr0-public")), 
action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 && tcp && 
reg9[[16..31]] == 80 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.100 && tcp && 
reg9[[16..31]] == 8082 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 && udp && 
reg9[[16..31]] == 60 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 && tcp 
&& reg9[[16..31]] == 80 && is_chassis_resident("cr-lr0-public")), 
action=(ct_lb(backends=10.0.0.4:8080);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.100 && tcp 
&& reg9[[16..31]] == 8082 && is_chassis_resident("cr-lr0-public")), 
action=(ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 && udp 
&& reg9[[16..31]] == 60 && is_chassis_resident("cr-lr0-public")), 
action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
  ])
AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl
@@ -4621,9 +4621,9 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl
  AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl
    table=5 (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
    table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.200), action=(reg0 = 172.168.0.200; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.100 
&& tcp), action=(reg0 = 172.168.0.100; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& udp), action=(reg0 = 172.168.0.210; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.100 
&& tcp), action=(reg0 = 172.168.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& udp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = udp.dst; ct_dnat;)
  ])
AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -4631,12 +4631,12 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
    table=6 (lr_in_dnat         ), priority=100  , match=(ip && ip4.dst == 
172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);)
    table=6 (lr_in_dnat         ), priority=110  , match=(ct.est && ip4 && reg0 == 
172.168.0.200 && ct_label.natted == 1), action=(next;)
    table=6 (lr_in_dnat         ), priority=110  , match=(ct.new && ip4 && reg0 
== 172.168.0.200), action=(ct_lb(backends=10.0.0.80,10.0.0.81);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 
&& ct_label.natted == 1 && tcp), action=(next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.100 
&& ct_label.natted == 1 && tcp), action=(next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 
&& ct_label.natted == 1 && udp), action=(next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && tcp.dst == 80), action=(ct_lb(backends=10.0.0.4:8080);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.100 
&& tcp && tcp.dst == 8082), action=(ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 
&& udp && udp.dst == 60), action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 && 
tcp && reg9[[16..31]] == 80 && ct_label.natted == 1), action=(next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.100 
&& tcp && reg9[[16..31]] == 8082 && ct_label.natted == 1), action=(next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 
&& udp && reg9[[16..31]] == 60 && ct_label.natted == 1), action=(next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && reg9[[16..31]] == 80), action=(ct_lb(backends=10.0.0.4:8080);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.100 
&& tcp && reg9[[16..31]] == 8082), action=(ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 
&& udp && reg9[[16..31]] == 60), action=(ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
  ])
AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl
@@ -4676,9 +4676,9 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], [dnl
  AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl
    table=5 (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
    table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.200), action=(reg0 = 172.168.0.200; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.100 
&& tcp), action=(reg0 = 172.168.0.100; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& udp), action=(reg0 = 172.168.0.210; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.100 
&& tcp), action=(reg0 = 172.168.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& udp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = udp.dst; ct_dnat;)
  ])
AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -4686,12 +4686,12 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
    table=6 (lr_in_dnat         ), priority=100  , match=(ip && ip4.dst == 
172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);)
    table=6 (lr_in_dnat         ), priority=110  , match=(ct.est && ip4 && reg0 == 
172.168.0.200 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;)
    table=6 (lr_in_dnat         ), priority=110  , match=(ct.new && ip4 && reg0 
== 172.168.0.200), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.80,10.0.0.81);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.100 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 
&& ct_label.natted == 1 && udp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.4:8080);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.100 
&& tcp && tcp.dst == 8082), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 
&& udp && udp.dst == 60), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 && 
tcp && reg9[[16..31]] == 80 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.100 
&& tcp && reg9[[16..31]] == 8082 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; 
next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 
&& udp && reg9[[16..31]] == 60 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; 
next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.4:8080);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.100 
&& tcp && reg9[[16..31]] == 8082), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 
&& udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
  ])
AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl
@@ -4734,10 +4734,10 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], 
[dnl
  AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl
    table=5 (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
    table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.200), action=(reg0 = 172.168.0.200; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.10 
&& tcp), action=(reg0 = 172.168.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.100 
&& tcp), action=(reg0 = 172.168.0.100; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& udp), action=(reg0 = 172.168.0.210; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.10 
&& tcp), action=(reg0 = 172.168.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.100 
&& tcp), action=(reg0 = 172.168.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& udp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = udp.dst; ct_dnat;)
  ])
AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -4745,14 +4745,14 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
    table=6 (lr_in_dnat         ), priority=100  , match=(ip && ip4.dst == 
172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);)
    table=6 (lr_in_dnat         ), priority=110  , match=(ct.est && ip4 && reg0 == 
172.168.0.200 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;)
    table=6 (lr_in_dnat         ), priority=110  , match=(ct.new && ip4 && reg0 
== 172.168.0.200), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.80,10.0.0.81);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.10 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.100 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 
&& ct_label.natted == 1 && udp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.4:8080);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.10 
&& tcp && tcp.dst == 9082), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.100 
&& tcp && tcp.dst == 8082), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 
&& udp && udp.dst == 60), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 && 
tcp && reg9[[16..31]] == 80 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.10 
&& tcp && reg9[[16..31]] == 9082 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; 
next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.100 
&& tcp && reg9[[16..31]] == 8082 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; 
next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 
&& udp && reg9[[16..31]] == 60 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; 
next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.4:8080);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.10 
&& tcp && reg9[[16..31]] == 9082), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.100 
&& tcp && reg9[[16..31]] == 8082), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 
&& udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
  ])
AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl
@@ -4805,11 +4805,11 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], 
[dnl
  AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl
    table=5 (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
    table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.200), action=(reg0 = 172.168.0.200; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.10 
&& tcp), action=(reg0 = 172.168.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.100 
&& tcp), action=(reg0 = 172.168.0.100; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& udp), action=(reg0 = 172.168.0.210; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip6.dst == def0::2 
&& tcp), action=(xxreg0 = def0::2; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 10.0.0.10 
&& tcp), action=(reg0 = 10.0.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.10 
&& tcp), action=(reg0 = 172.168.0.10; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.100 
&& tcp), action=(reg0 = 172.168.0.100; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& udp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = udp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip6.dst == def0::2 
&& tcp), action=(xxreg0 = def0::2; reg9[[16..31]] = tcp.dst; ct_dnat;)
  ])
AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -4817,16 +4817,16 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
    table=6 (lr_in_dnat         ), priority=100  , match=(ip && ip4.dst == 
172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);)
    table=6 (lr_in_dnat         ), priority=110  , match=(ct.est && ip4 && reg0 == 
172.168.0.200 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;)
    table=6 (lr_in_dnat         ), priority=110  , match=(ct.new && ip4 && reg0 
== 172.168.0.200), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.80,10.0.0.81);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.10 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.100 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 
&& ct_label.natted == 1 && udp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip6 && xxreg0 == def0::2 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb(backends=10.0.0.4:8080);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.10 
&& tcp && tcp.dst == 9082), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.100 
&& tcp && tcp.dst == 8082), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 
&& udp && udp.dst == 60), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip6 && xxreg0 == def0::2 
&& tcp && tcp.dst == 8000), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=[[aef0::2]]:80,[[aef0::3]]:80);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 && 
tcp && reg9[[16..31]] == 80 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.10 
&& tcp && reg9[[16..31]] == 9082 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; 
next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.100 
&& tcp && reg9[[16..31]] == 8082 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; 
next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 
&& udp && reg9[[16..31]] == 60 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; 
next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip6 && xxreg0 == def0::2 && 
tcp && reg9[[16..31]] == 8000 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 
&& tcp && reg9[[16..31]] == 80), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.4:8080);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.10 
&& tcp && reg9[[16..31]] == 9082), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.100 
&& tcp && reg9[[16..31]] == 8082), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 
&& udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip6 && xxreg0 == def0::2 
&& tcp && reg9[[16..31]] == 8000), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=[[aef0::2]]:80,[[aef0::3]]:80);)
  ])
AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl
@@ -4871,16 +4871,16 @@ AT_CHECK([grep "lr_in_unsnat" lr0flows | sort], [0], 
[dnl
AT_CHECK([grep "lr_in_defrag" lr0flows | sort], [0], [dnl
    table=5 (lr_in_defrag       ), priority=0    , match=(1), action=(next;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& tcp), action=(reg0 = 172.168.0.210; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& udp), action=(reg0 = 172.168.0.210; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& tcp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = tcp.dst; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=110  , match=(ip && ip4.dst == 172.168.0.210 
&& udp), action=(reg0 = 172.168.0.210; reg9[[16..31]] = udp.dst; ct_dnat;)
  ])
AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
    table=6 (lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 
&& ct_label.natted == 1 && tcp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 
&& ct_label.natted == 1 && udp), action=(flags.force_snat_for_lb = 1; next;)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 
&& tcp && tcp.dst == 60), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
-  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 
&& udp && udp.dst == 60), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 
&& tcp && reg9[[16..31]] == 60 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; 
next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 172.168.0.210 
&& udp && reg9[[16..31]] == 60 && ct_label.natted == 1), action=(flags.force_snat_for_lb = 1; 
next;)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 
&& tcp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
+  table=6 (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 172.168.0.210 
&& udp && reg9[[16..31]] == 60), action=(flags.force_snat_for_lb = 1; 
ct_lb(backends=10.0.0.50:6062,10.0.0.60:6062);)
  ])
AT_CHECK([grep "lr_out_undnat" lr0flows | sort], [0], [dnl
diff --git a/tests/ovn.at b/tests/ovn.at
index f2882d1ad3cb..f66b3c9edd55 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -21098,7 +21098,7 @@ AT_CAPTURE_FILE([sbflows2])
  OVS_WAIT_FOR_OUTPUT(
    [ovn-sbctl dump-flows > sbflows2
     ovn-sbctl dump-flows lr0 | grep ct_lb | grep priority=120 | sed 
's/table=..//'], 0,
-  [  (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 && tcp && tcp.dst == 
80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.3:80,20.0.0.3:80; 
hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");)
+  [  (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 && tcp && 
reg9[[16..31]] == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.3:80,20.0.0.3:80; 
hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");)
  ])
# get the svc monitor mac.
@@ -21139,8 +21139,8 @@ AT_CHECK(
  AT_CAPTURE_FILE([sbflows4])
  ovn-sbctl dump-flows lr0 > sbflows4
  AT_CHECK([grep lr_in_dnat sbflows4 | grep priority=120 | sed 's/table=..//' | 
sort], [0], [dnl
-  (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 && ct_label.natted == 
1 && tcp && is_chassis_resident("cr-lr0-public")), action=(next;)
-  (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 && tcp && 
tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(drop;)
+  (lr_in_dnat         ), priority=120  , match=(ct.est && ip4 && reg0 == 10.0.0.10 && tcp && 
reg9[[16..31]] == 80 && ct_label.natted == 1 && is_chassis_resident("cr-lr0-public")), action=(next;)
+  (lr_in_dnat         ), priority=120  , match=(ct.new && ip4 && reg0 == 10.0.0.10 && tcp && 
reg9[[16..31]] == 80 && is_chassis_resident("cr-lr0-public")), action=(drop;)
  ])
# Delete sw0-p1


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

Reply via email to