when ovn-monitor-all is set to false the ovn-controller sets
ovn-installed on OVS interfaces too early. ovn-controller needs to wait
for the response from the southbound database with the updates to the
newly monitored southbound fields and after that wait for flows to be
installed in OVS before labeling as installed.

Reported-at: https://redhat.atlassian.net/browse/FDP-2887
Signed-off-by: Jacob Tanenbaum <[email protected]>

diff --git a/controller/if-status.c b/controller/if-status.c
index ee9337e63..a9f31fe50 100644
--- a/controller/if-status.c
+++ b/controller/if-status.c
@@ -18,6 +18,7 @@
 #include "binding.h"
 #include "if-status.h"
 #include "lib/ofctrl-seqno.h"
+#include "local_data.h"
 #include "ovsport.h"
 #include "simap.h"
 
@@ -590,12 +591,18 @@ if_status_mgr_update(struct if_status_mgr *mgr,
         }
     }
 
+    bool update_seqno = false;
     /* Update pb->chassis in case it's not set (previous update still in fly
      * or pb->chassis was overwitten by another chassis.
      */
     if (!sb_readonly) {
         HMAPX_FOR_EACH_SAFE (node, &mgr->ifaces_per_state[OIF_INSTALL_FLOWS]) {
             struct ovs_iface *iface = node->data;
+            if (iface->is_vif) {
+                ovs_iface_set_state(mgr, iface, OIF_INSTALL_FLOWS);
+                iface->install_seqno = mgr->iface_seqno + 1;
+                update_seqno = true;
+            }
             if (!local_bindings_pb_chassis_is_set(bindings, iface->id,
                 chassis_rec)) {
                 long long int now = time_msec();
@@ -614,7 +621,6 @@ if_status_mgr_update(struct if_status_mgr *mgr,
 
     /* Move newly claimed interfaces from OIF_CLAIMED to OIF_INSTALL_FLOWS.
      */
-    bool new_ifaces = false;
     if (!sb_readonly) {
         HMAPX_FOR_EACH_SAFE (node, &mgr->ifaces_per_state[OIF_CLAIMED]) {
             struct ovs_iface *iface = node->data;
@@ -624,7 +630,7 @@ if_status_mgr_update(struct if_status_mgr *mgr,
             if (iface->is_vif) {
                 ovs_iface_set_state(mgr, iface, OIF_INSTALL_FLOWS);
                 iface->install_seqno = mgr->iface_seqno + 1;
-                new_ifaces = true;
+                update_seqno = true;
             } else {
                 ovs_iface_set_state(mgr, iface, OIF_MARK_UP);
             }
@@ -659,7 +665,7 @@ if_status_mgr_update(struct if_status_mgr *mgr,
      * Request a seqno update when the flows for new interfaces have been
      * installed in OVS.
      */
-    if (new_ifaces) {
+    if (update_seqno) {
         mgr->iface_seqno++;
         ofctrl_seqno_update_create(mgr->iface_seq_type_pb_cfg,
                                    mgr->iface_seqno);
@@ -694,6 +700,8 @@ if_status_mgr_run(struct if_status_mgr *mgr,
                   const struct sbrec_chassis *chassis_rec,
                   const struct ovsrec_interface_table *iface_table,
                   const struct sbrec_port_binding_table *pb_table,
+                  const struct hmap *local_datapaths,
+                  unsigned int ovnsb_cond_seqno,
                   bool sb_readonly, bool ovs_readonly)
 {
     struct ofctrl_acked_seqnos *acked_seqnos =
@@ -703,10 +711,34 @@ if_status_mgr_run(struct if_status_mgr *mgr,
     /* Move interfaces from state OIF_INSTALL_FLOWS to OIF_MARK_UP if a
      * notification has been received aabout their flows being installed
      * in OVS.
+     *
+     * In the ovn-monitor-all=false case it is possible that we have not
+     * received the update that the southbound database is monitoring a new
+     *  datapath. Check for the update before continuing.
      */
     HMAPX_FOR_EACH_SAFE (node, &mgr->ifaces_per_state[OIF_INSTALL_FLOWS]) {
         struct ovs_iface *iface = node->data;
 
+        bool sb_missing_update = false;
+        if (local_datapaths) {
+            const struct sbrec_port_binding *pb =
+                sbrec_port_binding_table_get_for_uuid(pb_table,
+                                                      &iface->pb_uuid);
+            const struct local_datapath *ld;
+            HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
+                if (uuid_equals(&ld->datapath->header_.uuid,
+                                &pb->datapath->header_.uuid) &&
+                    ld->expected_cond_seqno > ovnsb_cond_seqno) {
+
+                    sb_missing_update = true;
+                    break;
+                }
+            }
+        }
+        if (sb_missing_update) {
+            continue;
+        }
+
         if (!ofctrl_acked_seqnos_contains(acked_seqnos,
                                           iface->install_seqno)) {
             continue;
diff --git a/controller/if-status.h b/controller/if-status.h
index d15ca3008..a877ebe2b 100644
--- a/controller/if-status.h
+++ b/controller/if-status.h
@@ -49,6 +49,8 @@ void if_status_mgr_run(struct if_status_mgr *mgr, struct 
local_binding_data *,
                        const struct sbrec_chassis *,
                        const struct ovsrec_interface_table *iface_table,
                        const struct sbrec_port_binding_table *pb_table,
+                       const struct hmap *local_datapaths,
+                       const unsigned int ovnsb_cond_seqno,
                        bool sb_readonly, bool ovs_readonly);
 void if_status_mgr_get_memory_usage(struct if_status_mgr *mgr,
                                     struct simap *usage);
diff --git a/controller/local_data.h b/controller/local_data.h
index 948c1a935..01dd9516a 100644
--- a/controller/local_data.h
+++ b/controller/local_data.h
@@ -65,6 +65,9 @@ struct local_datapath {
 
     struct shash external_ports;
     struct shash multichassis_ports;
+
+    /* the expected seqno from the sb to be fully udpated for this datapath */
+    unsigned int expected_cond_seqno;
 };
 
 struct local_datapath *local_datapath_alloc(
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 4161fe2b3..81f6bdb47 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -443,6 +443,15 @@ out:;
         expected_cond_seqno = MAX(expected_cond_seqno, cond_seqnos[i]);
     }
 
+    if (!monitor_all && local_datapaths) {
+        struct local_datapath *ld;
+        HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
+            if (ld->expected_cond_seqno == 0) {
+                ld->expected_cond_seqno = expected_cond_seqno;
+            }
+        }
+    }
+
     ovsdb_idl_condition_destroy(&pb);
     ovsdb_idl_condition_destroy(&lf);
     ovsdb_idl_condition_destroy(&ldpg);
@@ -7903,6 +7912,8 @@ main(int argc, char *argv[])
                                                   ovs_idl_loop.idl),
                                       sbrec_port_binding_table_get(
                                                  ovnsb_idl_loop.idl),
+                                      &runtime_data->local_datapaths,
+                                      ovnsb_cond_seqno,
                                       !ovnsb_idl_txn, !ovs_idl_txn);
                     stopwatch_stop(IF_STATUS_MGR_RUN_STOPWATCH_NAME,
                                    time_msec());
diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
index c98de9bc4..f3a83176f 100644
--- a/tests/ovn-controller.at
+++ b/tests/ovn-controller.at
@@ -3944,3 +3944,68 @@ OVN_CLEANUP([hv1], [hv2
 /already has encap ip.*cannot duplicate on/d])
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([ovn-installed])
+ovn_start
+
+net_add n1
+sim_add hv1
+
+as hv1
+ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.1
+ovn-appctl vlog/set dbg
+ovs-vsctl add-port br-int vif1 -- \
+    set Interface vif1 external-ids:iface-id=lsp1
+
+
+check ovn-nbctl ls-add ls1
+sleep_controller hv1
+check ovn-nbctl --wait=sb lsp-add ls1 lsp1 -- \
+                          lsp-set-addresses lsp1 "f0:00:00:00:00:01 10.0.0.1"
+
+sleep_sb
+wake_up_controller hv1
+
+# Wait for pflow for lsp1
+OVS_WAIT_UNTIL([
+    ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=vif1)
+    echo "vif1 port=$ofport"
+    test -n "$ofport" && test 1 -le $(as hv1 ovs-ofctl dump-flows br-int | 
grep -c in_port=$ofport)
+])
+
+# if ovn-installed in ovs, all flows should be installed.
+# In that case, there should be at least one flow with lsp1 address.
+OVS_WAIT_UNTIL([
+    ovn_installed=$(as hv1 ovs-vsctl get Interface vif1 
external_ids:ovn-installed)
+    flow_count=$(as hv1 ovs-ofctl dump-flows br-int | grep -Fc "10.0.0.1")
+    # for the monitor-all=true case the flow gets installed because 
ovn-controller is monitoring all
+    # tavles in OVN_SOUTHBOUND.
+    if test -n "$ovn_installed"; then
+        as hv1 ovs-ofctl dump-flows br-int > output
+        test $flow_count -ge 1
+    else
+        true
+    fi
+])
+
+wake_up_sb
+# after the southbound db has woekn up and can send the update to the 
ovn-controller not monitoring all
+# tables in the southbound db it should be able to install the interface.
+OVS_WAIT_UNTIL([
+    ovn_installed=$(as hv1 ovs-vsctl get Interface vif1 
external_ids:ovn-installed)
+    flow_count=$(as hv1 ovs-ofctl dump-flows br-int | grep -Fc "10.0.0.1")
+    echo "installed=$ovn_installed, count=$flow_count"
+    if test -n "$ovn_installed"; then
+        as hv1 ovs-ofctl dump-flows br-int > output
+        test $flow_count -ge 1
+    else
+        false
+    fi
+])
+wait_for_ports_up
+
+OVN_CLEANUP([hv1])
+AT_CLEANUP
+])
-- 
2.53.0

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

Reply via email to