diff --git a/TODO.rst b/TODO.rst index d548170111..12738280ba 100644 --- a/TODO.rst +++ b/TODO.rst @@ -172,3 +172,10 @@ OVN To-do List * Multi-threaded logical flow computation was optimized for the case when datapath groups are disabled. Datpath groups are always enabled now so northd parallel processing should be revisited. + +* ovn-controller daemon module + + * Dumitru Ceara: Add a new module e.g. ovn/lib/daemon-ovn.c that wraps + OVS' daemonize_start() call and initializes the additional things, like + the unixctl commands. Or, we should move the APIs such as + daemon_started_recently() to OVS's lib/daemon. diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index c97744d570..51e2b3c40a 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -94,6 +94,7 @@ static unixctl_cb_func debug_dump_lflow_conj_ids; static unixctl_cb_func lflow_cache_flush_cmd; static unixctl_cb_func lflow_cache_show_stats_cmd; static unixctl_cb_func debug_delay_nb_cfg_report; +static unixctl_cb_func debug_ignore_startup_delay; #define DEFAULT_BRIDGE_NAME "br-int" #define DEFAULT_DATAPATH "system" @@ -866,11 +867,12 @@ static void store_nb_cfg(struct ovsdb_idl_txn *sb_txn, struct ovsdb_idl_txn *ovs_txn, const struct sbrec_chassis_private *chassis, const struct ovsrec_bridge *br_int, - unsigned int delay_nb_cfg_report, int64_t startup_ts) + unsigned int delay_nb_cfg_report) { struct ofctrl_acked_seqnos *acked_nb_cfg_seqnos = ofctrl_acked_seqnos_get(ofctrl_seq_type_nb_cfg); uint64_t cur_cfg = acked_nb_cfg_seqnos->last_acked; + int64_t startup_ts = daemon_startup_ts(); if (ovs_txn && br_int && startup_ts != smap_get_ullong(&br_int->external_ids, @@ -3858,6 +3860,9 @@ main(int argc, char *argv[]) debug_dump_lflow_conj_ids, &lflow_output_data->conj_ids); + unixctl_command_register("debug/ignore-startup-delay", "", 0, 0, + debug_ignore_startup_delay, NULL); + unsigned int ovs_cond_seqno = UINT_MAX; unsigned int ovnsb_cond_seqno = UINT_MAX; unsigned int ovnsb_expected_cond_seqno = UINT_MAX; @@ -3879,7 +3884,6 @@ main(int argc, char *argv[]) /* Main loop. */ exiting = false; restart = false; - int64_t startup_ts = time_wall_msec(); bool sb_monitor_all = false; while (!exiting) { memory_run(); @@ -4059,6 +4063,10 @@ main(int argc, char *argv[]) } stopwatch_stop(CONTROLLER_LOOP_STOPWATCH_NAME, time_msec()); + if (engine_has_updated()) { + daemon_started_recently_countdown(); + } + ct_zones_data = engine_get_data(&en_ct_zones); if (ovs_idl_txn) { if (ct_zones_data) { @@ -4221,7 +4229,7 @@ main(int argc, char *argv[]) } store_nb_cfg(ovnsb_idl_txn, ovs_idl_txn, chassis_private, - br_int, delay_nb_cfg_report, startup_ts); + br_int, delay_nb_cfg_report); if (pending_pkt.conn) { struct ed_type_addr_sets *as_data = @@ -4698,3 +4706,11 @@ debug_dump_lflow_conj_ids(struct unixctl_conn *conn, int argc OVS_UNUSED, unixctl_command_reply(conn, ds_cstr(&conj_ids_dump)); ds_destroy(&conj_ids_dump); } + +static void +debug_ignore_startup_delay(struct unixctl_conn *conn, int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, void *arg OVS_UNUSED) +{ + daemon_started_recently_ignore(); + unixctl_command_reply(conn, NULL); +} diff --git a/lib/inc-proc-eng.c b/lib/inc-proc-eng.c index 575b774ae6..2e2b310332 100644 --- a/lib/inc-proc-eng.c +++ b/lib/inc-proc-eng.c @@ -312,6 +312,17 @@ engine_has_run(void) return false; } +bool +engine_has_updated(void) +{ + for (size_t i = 0; i < engine_n_nodes; i++) { + if (engine_nodes[i]->state == EN_UPDATED) { + return true; + } + } + return false; +} + bool engine_aborted(void) { diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h index 9bfab1f7cd..dc365dc184 100644 --- a/lib/inc-proc-eng.h +++ b/lib/inc-proc-eng.h @@ -238,6 +238,10 @@ bool engine_node_changed(struct engine_node *node); /* Return true if the engine has run in the last iteration. */ bool engine_has_run(void); +/* Return true if the engine has any update in any node, i.e. any input + * has changed; false if nothing has changed. */ +bool engine_has_updated(void); + /* Returns true if during the last engine run we had to abort processing. */ bool engine_aborted(void); diff --git a/lib/ovn-util.c b/lib/ovn-util.c index 616999eabd..d80db179a7 100644 --- a/lib/ovn-util.c +++ b/lib/ovn-util.c @@ -883,3 +883,55 @@ get_bridge(const struct ovsrec_bridge_table *bridge_table, const char *br_name) } return NULL; } + +#define DAEMON_STARTUP_DELAY_SEED 20 +#define DAEMON_STARTUP_DELAY_MS 10000 + +static int64_t startup_ts; +static int startup_delay = DAEMON_STARTUP_DELAY_SEED; + +/* Used by debug command only, for tests. */ +static bool ignore_startup_delay = false; + +OVS_CONSTRUCTOR(startup_ts_initializer) { + startup_ts = time_wall_msec(); +} + +int64_t +daemon_startup_ts(void) +{ + return startup_ts; +} + +void +daemon_started_recently_countdown(void) +{ + if (startup_delay > 0) { + startup_delay--; + } +} + +void +daemon_started_recently_ignore(void) +{ + ignore_startup_delay = true; +} + +bool +daemon_started_recently(void) +{ + if (ignore_startup_delay) { + return false; + } + + VLOG_DBG("startup_delay: %d, startup_ts: %"PRId64, startup_delay, + startup_ts); + + /* Ensure that at least an amount of updates has been handled. */ + if (startup_delay) { + return true; + } + + /* Ensure that at least an amount of time has passed. */ + return time_wall_msec() - startup_ts <= DAEMON_STARTUP_DELAY_MS; +} diff --git a/lib/ovn-util.h b/lib/ovn-util.h index b3905ef7bf..145f974eda 100644 --- a/lib/ovn-util.h +++ b/lib/ovn-util.h @@ -309,5 +309,9 @@ struct ovsrec_bridge_table; const struct ovsrec_bridge *get_bridge(const struct ovsrec_bridge_table *, const char *br_name); +void daemon_started_recently_countdown(void); +void daemon_started_recently_ignore(void); +bool daemon_started_recently(void); +int64_t daemon_startup_ts(void); #endif /* OVN_UTIL_H */