@@ -211,6 +211,152 @@ static char *get_file_system_id(void)
211211 free (filename );
212212 return ret ;
213213}
214+
215+ /* Set/unset flow-restore-wait, and inc ovs next_cfg if false
216+ * When set to true, also sets ovn-managed-flow-restore-wait to true to
217+ * indicate ownership */
218+ static void
219+ set_flow_restore_wait (struct ovsdb_idl_txn * ovs_idl_txn ,
220+ const struct ovsrec_open_vswitch * cfg ,
221+ const struct smap * other_config ,
222+ const bool val , bool ovn_managed )
223+ {
224+ struct smap new_config ;
225+ smap_clone (& new_config , other_config );
226+ smap_replace (& new_config , "flow-restore-wait" , val ? "true" : "false" );
227+ ovsrec_open_vswitch_set_other_config (cfg , & new_config );
228+ if (val ) {
229+ ovsrec_open_vswitch_update_external_ids_setkey (
230+ cfg , "ovn-managed-flow-restore-wait" , "true" );
231+ } else if (ovn_managed ) {
232+ ovsrec_open_vswitch_update_external_ids_delkey (
233+ cfg , "ovn-managed-flow-restore-wait" );
234+ }
235+ ovsdb_idl_txn_increment (ovs_idl_txn , & cfg -> header_ ,
236+ & ovsrec_open_vswitch_col_next_cfg , true);
237+ smap_destroy (& new_config );
238+ }
239+
240+ static void
241+ manage_flow_restore_wait (struct ovsdb_idl_txn * ovs_idl_txn ,
242+ const struct ovsrec_open_vswitch * cfg ,
243+ uint64_t ofctrl_cur_cfg , uint64_t ovs_next_cfg ,
244+ int ovs_txn_status , bool is_ha_gw )
245+ {
246+ enum flow_restore_wait_state {
247+ FRW_INIT , /* Initial state */
248+ FRW_WAIT_TXN_COMPLETE , /* Sent false, waiting txn to complete */
249+ FRW_TXN_SUCCESS , /* Txn completed. Waiting for OVS Ack. */
250+ FRW_DONE /* Everything completed */
251+ };
252+
253+ static int64_t frw_next_cfg ;
254+ static enum flow_restore_wait_state frw_state ;
255+ static bool ofctrl_was_connected = false;
256+
257+ bool ofctrl_connected = ofctrl_is_connected ();
258+
259+ if (!ovs_idl_txn || !cfg ) {
260+ return ;
261+ }
262+
263+ /* If OVS is stopped/started, make sure flow-restore-wait is toggled. */
264+ if (ofctrl_connected && !ofctrl_was_connected ) {
265+ frw_state = FRW_INIT ;
266+ }
267+ ofctrl_was_connected = ofctrl_connected ;
268+
269+ if (!ofctrl_connected ) {
270+ return ;
271+ }
272+
273+ bool frw = smap_get_bool (& cfg -> other_config , "flow-restore-wait" , false);
274+ bool ovn_managed_once = smap_get_bool (& cfg -> external_ids ,
275+ "ovn-managed-flow-restore-wait" ,
276+ false);
277+
278+ if (frw && !ovn_managed_once ) {
279+ /* frw has been set by ovs-ctl. Do not touch. */
280+ return ;
281+ }
282+
283+ if (!is_ha_gw ) {
284+ if (frw ) {
285+ /* frw has once been set by OVN. We are now not an HA chassis
286+ * anymore, unset it. */
287+ set_flow_restore_wait (ovs_idl_txn , cfg , & cfg -> other_config ,
288+ false, ovn_managed_once );
289+ }
290+ /* else we are not an HA chassis and frw is false. Ignore it. */
291+ return ;
292+ }
293+
294+ switch (frw_state ) {
295+ case FRW_INIT :
296+ if (ofctrl_cur_cfg > 0 ) {
297+ set_flow_restore_wait (ovs_idl_txn , cfg , & cfg -> other_config ,
298+ false, ovn_managed_once );
299+ frw_state = FRW_WAIT_TXN_COMPLETE ;
300+ VLOG_INFO ("Setting flow-restore-wait=false "
301+ "(cur_cfg=%" PRIu64 ")" , ofctrl_cur_cfg );
302+ }
303+ break ;
304+
305+ case FRW_WAIT_TXN_COMPLETE :
306+ /* if (ovs_idl_txn != NULL), the transaction completed.
307+ * When the transaction completed, it either failed
308+ * (ovs_txn_status == 0) or succeeded (ovs_txn_status != 0). */
309+ if (ovs_txn_status == 0 ) {
310+ /* Previous transaction failed. */
311+ set_flow_restore_wait (ovs_idl_txn , cfg , & cfg -> other_config ,
312+ false, ovn_managed_once );
313+ break ;
314+ }
315+ /* txn succeeded, get next_cfg */
316+ frw_next_cfg = ovs_next_cfg ;
317+ frw_state = FRW_TXN_SUCCESS ;
318+ /* fall through */
319+
320+ case FRW_TXN_SUCCESS :
321+ if (ovs_next_cfg < frw_next_cfg ) {
322+ /* DB was reset, next_cfg went backwards. */
323+ VLOG_INFO ("OVS DB reset (next_cfg %" PRId64 " -> %" PRIu64 "), "
324+ "resetting state" ,
325+ frw_next_cfg , ovs_next_cfg );
326+ set_flow_restore_wait (ovs_idl_txn , cfg , & cfg -> other_config ,
327+ false, ovn_managed_once );
328+ frw_state = FRW_WAIT_TXN_COMPLETE ;
329+ break ;
330+ }
331+
332+ if (!frw ) {
333+ if (cfg -> cur_cfg >= frw_next_cfg ) {
334+ set_flow_restore_wait (ovs_idl_txn , cfg , & cfg -> other_config ,
335+ true, ovn_managed_once );
336+ frw_state = FRW_DONE ;
337+ VLOG_INFO ("Setting flow-restore-wait=true" );
338+ }
339+ } else {
340+ /* The transaction to false succeeded but frw is true.
341+ * So, another task already set it to true. */
342+ frw_state = FRW_DONE ;
343+ VLOG_INFO ("flow-restore-wait was already true" );
344+ }
345+ break ;
346+ case FRW_DONE :
347+ if (!frw ) {
348+ /* frw has been removed (e.g. by ovs-ctl restart) or is false
349+ * (e.g. txn failed.) */
350+ set_flow_restore_wait (ovs_idl_txn , cfg , & cfg -> other_config ,
351+ false, ovn_managed_once );
352+ frw_state = FRW_WAIT_TXN_COMPLETE ;
353+ VLOG_INFO ("OVS frw cleared, restarting flow-restore-wait sequence "
354+ "(cur_cfg=%" PRIu64 ")" , ofctrl_cur_cfg );
355+ }
356+ break ;
357+ }
358+ }
359+
214360/* Only set monitor conditions on tables that are available in the
215361 * server schema.
216362 */
@@ -3381,6 +3527,7 @@ en_mac_cache_cleanup(void *data)
33813527
33823528struct ed_type_bfd_chassis {
33833529 struct sset bfd_chassis ;
3530+ bool is_ha_gw ;
33843531};
33853532
33863533static void *
@@ -3409,8 +3556,9 @@ en_bfd_chassis_run(struct engine_node *node, void *data OVS_UNUSED)
34093556 = chassis_lookup_by_name (sbrec_chassis_by_name , chassis_id );
34103557
34113558 sset_clear (& bfd_chassis -> bfd_chassis );
3412- bfd_calculate_chassis (chassis , ha_chassis_grp_table ,
3413- & bfd_chassis -> bfd_chassis );
3559+ bfd_chassis -> is_ha_gw = bfd_calculate_chassis (chassis ,
3560+ ha_chassis_grp_table ,
3561+ & bfd_chassis -> bfd_chassis );
34143562 return EN_UPDATED ;
34153563}
34163564
@@ -7117,6 +7265,7 @@ main(int argc, char *argv[])
71177265 struct unixctl_server * unixctl ;
71187266 struct ovn_exit_args exit_args = {0 };
71197267 struct br_int_remote br_int_remote = {0 };
7268+ static uint64_t next_cfg = 0 ;
71207269 int retval ;
71217270
71227271 /* Read from system-id-override file once on startup. */
@@ -7444,6 +7593,7 @@ main(int argc, char *argv[])
74447593
74457594 /* Main loop. */
74467595 int ovnsb_txn_status = 1 ;
7596+ int ovs_txn_status = 1 ;
74477597 bool sb_monitor_all = false;
74487598 struct tracked_acl_ids * tracked_acl_ids = NULL ;
74497599 while (!exit_args .exiting ) {
@@ -7545,6 +7695,11 @@ main(int argc, char *argv[])
75457695 pinctrl_update_swconn (br_int_remote .target ,
75467696 br_int_remote .probe_interval );
75477697
7698+ if (cfg && ovs_idl_txn && ovs_txn_status == -1 ) {
7699+ /* txn was in progress and is now completed */
7700+ next_cfg = cfg -> next_cfg ;
7701+ }
7702+
75487703 /* Enable ACL matching for double tagged traffic. */
75497704 if (ovs_idl_txn && cfg ) {
75507705 int vlan_limit = smap_get_int (
@@ -7894,6 +8049,13 @@ main(int argc, char *argv[])
78948049 stopwatch_start (OFCTRL_SEQNO_RUN_STOPWATCH_NAME ,
78958050 time_msec ());
78968051 ofctrl_seqno_run (ofctrl_get_cur_cfg ());
8052+ if (ovs_idl_txn && bfd_chassis_data ) {
8053+ manage_flow_restore_wait (ovs_idl_txn , cfg ,
8054+ ofctrl_get_cur_cfg (),
8055+ next_cfg , ovs_txn_status ,
8056+ bfd_chassis_data -> is_ha_gw );
8057+ }
8058+
78978059 stopwatch_stop (OFCTRL_SEQNO_RUN_STOPWATCH_NAME ,
78988060 time_msec ());
78998061 stopwatch_start (IF_STATUS_MGR_RUN_STOPWATCH_NAME ,
@@ -7993,7 +8155,7 @@ main(int argc, char *argv[])
79938155 OVS_NOT_REACHED ();
79948156 }
79958157
7996- int ovs_txn_status = ovsdb_idl_loop_commit_and_wait (& ovs_idl_loop );
8158+ ovs_txn_status = ovsdb_idl_loop_commit_and_wait (& ovs_idl_loop );
79978159 if (!ovs_txn_status ) {
79988160 /* The transaction failed. */
79998161 vif_plug_clear_deleted (
@@ -8012,6 +8174,9 @@ main(int argc, char *argv[])
80128174 & vif_plug_deleted_iface_ids );
80138175 vif_plug_finish_changed (
80148176 & vif_plug_changed_iface_ids );
8177+ if (cfg ) {
8178+ next_cfg = cfg -> next_cfg ;
8179+ }
80158180 } else if (ovs_txn_status == -1 ) {
80168181 /* The commit is still in progress */
80178182 } else {
@@ -8085,7 +8250,7 @@ main(int argc, char *argv[])
80858250 }
80868251
80878252 ovsdb_idl_loop_commit_and_wait (& ovnsb_idl_loop );
8088- int ovs_txn_status = ovsdb_idl_loop_commit_and_wait (& ovs_idl_loop );
8253+ ovs_txn_status = ovsdb_idl_loop_commit_and_wait (& ovs_idl_loop );
80898254 if (!ovs_txn_status ) {
80908255 /* The transaction failed. */
80918256 vif_plug_clear_deleted (
0 commit comments