diff options
Diffstat (limited to 'watchfrr')
-rw-r--r-- | watchfrr/watchfrr.c | 49 |
1 files changed, 42 insertions, 7 deletions
diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c index 3a5919ede..e5afa6898 100644 --- a/watchfrr/watchfrr.c +++ b/watchfrr/watchfrr.c @@ -54,6 +54,7 @@ #define DEFAULT_LOGLEVEL LOG_INFO #define DEFAULT_MIN_RESTART 60 #define DEFAULT_MAX_RESTART 600 +#define DEFAULT_OPERATIONAL_TIMEOUT 60 #define DEFAULT_RESTART_CMD WATCHFRR_SH_PATH " restart %s" #define DEFAULT_START_CMD WATCHFRR_SH_PATH " start %s" @@ -106,12 +107,14 @@ static struct global_state { enum restart_phase phase; struct thread *t_phase_hanging; struct thread *t_startup_timeout; + struct thread *t_operational; const char *vtydir; long period; long timeout; long restart_timeout; long min_restart_interval; long max_restart_interval; + long operational_timeout; struct daemon *daemons; const char *restart_command; const char *start_command; @@ -131,6 +134,7 @@ static struct global_state { .loglevel = DEFAULT_LOGLEVEL, .min_restart_interval = DEFAULT_MIN_RESTART, .max_restart_interval = DEFAULT_MAX_RESTART, + .operational_timeout = DEFAULT_OPERATIONAL_TIMEOUT, .restart_command = DEFAULT_RESTART_CMD, .start_command = DEFAULT_START_CMD, .stop_command = DEFAULT_STOP_CMD, @@ -177,6 +181,7 @@ struct daemon { #define OPTION_MAXRESTART 2001 #define OPTION_DRY 2002 #define OPTION_NETNS 2003 +#define OPTION_MAXOPERATIONAL 2004 static const struct option longopts[] = { {"daemon", no_argument, NULL, 'd'}, @@ -191,6 +196,7 @@ static const struct option longopts[] = { {"dry", no_argument, NULL, OPTION_DRY}, {"min-restart-interval", required_argument, NULL, OPTION_MINRESTART}, {"max-restart-interval", required_argument, NULL, OPTION_MAXRESTART}, + {"operational-timeout", required_argument, NULL, OPTION_MAXOPERATIONAL}, {"pid-file", required_argument, NULL, 'p'}, {"blank-string", required_argument, NULL, 'b'}, #ifdef GNU_LINUX @@ -265,6 +271,9 @@ Otherwise, the interval is doubled (but capped at the -M value).\n\n", --max-restart-interval\n\ Set the maximum seconds to wait between invocations of daemon\n\ restart commands (default is %d).\n\ + --operational-timeout\n\ + Set the time before systemd is notified that we are considered\n\ + operational again after a daemon restart (default is %d).\n\ -i, --interval Set the status polling interval in seconds (default is %d)\n\ -t, --timeout Set the unresponsiveness timeout in seconds (default is %d)\n\ -T, --restart-timeout\n\ @@ -296,10 +305,10 @@ Otherwise, the interval is doubled (but capped at the -M value).\n\n", -v, --version Print program version\n\ -h, --help Display this help and exit\n", frr_vtydir, DEFAULT_LOGLEVEL, LOG_EMERG, LOG_DEBUG, LOG_DEBUG, - DEFAULT_MIN_RESTART, DEFAULT_MAX_RESTART, DEFAULT_PERIOD, - DEFAULT_TIMEOUT, DEFAULT_RESTART_TIMEOUT, - DEFAULT_RESTART_CMD, DEFAULT_START_CMD, DEFAULT_STOP_CMD, - frr_vtydir); + DEFAULT_MIN_RESTART, DEFAULT_MAX_RESTART, + DEFAULT_OPERATIONAL_TIMEOUT, DEFAULT_PERIOD, DEFAULT_TIMEOUT, + DEFAULT_RESTART_TIMEOUT, DEFAULT_RESTART_CMD, DEFAULT_START_CMD, + DEFAULT_STOP_CMD, frr_vtydir); } static pid_t run_background(char *shell_cmd) @@ -502,8 +511,6 @@ static int run_job(struct restart_info *restart, const char *cmdtype, restart->pid = 0; } - systemd_send_status("FRR Operational"); - /* Calculate the new restart interval. */ if (update_interval) { if (delay.tv_sec > 2 * gs.max_restart_interval) @@ -584,6 +591,11 @@ static void restart_done(struct daemon *dmn) SET_WAKEUP_DOWN(dmn); } +static void daemon_restarting_operational(struct thread *thread) +{ + systemd_send_status("FRR Operational"); +} + static void daemon_down(struct daemon *dmn, const char *why) { if (IS_UP(dmn) || (dmn->state == DAEMON_INIT)) @@ -603,6 +615,8 @@ static void daemon_down(struct daemon *dmn, const char *why) THREAD_OFF(dmn->t_wakeup); if (try_connect(dmn) < 0) SET_WAKEUP_DOWN(dmn); + + systemd_send_status("FRR partially operational"); phase_check(); } @@ -721,8 +735,15 @@ static void daemon_up(struct daemon *dmn, const char *why) gs.numdown--; dmn->connect_tries = 0; zlog_notice("%s state -> up : %s", dmn->name, why); - if (gs.numdown == 0) + if (gs.numdown == 0) { daemon_send_ready(0); + + THREAD_OFF(gs.t_operational); + + thread_add_timer(master, daemon_restarting_operational, NULL, + gs.operational_timeout, &gs.t_operational); + } + SET_WAKEUP_ECHO(dmn); phase_check(); } @@ -889,6 +910,7 @@ static void phase_check(void) case PHASE_WAITING_DOWN: if (gs.numdown + IS_UP(gs.special) < gs.numdaemons) break; + systemd_send_status("Phased Restart"); zlog_info("Phased restart: all routing daemons now down."); run_job(&gs.special->restart, "restart", gs.restart_command, 1, 1); @@ -898,6 +920,7 @@ static void phase_check(void) case PHASE_ZEBRA_RESTART_PENDING: if (gs.special->restart.pid) break; + systemd_send_status("Zebra Restarting"); zlog_info("Phased restart: %s restart job completed.", gs.special->name); set_phase(PHASE_WAITING_ZEBRA_UP); @@ -1395,6 +1418,18 @@ int main(int argc, char **argv) frr_help_exit(1); } } break; + case OPTION_MAXOPERATIONAL: { + char garbage[3]; + + if ((sscanf(optarg, "%ld%1s", &gs.operational_timeout, + garbage) != 1) || + (gs.max_restart_interval < 0)) { + fprintf(stderr, + "Invalid Operational_timeout argument: %s\n", + optarg); + frr_help_exit(1); + } + } break; case OPTION_NETNS: netns_en = true; if (optarg && strchr(optarg, '/')) { |