There is a difference between userspace and kernel DP for fragmented
packets. The kernel DP will try to reassemble the fragments during CT
lookup, however userspace won't reassemble them. In case of LB with
protocol match we cannot match on L4 header for later fragments
because the information is not available. Match on CT L4 fields
instead, this shouldn't cause any HWOL issues because the match
is adjusted only for ct.new packets that cannot be offloaded anyway.

Move the original test for fragmented traffic through LB into
system-ovn.at so it's no longer skipped with userspace DP.

Reported-at: https://issues.redhat.com/browse/FDP-684
Signed-off-by: Ales Musil <[email protected]>
Acked-by: Dumitru Ceara <[email protected]>
---
v3: Rebase on top of current main.
    Add Dumitru's ack.
---
 lib/logical-fields.c     |  15 ++++
 northd/northd.c          |   6 +-
 tests/ovn-northd.at      | 150 +++++++++++++++++++--------------------
 tests/ovn.at             |  27 ++++---
 tests/system-ovn-kmod.at | 141 ------------------------------------
 tests/system-ovn.at      | 145 +++++++++++++++++++++++++++++++++++++
 6 files changed, 255 insertions(+), 229 deletions(-)

diff --git a/lib/logical-fields.c b/lib/logical-fields.c
index db2d08ada..fabe17338 100644
--- a/lib/logical-fields.c
+++ b/lib/logical-fields.c
@@ -355,6 +355,21 @@ ovn_init_symtab(struct shash *symtab)
 
     expr_symtab_add_ovn_field(symtab, "icmp4.frag_mtu", OVN_ICMP4_FRAG_MTU);
     expr_symtab_add_ovn_field(symtab, "icmp6.frag_mtu", OVN_ICMP6_FRAG_MTU);
+
+    expr_symtab_add_field(symtab, "ct_proto", MFF_CT_NW_PROTO,
+                          "ct.trk", false);
+
+    expr_symtab_add_predicate(symtab, "ct_udp", "ct_proto == 17");
+    expr_symtab_add_field(symtab, "ct_udp.dst", MFF_CT_TP_DST,
+                          "ct_udp", false);
+
+    expr_symtab_add_predicate(symtab, "ct_tcp", "ct_proto == 6");
+    expr_symtab_add_field(symtab, "ct_tcp.dst", MFF_CT_TP_DST,
+                          "ct_tcp", false);
+
+    expr_symtab_add_predicate(symtab, "ct_sctp", "ct_proto == 132");
+    expr_symtab_add_field(symtab, "ct_sctp.dst", MFF_CT_TP_DST,
+                          "ct_sctp", false);
 }
 
 const char *
diff --git a/northd/northd.c b/northd/northd.c
index a3d278746..613317a4a 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -8329,7 +8329,7 @@ build_lb_affinity_ls_flows(struct lflow_table *lflows,
                   ip_match, ip_match, lb_vip->vip_str);
 
     if (lb_vip->port_str) {
-        ds_put_format(&new_lb_match, " && %s && %s.dst == %s",
+        ds_put_format(&new_lb_match, " && ct_%s && ct_%s.dst == %s",
                       lb->proto, lb->proto, lb_vip->port_str);
     }
 
@@ -8493,7 +8493,7 @@ build_lb_rules(struct lflow_table *lflows, struct 
ovn_lb_datapaths *lb_dps,
                       lb_vip->vip_str);
         int priority = 110;
         if (lb_vip->port_str) {
-            ds_put_format(match, " && %s.dst == %s", lb->proto,
+            ds_put_format(match, " && ct_%s.dst == %s", lb->proto,
                           lb_vip->port_str);
             priority = 120;
         }
@@ -12472,7 +12472,7 @@ build_lrouter_nat_flows_for_lb(
                   ip_match, ip_match, lb_vip->vip_str);
     if (lb_vip->port_str) {
         prio = 120;
-        ds_put_format(match, " && %s && %s.dst == %s",
+        ds_put_format(match, " && ct_%s && ct_%s.dst == %s",
                       lb->proto, lb->proto, lb_vip->port_str);
     }
 
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index f66ba4c85..136e72e8a 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -1475,7 +1475,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.*backends' | 
ovn_strip_lflows], 0, [dnl
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
 ])
 
 # disabled LSPs should not be a backend of Load Balancer
@@ -1484,7 +1484,7 @@ check ovn-nbctl lsp-set-enabled sw0-p1 disabled
 AT_CAPTURE_FILE([sbflows])
 OVS_WAIT_FOR_OUTPUT(
   [ovn-sbctl dump-flows sw0 | tee sbflows | grep 'priority=120.*backends' | 
ovn_strip_lflows], 0, [dnl
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=20.0.0.3:80);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=20.0.0.3:80);)
 ])
 wait_row_count Service_Monitor 1
 
@@ -1493,7 +1493,7 @@ check ovn-nbctl lsp-set-enabled sw0-p1 enabled
 AT_CAPTURE_FILE([sbflows])
 OVS_WAIT_FOR_OUTPUT(
   [ovn-sbctl dump-flows sw0 | tee sbflows | grep 'priority=120.*backends' | 
ovn_strip_lflows], 0, [dnl
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
 ])
 wait_row_count Service_Monitor 2
 
@@ -1504,7 +1504,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.*backends' | 
ovn_strip_lflows], [0],
-[  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
+[  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
 ])
 
 AS_BOX([Create the Load_Balancer_Health_Check again.])
@@ -1516,7 +1516,7 @@ check ovn-nbctl --wait=sb sync
 
 ovn-sbctl dump-flows sw0 | grep backends | grep priority=120 > lflows.txt
 AT_CHECK([cat lflows.txt | ovn_strip_lflows], [0], [dnl
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
 ])
 
 AS_BOX([Get the uuid of both the service_monitor])
@@ -1526,7 +1526,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.*backends' | 
ovn_strip_lflows], [0],
-[  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
+[  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
 ])
 
 AS_BOX([Set the service monitor for sw1-p1 to offline])
@@ -1537,7 +1537,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.*backends' | 
ovn_strip_lflows], [0],
-[  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80);)
+[  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80);)
 ])
 
 AS_BOX([Set the service monitor for sw0-p1 to offline])
@@ -1552,8 +1552,8 @@ OVS_WAIT_FOR_OUTPUT(
 
 AT_CAPTURE_FILE([sbflows6])
 OVS_WAIT_FOR_OUTPUT(
-  [ovn-sbctl dump-flows sw0 | tee sbflows6 | grep "ip4.dst == 10.0.0.10 && 
tcp.dst == 80" | grep priority=120 | grep ls_in_lb | ovn_strip_lflows], [0], 
[dnl
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(drop;)
+  [ovn-sbctl dump-flows sw0 | tee sbflows6 | grep "ip4.dst == 10.0.0.10 && 
ct_tcp.dst == 80" | grep priority=120 | grep ls_in_lb | ovn_strip_lflows], [0], 
[dnl
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(drop;)
 ])
 
 AS_BOX([Set the service monitor for sw0-p1 and sw1-p1 to online])
@@ -1566,7 +1566,7 @@ check ovn-nbctl --wait=sb sync
 AT_CAPTURE_FILE([sbflows7])
 OVS_WAIT_FOR_OUTPUT(
   [ovn-sbctl dump-flows sw0 | tee sbflows7 | grep backends | grep priority=120 
| ovn_strip_lflows], 0,
-[  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
+[  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
 ])
 
 AS_BOX([Set the service monitor for sw1-p1 to error])
@@ -1574,10 +1574,10 @@ check ovn-sbctl set service_monitor $sm_sw1_p1 
status=error
 wait_row_count Service_Monitor 1 logical_port=sw1-p1 status=error
 check ovn-nbctl --wait=sb sync
 
-ovn-sbctl dump-flows sw0 | grep "ip4.dst == 10.0.0.10 && tcp.dst == 80" \
+ovn-sbctl dump-flows sw0 | grep "ip4.dst == 10.0.0.10 && ct_tcp.dst == 80" \
 | grep priority=120 > lflows.txt
 AT_CHECK([cat lflows.txt | grep ls_in_lb | ovn_strip_lflows], [0], [dnl
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80);)
 ])
 
 AS_BOX([Add one more vip to lb1])
@@ -1603,8 +1603,8 @@ AT_CAPTURE_FILE([sbflows9])
 OVS_WAIT_FOR_OUTPUT(
   [ovn-sbctl dump-flows sw0 | tee sbflows9 | grep backends | grep priority=120 
| ovn_strip_lflows],
   0,
-[  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80);)
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.40 && tcp.dst == 1000), action=(reg4 = 10.0.0.40; reg2[[0..15]] = 1000; 
ct_lb_mark(backends=10.0.0.3:1000);)
+[  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.40 && ct_tcp.dst == 1000), action=(reg4 = 10.0.0.40; reg2[[0..15]] = 
1000; ct_lb_mark(backends=10.0.0.3:1000);)
 ])
 
 AS_BOX([Set the service monitor for sw1-p1 to online])
@@ -1617,8 +1617,8 @@ AT_CAPTURE_FILE([sbflows10])
 OVS_WAIT_FOR_OUTPUT(
   [ovn-sbctl dump-flows sw0 | tee sbflows10 | grep backends | grep 
priority=120 | ovn_strip_lflows],
   0,
-[  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.40 && tcp.dst == 1000), action=(reg4 = 10.0.0.40; reg2[[0..15]] = 1000; 
ct_lb_mark(backends=10.0.0.3:1000,20.0.0.3:80);)
+[  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.40 && ct_tcp.dst == 1000), action=(reg4 = 10.0.0.40; reg2[[0..15]] = 
1000; ct_lb_mark(backends=10.0.0.3:1000,20.0.0.3:80);)
 ])
 
 AS_BOX([Associate lb1 to sw1])
@@ -1627,8 +1627,8 @@ AT_CAPTURE_FILE([sbflows11])
 OVS_WAIT_FOR_OUTPUT(
   [ovn-sbctl dump-flows sw1 | tee sbflows11 | grep backends | grep 
priority=120 | ovn_strip_lflows],
   0, [dnl
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.40 && tcp.dst == 1000), action=(reg4 = 10.0.0.40; reg2[[0..15]] = 1000; 
ct_lb_mark(backends=10.0.0.3:1000,20.0.0.3:80);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.40 && ct_tcp.dst == 1000), action=(reg4 = 10.0.0.40; reg2[[0..15]] = 
1000; ct_lb_mark(backends=10.0.0.3:1000,20.0.0.3:80);)
 ])
 
 AS_BOX([Now create lb2 same as lb1 but udp protocol.])
@@ -1684,8 +1684,8 @@ check ovn-sbctl set service_monitor $sm_sw1_p1 
status=offline
 
 AT_CAPTURE_FILE([sbflows12])
 OVS_WAIT_FOR_OUTPUT(
-  [ovn-sbctl dump-flows sw0 | tee sbflows12 | grep "ip4.dst == 10.0.0.10 && 
tcp.dst == 80" | grep priority=120 | grep ls_in_lb | ovn_strip_lflows], [0], 
[dnl
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg0 = 0; reject { outport <-> inport; 
next(pipeline=egress,table=??);};)
+  [ovn-sbctl dump-flows sw0 | tee sbflows12 | grep "ip4.dst == 10.0.0.10 && 
ct_tcp.dst == 80" | grep priority=120 | grep ls_in_lb | ovn_strip_lflows], [0], 
[dnl
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg0 = 0; reject { outport <-> inport; 
next(pipeline=egress,table=??);};)
 ])
 
 AT_CLEANUP
@@ -4399,8 +4399,8 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | 
ovn_strip_lflows], [0], [dnl
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), 
action=(ct_lb_mark(backends=10.0.0.4:8080);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.100 && tcp && tcp.dst == 80), 
action=(ct_lb_mark(backends=10.0.0.40:8080);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), 
action=(ct_lb_mark(backends=10.0.0.4:8080);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.100 && ct_tcp && ct_tcp.dst == 80), 
action=(ct_lb_mark(backends=10.0.0.40:8080);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -4430,8 +4430,8 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | 
ovn_strip_lflows], [0], [dnl
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; 
force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.100 && tcp && tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; 
force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; 
force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.100 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; 
force_snat);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -4481,8 +4481,8 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | 
ovn_strip_lflows], [0], [dnl
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; 
force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.100 && tcp && tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; 
force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; 
force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.100 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; 
force_snat);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -4549,8 +4549,8 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | 
ovn_strip_lflows], [0], [dnl
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; 
force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.100 && tcp && tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; 
force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; 
force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.100 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; 
force_snat);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -4604,7 +4604,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | 
ovn_strip_lflows], [0], [dnl
 ])
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | grep skip_snat_for_lb | 
ovn_strip_lflows], [0], [dnl
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.20 && tcp && tcp.dst == 80), 
action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; 
skip_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.20 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; 
skip_snat);)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.skip_snat == 1), 
action=(flags.skip_snat_for_lb = 1; next;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 
1; ct_commit_nat;)
 ])
@@ -4785,8 +4785,8 @@ check_stateful_flows() {
   table=??(ls_in_lb           ), priority=0    , match=(1), action=(next;)
   table=??(ls_in_lb           ), priority=110  , match=(ct.trk && !ct.rpl && 
reg0[[19]] == 1 && ip4), action=(reg4 = ct_nw_dst(); reg2[[0..15]] = 
ct_tp_dst(); next;)
   table=??(ls_in_lb           ), priority=110  , match=(ct.trk && !ct.rpl && 
reg0[[19]] == 1 && ip6), action=(xxreg1 = ct_ip6_dst(); reg2[[0..15]] = 
ct_tp_dst(); next;)
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.4:8080);)
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.20 && tcp.dst == 80), action=(reg4 = 10.0.0.20; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.40:8080);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.4:8080);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.20 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.20; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.40:8080);)
 ])
 
     AT_CHECK([grep "ls_in_stateful" sw0flows | ovn_strip_lflows], [0], [dnl
@@ -6040,9 +6040,9 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], 
[0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
   table=??(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_in_czone(10.0.0.3);)
   table=??(lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.200 && is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.80,10.0.0.81);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.4:8080);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.4:8080);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -6110,9 +6110,9 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], 
[0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
   table=??(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=??(lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.200 && is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.80,10.0.0.81);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.4:8080);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.4:8080);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -6184,9 +6184,9 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], 
[0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
   table=??(lr_in_dnat         ), priority=100  , match=(ip && ip4.dst == 
172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);)
   table=??(lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.200), 
action=(ct_lb_mark(backends=10.0.0.80,10.0.0.81);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), 
action=(ct_lb_mark(backends=10.0.0.4:8080);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60), 
action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), 
action=(ct_lb_mark(backends=10.0.0.4:8080);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60), 
action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -6247,9 +6247,9 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], 
[0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
   table=??(lr_in_dnat         ), priority=100  , match=(ip && ip4.dst == 
172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);)
   table=??(lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.200), action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.80,10.0.0.81; force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; 
force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; 
force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -6314,10 +6314,10 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | 
ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
   table=??(lr_in_dnat         ), priority=100  , match=(ip && ip4.dst == 
172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);)
   table=??(lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.200), action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.80,10.0.0.81; force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; 
force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.10 && tcp && tcp.dst == 9082), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; 
force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.10 && ct_tcp && ct_tcp.dst == 9082), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -6393,11 +6393,11 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | 
ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
   table=??(lr_in_dnat         ), priority=100  , match=(ip && ip4.dst == 
172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);)
   table=??(lr_in_dnat         ), priority=110  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.200), action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.80,10.0.0.81; force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; 
force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.10 && tcp && tcp.dst == 9082), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip6 && ip6.dst == def0::2 && tcp && tcp.dst == 8000), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=[[aef0::2]]:80,[[aef0::3]]:80; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; 
force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.10 && ct_tcp && ct_tcp.dst == 9082), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip6 && ip6.dst == def0::2 && ct_tcp && ct_tcp.dst == 8000), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=[[aef0::2]]:80,[[aef0::3]]:80; force_snat);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -6462,8 +6462,8 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | 
ovn_strip_lflows], [0], [dnl
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && tcp && tcp.dst == 60), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && udp && udp.dst == 60), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && ct_tcp && ct_tcp.dst == 60), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60), 
action=(flags.force_snat_for_lb = 1; 
ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -9656,13 +9656,13 @@ AT_CAPTURE_FILE([S1flows])
 
 AT_CHECK([grep "ls_in_lb " S0flows | ovn_strip_lflows], [0], [dnl
   table=??(ls_in_lb           ), priority=0    , match=(1), action=(next;)
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
172.16.0.10 && tcp.dst == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80);)
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
172.16.0.11 && tcp.dst == 8080), action=(reg4 = 172.16.0.11; reg2[[0..15]] = 
8080; ct_lb_mark(backends=10.0.0.2:8080);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
172.16.0.10 && ct_tcp.dst == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 
80; ct_lb_mark(backends=10.0.0.2:80);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
172.16.0.11 && ct_tcp.dst == 8080), action=(reg4 = 172.16.0.11; reg2[[0..15]] = 
8080; ct_lb_mark(backends=10.0.0.2:8080);)
 ])
 AT_CHECK([grep "ls_in_lb " S1flows | ovn_strip_lflows], [0], [dnl
   table=??(ls_in_lb           ), priority=0    , match=(1), action=(next;)
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
172.16.0.10 && tcp.dst == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80);)
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
172.16.0.11 && tcp.dst == 8080), action=(reg4 = 172.16.0.11; reg2[[0..15]] = 
8080; ct_lb_mark(backends=10.0.0.2:8080);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
172.16.0.10 && ct_tcp.dst == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 
80; ct_lb_mark(backends=10.0.0.2:80);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
172.16.0.11 && ct_tcp.dst == 8080), action=(reg4 = 172.16.0.11; reg2[[0..15]] = 
8080; ct_lb_mark(backends=10.0.0.2:8080);)
 ])
 
 ovn-sbctl get datapath S0 _uuid > dp_uuids
@@ -9788,13 +9788,13 @@ AT_CAPTURE_FILE([S0flows])
 
 AT_CHECK([grep "ls_in_lb_aff_check" S0flows | ovn_strip_lflows], [0], [dnl
   table=??(ls_in_lb_aff_check ), priority=0    , match=(1), action=(next;)
-  table=??(ls_in_lb_aff_check ), priority=100  , match=(ct.new && ip4 && 
ip4.dst == 172.16.0.10 && tcp && tcp.dst == 80), action=(reg9[[6]] = 
chk_lb_aff(); next;)
+  table=??(ls_in_lb_aff_check ), priority=100  , match=(ct.new && ip4 && 
ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), action=(reg9[[6]] = 
chk_lb_aff(); next;)
 ])
 AT_CHECK([grep "ls_in_lb " S0flows | ovn_strip_lflows], [0], [dnl
   table=??(ls_in_lb           ), priority=0    , match=(1), action=(next;)
   table=??(ls_in_lb           ), priority=110  , match=(ct.trk && !ct.rpl && 
reg0[[19]] == 1 && ip4), action=(reg4 = ct_nw_dst(); reg2[[0..15]] = 
ct_tp_dst(); next;)
   table=??(ls_in_lb           ), priority=110  , match=(ct.trk && !ct.rpl && 
reg0[[19]] == 1 && ip6), action=(xxreg1 = ct_ip6_dst(); reg2[[0..15]] = 
ct_tp_dst(); next;)
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
172.16.0.10 && tcp.dst == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80);)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
172.16.0.10 && ct_tcp.dst == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 
80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80);)
   table=??(ls_in_lb           ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.10 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), 
action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80);)
   table=??(ls_in_lb           ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.10 && reg4 == 20.0.0.2 && reg2[[0..15]] == 80), 
action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=20.0.0.2:80);)
 ])
@@ -9810,11 +9810,11 @@ AT_CAPTURE_FILE([R1flows])
 
 AT_CHECK([grep "lr_in_lb_aff_check" R1flows | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_lb_aff_check ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_lb_aff_check ), priority=100  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.10 && tcp && tcp.dst == 80), action=(reg9[[6]] = 
chk_lb_aff(); next;)
+  table=??(lr_in_lb_aff_check ), priority=100  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), action=(reg9[[6]] 
= chk_lb_aff(); next;)
 ])
 AT_CHECK([grep "lr_in_dnat " R1flows | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.10 && tcp && tcp.dst == 80), action=(reg4 = 
172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), action=(reg4 = 
172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80);)
   table=??(lr_in_dnat         ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.10 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), 
action=(ct_lb_mark(backends=10.0.0.2:80);)
   table=??(lr_in_dnat         ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.10 && reg4 == 20.0.0.2 && reg2[[0..15]] == 80), 
action=(ct_lb_mark(backends=20.0.0.2:80);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
@@ -9838,7 +9838,7 @@ AT_CAPTURE_FILE([R1flows_skip_snat])
 
 AT_CHECK([grep "lr_in_dnat " R1flows_skip_snat | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.10 && tcp && tcp.dst == 80), 
action=(flags.skip_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.skip_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);)
   table=??(lr_in_dnat         ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.10 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), 
action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; 
skip_snat);)
   table=??(lr_in_dnat         ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.10 && reg4 == 20.0.0.2 && reg2[[0..15]] == 80), 
action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=20.0.0.2:80; 
skip_snat);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
@@ -9859,7 +9859,7 @@ AT_CAPTURE_FILE([R1flows_force_snat])
 
 AT_CHECK([grep "lr_in_dnat " R1flows_force_snat | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.10 && tcp && tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; force_snat);)
   table=??(lr_in_dnat         ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.10 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; 
force_snat);)
   table=??(lr_in_dnat         ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.10 && reg4 == 20.0.0.2 && reg2[[0..15]] == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=20.0.0.2:80; 
force_snat);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
@@ -9879,7 +9879,7 @@ AT_CAPTURE_FILE([R1flows_force_skip_snat])
 
 AT_CHECK([grep "lr_in_dnat " R1flows_force_skip_snat | ovn_strip_lflows], [0], 
[dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.10 && tcp && tcp.dst == 80), 
action=(flags.skip_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.skip_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);)
   table=??(lr_in_dnat         ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.10 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), 
action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; 
skip_snat);)
   table=??(lr_in_dnat         ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.10 && reg4 == 20.0.0.2 && reg2[[0..15]] == 80), 
action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=20.0.0.2:80; 
skip_snat);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
@@ -9903,8 +9903,8 @@ AT_CAPTURE_FILE([R1flows_2lbs])
 
 AT_CHECK([grep "lr_in_dnat " R1flows_2lbs | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.10 && tcp && tcp.dst == 80), 
action=(flags.skip_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.20 && tcp && tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; reg4 = 172.16.0.20; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; force_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.skip_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.16.0.20 && ct_tcp && ct_tcp.dst == 80), 
action=(flags.force_snat_for_lb = 1; reg4 = 172.16.0.20; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; force_snat);)
   table=??(lr_in_dnat         ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.10 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), 
action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; 
skip_snat);)
   table=??(lr_in_dnat         ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.10 && reg4 == 20.0.0.2 && reg2[[0..15]] == 80), 
action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=20.0.0.2:80; 
skip_snat);)
   table=??(lr_in_dnat         ), priority=150  , match=(reg9[[6]] == 1 && 
ct.new && ip4.dst == 172.16.0.20 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), 
action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; 
force_snat);)
@@ -12362,7 +12362,7 @@ check ovn-nbctl --wait=sb ls-lb-add sw0 lb1
 check_engine_stats lflow norecompute compute
 CHECK_NO_CHANGE_AFTER_RECOMPUTE
 
-lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80"')
+lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80"')
 sw0_uuid=$(fetch_column Datapath_Binding _uuid external_ids:name=sw0)
 
 lb_lflow_dp=$(ovn-sbctl --bare --columns logical_datapath list logical_flow 
$lb_lflow_uuid)
@@ -12400,7 +12400,7 @@ check ovn-nbctl --wait=sb set load_balancer lb1 
options:foo=bar
 check_engine_stats lflow recompute nocompute
 CHECK_NO_CHANGE_AFTER_RECOMPUTE
 
-lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80"')
+lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80"')
 
 check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
 check ovn-nbctl --wait=sb clear load_balancer lb2 vips
@@ -12481,7 +12481,7 @@ check ovn-nbctl --wait=sb clear load_balancer lb1 vips
 
 AT_CHECK([ovn-sbctl --bare --columns logical_datapath list logical_flow 
$lb_lflow_uuid], [1], [ignore], [ignore])
 
-lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80"')
+lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80"')
 AT_CHECK([test "$lb_lflow_uuid" = ""])
 
 
@@ -12498,7 +12498,7 @@ check ovn-nbctl --wait=sb ls-lb-add sw1 lb3
 check_engine_stats lflow norecompute compute
 CHECK_NO_CHANGE_AFTER_RECOMPUTE
 
-lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80"')
+lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80"')
 
 lb_lflow_dp=$(ovn-sbctl --bare --columns logical_datapath list logical_flow 
$lb_lflow_uuid)
 AT_CHECK([test "$lb_lflow_dp" = ""])
@@ -15975,7 +15975,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | 
ovn_strip_lflows], [0], [dnl
 AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
   table=??(lr_in_dnat         ), priority=10   , match=(ip && ct.new && inport 
== "lr0-public" && is_chassis_resident("cr-lr0-public")), 
action=(ct_commit_to_zone(dnat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -16019,7 +16019,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | 
ovn_strip_lflows], [0], [dnl
 AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
   table=??(lr_in_dnat         ), priority=10   , match=(ip && ct.new && inport 
== "lr0-public" && is_chassis_resident("cr-lr0-public")), 
action=(ct_commit_to_zone(dnat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -16065,7 +16065,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | 
ovn_strip_lflows], [0], [dnl
 AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
   table=??(lr_in_dnat         ), priority=10   , match=(ip && ct.new), 
action=(ct_commit_to_zone(dnat);)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
@@ -16106,7 +16106,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | 
ovn_strip_lflows], [0], [dnl
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_dnat         ), priority=0    , match=(1), action=(next;)
-  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && tcp && tcp.dst == 8082), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
+  table=??(lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && 
ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082), 
action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted), action=(next;)
   table=??(lr_in_dnat         ), priority=50   , match=(ct.rel && !ct.est && 
!ct.new && !ct.rpl), action=(ct_commit_nat;)
   table=??(lr_in_dnat         ), priority=70   , match=(ct.est && !ct.rel && 
!ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), 
action=(flags.force_snat_for_lb = 1; next;)
diff --git a/tests/ovn.at b/tests/ovn.at
index 596a7be2b..03273a3a8 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -154,7 +154,14 @@ ct_mark.natted = ct_mark[1]
 ct_mark.obs_collector_id = ct_mark[16..23]
 ct_mark.obs_stage = ct_mark[4..5]
 ct_mark.skip_snat = ct_mark[2]
+ct_proto = NXM_NX_CT_NW_PROTO
+ct_sctp = ct_proto == 132
+ct_sctp.dst = NXM_NX_CT_TP_DST
 ct_state = NXM_NX_CT_STATE
+ct_tcp = ct_proto == 6
+ct_tcp.dst = NXM_NX_CT_TP_DST
+ct_udp = ct_proto == 17
+ct_udp.dst = NXM_NX_CT_TP_DST
 ]])
 AT_CLEANUP
 
@@ -26712,14 +26719,14 @@ OVS_WAIT_FOR_OUTPUT(
    ovn-sbctl dump-flows sw0 | grep ct_lb_mark | grep priority=120 | sed 
's/table=..//'], 0,
   [dnl
   (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark;)
-  (ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 
&& tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80; 
hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");)
+  (ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 10.0.0.10 
&& ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; 
ct_lb_mark(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])
 OVS_WAIT_FOR_OUTPUT(
   [ovn-sbctl dump-flows > sbflows2
    ovn-sbctl dump-flows lr0 | grep ct_lb_mark | grep priority=120 | sed 
's/table=..//'], 0,
-  [  (lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && ip4 && 
ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(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 && !ct.rel && ip4 && 
ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(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.
@@ -26753,16 +26760,16 @@ grep "405400000003${svc_mon_src_mac}" | wc -l`]
 AT_CAPTURE_FILE([sbflows3])
 ovn-sbctl dump-flows sw0 > sbflows3
 AT_CHECK(
-  [grep "ip4.dst == 10.0.0.10 && tcp.dst == 80" sbflows3 | grep priority=120 |\
+  [grep "ip4.dst == 10.0.0.10" sbflows3 | grep priority=120 |\
    ovn_strip_lflows], [0], [dnl
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && tcp.dst == 80), action=(drop;)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip4.dst == 
10.0.0.10 && ct_tcp.dst == 80), action=(drop;)
   table=??(ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && 
ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] 
= 80; ct_lb_mark;)
 ])
 
 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.new && !ct.rel && ip4 && 
ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80 && 
is_chassis_resident("cr-lr0-public")), action=(drop;)
+  (lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && ip4 && 
ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80 && 
is_chassis_resident("cr-lr0-public")), action=(drop;)
 ])
 
 # Delete sw0-p1
@@ -26918,14 +26925,14 @@ OVS_WAIT_FOR_OUTPUT(
    ovn-sbctl dump-flows sw0 | grep ct_lb_mark | grep priority=120 | sed 
's/table=..//'], 0,
   [dnl
   (ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && ip6.dst == 
2002::a && tcp.dst == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] = 80; 
ct_lb_mark;)
-  (ls_in_lb           ), priority=120  , match=(ct.new && ip6.dst == 2002::a 
&& tcp.dst == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] = 80; 
ct_lb_mark(backends=[[2001::3]]:80,[[2002::3]]:80; 
hash_fields="ipv6_dst,ipv6_src,tcp_dst,tcp_src");)
+  (ls_in_lb           ), priority=120  , match=(ct.new && ip6.dst == 2002::a 
&& ct_tcp.dst == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] = 80; 
ct_lb_mark(backends=[[2001::3]]:80,[[2002::3]]:80; 
hash_fields="ipv6_dst,ipv6_src,tcp_dst,tcp_src");)
 ])
 
 AT_CAPTURE_FILE([sbflows2])
 OVS_WAIT_FOR_OUTPUT(
   [ovn-sbctl dump-flows > sbflows2
    ovn-sbctl dump-flows lr0 | grep ct_lb_mark | grep priority=120 | sed 
's/table=..//'], 0,
-  [  (lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && ip6 && 
ip6.dst == 2002::a && tcp && tcp.dst == 80 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=[[2001::3]]:80,[[2002::3]]:80; 
hash_fields="ipv6_dst,ipv6_src,tcp_dst,tcp_src");)
+  [  (lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && ip6 && 
ip6.dst == 2002::a && ct_tcp && ct_tcp.dst == 80 && 
is_chassis_resident("cr-lr0-public")), 
action=(ct_lb_mark(backends=[[2001::3]]:80,[[2002::3]]:80; 
hash_fields="ipv6_dst,ipv6_src,tcp_dst,tcp_src");)
 ])
 
 # get the svc monitor mac.
@@ -26958,16 +26965,16 @@ grep "405400000003${svc_mon_src_mac}" | wc -l`]
 AT_CAPTURE_FILE([sbflows3])
 ovn-sbctl dump-flows sw0 > sbflows3
 AT_CHECK(
-  [grep "ip6.dst == 2002::a && tcp.dst == 80" sbflows3 | grep priority=120 |\
+  [grep "ip6.dst == 2002::a" sbflows3 | grep priority=120 |\
    ovn_strip_lflows], [0], [dnl
-  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip6.dst == 
2002::a && tcp.dst == 80), action=(drop;)
+  table=??(ls_in_lb           ), priority=120  , match=(ct.new && ip6.dst == 
2002::a && ct_tcp.dst == 80), action=(drop;)
   table=??(ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 && 
ip6.dst == 2002::a && tcp.dst == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] = 
80; ct_lb_mark;)
 ])
 
 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.new && !ct.rel && ip6 && 
ip6.dst == 2002::a && tcp && tcp.dst == 80 && 
is_chassis_resident("cr-lr0-public")), action=(drop;)
+  (lr_in_dnat         ), priority=120  , match=(ct.new && !ct.rel && ip6 && 
ip6.dst == 2002::a && ct_tcp && ct_tcp.dst == 80 && 
is_chassis_resident("cr-lr0-public")), action=(drop;)
 ])
 
 # Delete sw0-p1
diff --git a/tests/system-ovn-kmod.at b/tests/system-ovn-kmod.at
index f0d4de1f8..438908335 100644
--- a/tests/system-ovn-kmod.at
+++ b/tests/system-ovn-kmod.at
@@ -598,147 +598,6 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port 
patch-.*/d
 AT_CLEANUP
 ])
 
-OVN_FOR_EACH_NORTHD([
-AT_SETUP([LB correctly handles fragmented traffic])
-AT_KEYWORDS([ovnlb])
-
-CHECK_CONNTRACK()
-CHECK_CONNTRACK_NAT()
-
-ovn_start
-OVS_TRAFFIC_VSWITCHD_START()
-ADD_BR([br-int])
-ADD_BR([br-ext])
-
-# Logical network:
-# 2 logical switches "public" (192.168.1.0/24) and "internal" (172.16.1.0/24)
-# connected to a router lr.
-# internal has a server.
-# client is connected through localnet.
-
-check ovs-ofctl add-flow br-ext action=normal
-# Set external-ids in br-int needed for ovn-controller
-check ovs-vsctl \
-        -- set Open_vSwitch . external-ids:system-id=hv1 \
-        -- set Open_vSwitch . 
external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
-        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
-        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
-        -- set bridge br-int fail-mode=secure 
other-config:disable-in-band=true \
-        -- set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext
-
-
-# Start ovn-controller
-start_daemon ovn-controller
-
-check ovn-nbctl lr-add lr
-check ovn-nbctl ls-add internal
-check ovn-nbctl ls-add public
-
-check ovn-nbctl lrp-add lr lr-pub 00:00:01:01:02:03 192.168.1.1/24
-check ovn-nbctl lsp-add  public pub-lr -- set Logical_Switch_Port pub-lr \
-    type=router options:router-port=lr-pub addresses=\"00:00:01:01:02:03\"
-
-check ovn-nbctl lrp-add lr lr-internal 00:00:01:01:02:04 172.16.1.1/24
-check ovn-nbctl lsp-add internal internal-lr -- set Logical_Switch_Port 
internal-lr \
-    type=router options:router-port=lr-internal addresses=\"00:00:01:01:02:04\"
-
-check ovn-nbctl lsp-add public ln_port \
-                -- lsp-set-addresses ln_port unknown \
-                -- lsp-set-type ln_port localnet \
-                -- lsp-set-options ln_port network_name=phynet
-
-ADD_NAMESPACES(client)
-ADD_VETH(client, client, br-ext, "192.168.1.2/24", "f0:00:00:01:02:03", \
-         "192.168.1.1")
-NS_EXEC([client], [ip l set dev client mtu 900])
-
-ADD_NAMESPACES(server)
-ADD_VETH(server, server, br-int, "172.16.1.2/24", "f0:00:0f:01:02:03", \
-         "172.16.1.1")
-check ovn-nbctl lsp-add internal server \
--- lsp-set-addresses server "f0:00:0f:01:02:03 172.16.1.2"
-
-check ovn-nbctl set logical_router lr options:chassis=hv1
-
-AT_DATA([client.py], [dnl
-import socket
-
-sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-sock.sendto(b"x" * 1000, ("172.16.1.20", 4242))
-])
-
-test_fragmented_traffic() {
-    check ovn-nbctl --wait=hv sync
-
-    check ovs-appctl dpctl/flush-conntrack
-
-    NETNS_DAEMONIZE([server], [nc -l -u 172.16.1.2 4242 > /dev/null], 
[server.pid])
-
-    # Collect ICMP packets on client side
-    NETNS_START_TCPDUMP([client], [-U -i client -vnne udp], [tcpdump-client])
-
-    # Collect UDP packets on server side
-    NETNS_START_TCPDUMP([server], [-U -i server -vnne 'udp and ip[[6:2]] > 0 
and not ip[[6]] = 64'], [tcpdump-server])
-
-    NS_CHECK_EXEC([client], [$PYTHON3 ./client.py])
-    OVS_WAIT_UNTIL([test "$(cat tcpdump-server.tcpdump | wc -l)" = "4"])
-
-    kill $(cat tcpdump-client.pid) $(cat tcpdump-server.pid) $(cat server.pid)
-}
-
-AS_BOX([LB on router without port and protocol])
-check ovn-nbctl lb-add lb1 172.16.1.20 172.16.1.2
-check ovn-nbctl lr-lb-add lr lb1
-
-test_fragmented_traffic
-
-check ovn-nbctl lr-lb-del lr
-check ovn-nbctl lb-del lb1
-
-AS_BOX([LB on router with port and protocol])
-check ovn-nbctl lb-add lb1 172.16.1.20:4242 172.16.1.2:4242 udp
-check ovn-nbctl lr-lb-add lr lb1
-
-test_fragmented_traffic
-
-check ovn-nbctl lr-lb-del lr
-check ovn-nbctl lb-del lb1
-
-AS_BOX([LB on switch without port and protocol])
-check ovn-nbctl lb-add lb1 172.16.1.20 172.16.1.2
-check ovn-nbctl ls-lb-add public lb1
-
-test_fragmented_traffic
-
-check ovn-nbctl ls-lb-del public
-check ovn-nbctl lb-del lb1
-
-AS_BOX([LB on switch witho port and protocol])
-check ovn-nbctl lb-add lb1 172.16.1.20:4242 172.16.1.2:4242 udp
-check ovn-nbctl ls-lb-add public lb1
-
-test_fragmented_traffic
-
-check ovn-nbctl ls-lb-del public
-check ovn-nbctl lb-del lb1
-
-OVN_CLEANUP_CONTROLLER([hv1])
-
-as ovn-sb
-OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-
-as ovn-nb
-OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-
-as northd
-OVS_APP_EXIT_AND_WAIT([ovn-northd])
-
-as
-OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
-/connection dropped.*/d"])
-AT_CLEANUP
-])
-
 OVN_FOR_EACH_NORTHD([
 AT_SETUP([SNAT in separate zone from DNAT])
 
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index ac9dedbf3..9de017ed0 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -17808,3 +17808,148 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port 
patch-.*/d
 
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([LB correctly handles fragmented traffic])
+AT_KEYWORDS([ovnlb])
+
+CHECK_CONNTRACK()
+CHECK_CONNTRACK_NAT()
+
+ovn_start
+OVS_TRAFFIC_VSWITCHD_START()
+ADD_BR([br-int])
+ADD_BR([br-ext])
+
+# Logical network:
+# 2 logical switches "public" (192.168.1.0/24) and "internal" (172.16.1.0/24)
+# connected to a router lr.
+# internal has a server.
+# client is connected through localnet.
+
+check ovs-ofctl add-flow br-ext action=normal
+# Set external-ids in br-int needed for ovn-controller
+check ovs-vsctl \
+        -- set Open_vSwitch . external-ids:system-id=hv1 \
+        -- set Open_vSwitch . 
external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
+        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
+        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
+        -- set bridge br-int fail-mode=secure 
other-config:disable-in-band=true \
+        -- set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext
+
+
+# Start ovn-controller
+start_daemon ovn-controller
+
+# Set the minimal fragment size for userspace DP.
+# Note that this call will fail for system DP as this setting is not supported 
there.
+ovs-appctl dpctl/ipf-set-min-frag v4 500
+
+check ovn-nbctl lr-add lr
+check ovn-nbctl ls-add internal
+check ovn-nbctl ls-add public
+
+check ovn-nbctl lrp-add lr lr-pub 00:00:01:01:02:03 192.168.1.1/24
+check ovn-nbctl lsp-add  public pub-lr -- set Logical_Switch_Port pub-lr \
+    type=router options:router-port=lr-pub addresses=\"00:00:01:01:02:03\"
+
+check ovn-nbctl lrp-add lr lr-internal 00:00:01:01:02:04 172.16.1.1/24
+check ovn-nbctl lsp-add internal internal-lr -- set Logical_Switch_Port 
internal-lr \
+    type=router options:router-port=lr-internal addresses=\"00:00:01:01:02:04\"
+
+check ovn-nbctl lsp-add public ln_port \
+                -- lsp-set-addresses ln_port unknown \
+                -- lsp-set-type ln_port localnet \
+                -- lsp-set-options ln_port network_name=phynet
+
+ADD_NAMESPACES(client)
+ADD_VETH(client, client, br-ext, "192.168.1.2/24", "f0:00:00:01:02:03", \
+         "192.168.1.1")
+NS_EXEC([client], [ip l set dev client mtu 900])
+
+ADD_NAMESPACES(server)
+ADD_VETH(server, server, br-int, "172.16.1.2/24", "f0:00:0f:01:02:03", \
+         "172.16.1.1")
+check ovn-nbctl lsp-add internal server \
+-- lsp-set-addresses server "f0:00:0f:01:02:03 172.16.1.2"
+
+check ovn-nbctl set logical_router lr options:chassis=hv1
+
+AT_DATA([client.py], [dnl
+import socket
+
+sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+sock.sendto(b"x" * 1000, ("172.16.1.20", 4242))
+])
+
+test_fragmented_traffic() {
+    check ovn-nbctl --wait=hv sync
+
+    check ovs-appctl dpctl/flush-conntrack
+
+    NETNS_DAEMONIZE([server], [nc -l -u 172.16.1.2 4242 > /dev/null], 
[server.pid])
+
+    # Collect ICMP packets on client side
+    NETNS_START_TCPDUMP([client], [-U -i client -vnne udp], [tcpdump-client])
+
+    # Collect UDP packets on server side
+    NETNS_START_TCPDUMP([server], [-U -i server -vnne 'udp and ip[[6:2]] > 0 
and not ip[[6]] = 64'], [tcpdump-server])
+
+    NS_CHECK_EXEC([client], [$PYTHON3 ./client.py])
+    OVS_WAIT_UNTIL([test "$(cat tcpdump-server.tcpdump | wc -l)" = "4"])
+
+    kill $(cat tcpdump-client.pid) $(cat tcpdump-server.pid) $(cat server.pid)
+}
+
+AS_BOX([LB on router without port and protocol])
+check ovn-nbctl lb-add lb1 172.16.1.20 172.16.1.2
+check ovn-nbctl lr-lb-add lr lb1
+
+test_fragmented_traffic
+
+check ovn-nbctl lr-lb-del lr
+check ovn-nbctl lb-del lb1
+
+AS_BOX([LB on router with port and protocol])
+check ovn-nbctl lb-add lb1 172.16.1.20:4242 172.16.1.2:4242 udp
+check ovn-nbctl lr-lb-add lr lb1
+
+test_fragmented_traffic
+
+check ovn-nbctl lr-lb-del lr
+check ovn-nbctl lb-del lb1
+
+AS_BOX([LB on switch without port and protocol])
+check ovn-nbctl lb-add lb1 172.16.1.20 172.16.1.2
+check ovn-nbctl ls-lb-add public lb1
+
+test_fragmented_traffic
+
+check ovn-nbctl ls-lb-del public
+check ovn-nbctl lb-del lb1
+
+AS_BOX([LB on switch witho port and protocol])
+check ovn-nbctl lb-add lb1 172.16.1.20:4242 172.16.1.2:4242 udp
+check ovn-nbctl ls-lb-add public lb1
+
+test_fragmented_traffic
+
+check ovn-nbctl ls-lb-del public
+check ovn-nbctl lb-del lb1
+
+OVN_CLEANUP_CONTROLLER([hv1])
+
+as ovn-sb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as ovn-nb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as northd
+OVS_APP_EXIT_AND_WAIT([ovn-northd])
+
+as
+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
+/connection dropped.*/d"])
+AT_CLEANUP
+])
-- 
2.49.0

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

Reply via email to