When adding two SB flows with the same vip but different protocols, only
the most recent flow will be added due to the `if` statement:

            if (!sset_contains(&all_ips, lb_vip->vip_str)) {
                sset_add(&all_ips, lb_vip->vip_str);

This can cause unexpected behaviour when two load balancers with
the same VIP (and different protocols) are added to a logical router.

This is due to the addition of "protocol" to the match in
defrag table flows in a previous commit. Revert that change.

This bug was discovered through the OVN CI (ovn-kubernetes.yml).

Fixes: 384a7c6237da ("northd: Refactor Logical Flows for routers with DNAT/Load 
Balancers")
Signed-off-by: Mark Gray <[email protected]>
---
 northd/ovn-northd.c  |  8 --------
 northd/ovn_northd.dl |  9 +--------
 tests/ovn-northd.at  | 46 ++++++++++++++++++++++----------------------
 3 files changed, 24 insertions(+), 39 deletions(-)

diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 999c3f482c29..5fab62c0fcf7 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -9219,11 +9219,6 @@ build_lrouter_lb_flows(struct hmap *lflows, struct 
ovn_datapath *od,
         for (size_t j = 0; j < lb->n_vips; j++) {
             struct ovn_lb_vip *lb_vip = &lb->vips[j];
 
-            bool is_udp = nullable_string_is_equal(nb_lb->protocol, "udp");
-            bool is_sctp = nullable_string_is_equal(nb_lb->protocol,
-                                                    "sctp");
-            const char *proto = is_udp ? "udp" : is_sctp ? "sctp" : "tcp";
-
             struct ds defrag_actions = DS_EMPTY_INITIALIZER;
             if (!sset_contains(&all_ips, lb_vip->vip_str)) {
                 sset_add(&all_ips, lb_vip->vip_str);
@@ -9249,9 +9244,6 @@ build_lrouter_lb_flows(struct hmap *lflows, struct 
ovn_datapath *od,
                                   lb_vip->vip_str);
                 }
 
-                if (lb_vip->vip_port) {
-                    ds_put_format(match, " && %s", proto);
-                }
                 ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DEFRAG,
                                         100, ds_cstr(match),
                                         ds_cstr(&defrag_actions),
diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl
index ceeabe6f384e..b37da86f76aa 100644
--- a/northd/ovn_northd.dl
+++ b/northd/ovn_northd.dl
@@ -6167,14 +6167,7 @@ for (RouterLBVIP(
          *    pick a DNAT ip address from a group.
          * 2. If there are L4 ports in load balancing rules, we
          *    need the defragmentation to match on L4 ports. */
-        var match1 = "ip && ${ipX}.dst == ${ip_address}" in
-        var match2 =
-            if (port != 0) {
-                " && ${proto}"
-            } else {
-                ""
-            } in
-        var __match = match1 ++ match2 in
+        var __match = "ip && ${ipX}.dst == ${ip_address}" in
         var xx = ip_address.xxreg() in
         var __actions = "${xx}${rEG_NEXT_HOP()} = ${ip_address}; ct_dnat;" in
         /* One of these flows must be created for each unique LB VIP address.
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 11461d3f4c2a..072616898d63 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -3167,7 +3167,7 @@ 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 == 
10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
10.0.0.10), action=(reg0 = 10.0.0.10; ct_dnat;)
 ])
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -3200,7 +3200,7 @@ 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 == 
10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
10.0.0.10), action=(reg0 = 10.0.0.10; ct_dnat;)
 ])
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -3243,7 +3243,7 @@ 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 == 
10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
10.0.0.10), action=(reg0 = 10.0.0.10; ct_dnat;)
 ])
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -3300,7 +3300,7 @@ 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 == 
10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
10.0.0.10), action=(reg0 = 10.0.0.10; ct_dnat;)
 ])
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -3344,7 +3344,7 @@ 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 == 
10.0.0.20 && tcp), action=(reg0 = 10.0.0.20; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
10.0.0.20), action=(reg0 = 10.0.0.20; ct_dnat;)
 ])
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | grep skip_snat_for_lb | sort], [0], [dnl
@@ -4361,10 +4361,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 == 
10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.100 && tcp), action=(reg0 = 172.168.0.100; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
10.0.0.10), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.100), action=(reg0 = 172.168.0.100; ct_dnat;)
   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=100  , match=(ip && ip4.dst == 
172.168.0.210 && udp), action=(reg0 = 172.168.0.210; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.210), action=(reg0 = 172.168.0.210; ct_dnat;)
 ])
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -4421,10 +4421,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 == 
10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.100 && tcp), action=(reg0 = 172.168.0.100; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
10.0.0.10), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.100), action=(reg0 = 172.168.0.100; ct_dnat;)
   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=100  , match=(ip && ip4.dst == 
172.168.0.210 && udp), action=(reg0 = 172.168.0.210; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.210), action=(reg0 = 172.168.0.210; ct_dnat;)
 ])
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -4476,10 +4476,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 == 
10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.100 && tcp), action=(reg0 = 172.168.0.100; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
10.0.0.10), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.100), action=(reg0 = 172.168.0.100; ct_dnat;)
   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=100  , match=(ip && ip4.dst == 
172.168.0.210 && udp), action=(reg0 = 172.168.0.210; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.210), action=(reg0 = 172.168.0.210; ct_dnat;)
 ])
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -4534,11 +4534,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 == 
10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.10 && tcp), action=(reg0 = 172.168.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.100 && tcp), action=(reg0 = 172.168.0.100; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
10.0.0.10), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.10), action=(reg0 = 172.168.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.100), action=(reg0 = 172.168.0.100; ct_dnat;)
   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=100  , match=(ip && ip4.dst == 
172.168.0.210 && udp), action=(reg0 = 172.168.0.210; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.210), action=(reg0 = 172.168.0.210; ct_dnat;)
 ])
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
@@ -4605,12 +4605,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=100  , match=(ip && ip4.dst == 
10.0.0.10 && tcp), action=(reg0 = 10.0.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.10 && tcp), action=(reg0 = 172.168.0.10; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.100 && tcp), action=(reg0 = 172.168.0.100; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
10.0.0.10), action=(reg0 = 10.0.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.10), action=(reg0 = 172.168.0.10; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.100), action=(reg0 = 172.168.0.100; ct_dnat;)
   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=100  , match=(ip && ip4.dst == 
172.168.0.210 && udp), action=(reg0 = 172.168.0.210; ct_dnat;)
-  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip6.dst == 
def0::2 && tcp), action=(xxreg0 = def0::2; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip4.dst == 
172.168.0.210), action=(reg0 = 172.168.0.210; ct_dnat;)
+  table=5 (lr_in_defrag       ), priority=100  , match=(ip && ip6.dst == 
def0::2), action=(xxreg0 = def0::2; ct_dnat;)
 ])
 
 AT_CHECK([grep "lr_in_dnat" lr0flows | sort], [0], [dnl
-- 
2.27.0

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

Reply via email to