From 110945ba0d2314c18504adbc6ee3896fb67e4f09 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 25 Jan 2024 18:10:08 +0100 Subject: [PATCH] ospfd: fix GR state location This belongs in `/var/lib`, not `/var/run`. Use library facility to load/save, support previous path as fallback, and do proper fsync(). Signed-off-by: David Lamparter --- configure.ac | 1 - ospfd/ospf_gr.c | 42 ++++++------------------------------------ ospfd/ospf_main.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 37 deletions(-) diff --git a/configure.ac b/configure.ac index b6438889adf3..141f0612d70a 100644 --- a/configure.ac +++ b/configure.ac @@ -2741,7 +2741,6 @@ AC_DEFINE_UNQUOTED([FRR_LIBSTATE_PATH], ["$CFG_LIBSTATE"], [/var/lib/frr equival AC_DEFINE_UNQUOTED([YANG_MODELS_PATH], ["$CFG_YANGMODELS"], [path to YANG data models]) AC_DEFINE_UNQUOTED([WATCHFRR_SH_PATH], ["${CFG_SBIN%/}/watchfrr.sh"], [path to watchfrr.sh]) -AC_DEFINE_UNQUOTED([OSPFD_GR_STATE], ["$CFG_STATE%s/ospfd-gr.json"], [ospfd GR state information]) AC_DEFINE_UNQUOTED([OSPF6D_GR_STATE], ["$CFG_STATE/ospf6d-gr.json"], [ospf6d GR state information]) AC_DEFINE_UNQUOTED([OSPF6_AUTH_SEQ_NUM_FILE], ["$CFG_STATE/ospf6d-at-seq-no.dat"], [ospf6d AT Sequence number information]) AC_DEFINE_UNQUOTED([DAEMON_DB_DIR], ["$CFG_STATE"], [daemon database directory]) diff --git a/ospfd/ospf_gr.c b/ospfd/ospf_gr.c index c23c42052fc7..0a4d579fc976 100644 --- a/ospfd/ospf_gr.c +++ b/ospfd/ospf_gr.c @@ -555,21 +555,6 @@ static void ospf_gr_grace_period_expired(struct event *thread) ospf_gr_restart_exit(ospf, "grace period has expired"); } -/* - * Returns the path of the file (non-volatile memory) that contains GR status - * information. - */ -static char *ospf_gr_nvm_filepath(struct ospf *ospf) -{ - static char filepath[MAXPATHLEN]; - char instance[16] = ""; - - if (ospf->instance) - snprintf(instance, sizeof(instance), "-%d", ospf->instance); - snprintf(filepath, sizeof(filepath), OSPFD_GR_STATE, instance); - return filepath; -} - /* Send extra Grace-LSA out the interface (unplanned outages only). */ void ospf_gr_iface_send_grace_lsa(struct event *thread) { @@ -591,18 +576,14 @@ void ospf_gr_iface_send_grace_lsa(struct event *thread) */ static void ospf_gr_nvm_update(struct ospf *ospf, bool prepare) { - char *filepath; const char *inst_name; json_object *json; json_object *json_instances; json_object *json_instance; - filepath = ospf_gr_nvm_filepath(ospf); inst_name = ospf_get_name(ospf); - json = json_object_from_file(filepath); - if (json == NULL) - json = json_object_new_object(); + json = frr_daemon_state_load(); json_object_object_get_ex(json, "instances", &json_instances); if (!json_instances) { @@ -630,8 +611,7 @@ static void ospf_gr_nvm_update(struct ospf *ospf, bool prepare) json_object_int_add(json_instance, "timestamp", time(NULL) + ospf->gr_info.grace_period); - json_object_to_file_ext(filepath, json, JSON_C_TO_STRING_PRETTY); - json_object_free(json); + frr_daemon_state_save(&json); } /* @@ -640,17 +620,13 @@ static void ospf_gr_nvm_update(struct ospf *ospf, bool prepare) */ void ospf_gr_nvm_delete(struct ospf *ospf) { - char *filepath; const char *inst_name; json_object *json; json_object *json_instances; - filepath = ospf_gr_nvm_filepath(ospf); inst_name = ospf_get_name(ospf); - json = json_object_from_file(filepath); - if (json == NULL) - json = json_object_new_object(); + json = frr_daemon_state_load(); json_object_object_get_ex(json, "instances", &json_instances); if (!json_instances) { @@ -660,8 +636,7 @@ void ospf_gr_nvm_delete(struct ospf *ospf) json_object_object_del(json_instances, inst_name); - json_object_to_file_ext(filepath, json, JSON_C_TO_STRING_PRETTY); - json_object_free(json); + frr_daemon_state_save(&json); } /* @@ -670,7 +645,6 @@ void ospf_gr_nvm_delete(struct ospf *ospf) */ void ospf_gr_nvm_read(struct ospf *ospf) { - char *filepath; const char *inst_name; json_object *json; json_object *json_instances; @@ -679,12 +653,9 @@ void ospf_gr_nvm_read(struct ospf *ospf) json_object *json_grace_period; time_t timestamp = 0; - filepath = ospf_gr_nvm_filepath(ospf); inst_name = ospf_get_name(ospf); - json = json_object_from_file(filepath); - if (json == NULL) - json = json_object_new_object(); + json = frr_daemon_state_load(); json_object_object_get_ex(json, "instances", &json_instances); if (!json_instances) { @@ -730,8 +701,7 @@ void ospf_gr_nvm_read(struct ospf *ospf) json_object_object_del(json_instances, inst_name); - json_object_to_file_ext(filepath, json, JSON_C_TO_STRING_PRETTY); - json_object_free(json); + frr_daemon_state_save(&json); } void ospf_gr_unplanned_start_interface(struct ospf_interface *oi) diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 168cdbe482c3..6a4a9a148177 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -45,6 +45,16 @@ #include "ospfd/ospf_ldp_sync.h" #include "ospfd/ospf_routemap_nb.h" +#define OSPFD_STATE_NAME "%s/ospfd.json", frr_libstatedir +#define OSPFD_INST_STATE_NAME(i) "%s/ospfd-%d.json", frr_runstatedir, i + +/* this one includes the path... because the instance number was in the path + * before :( ... which totally didn't have a mkdir anywhere. + */ +#define OSPFD_COMPAT_STATE_NAME "%s/ospfd-gr.json", frr_libstatedir +#define OSPFD_COMPAT_INST_STATE_NAME(i) \ + "%s-%d/ospfd-gr.json", frr_runstatedir, i + /* ospfd privileges */ zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN}; @@ -126,6 +136,15 @@ static const struct frr_yang_module_info *const ospfd_yang_modules[] = { &frr_ospf_route_map_info, }; +/* actual paths filled in main() */ +static char state_path[512]; +static char state_compat_path[512]; +static char *state_paths[] = { + state_path, + state_compat_path, + NULL, +}; + /* clang-format off */ FRR_DAEMON_INFO(ospfd, OSPF, .vty_port = OSPF_VTY_PORT, @@ -138,6 +157,8 @@ FRR_DAEMON_INFO(ospfd, OSPF, .yang_modules = ospfd_yang_modules, .n_yang_modules = array_size(ospfd_yang_modules), + + .state_paths = state_paths, ); /* clang-format on */ @@ -213,6 +234,17 @@ int main(int argc, char **argv) exit(1); } + if (ospf_instance) { + snprintf(state_path, sizeof(state_path), + OSPFD_INST_STATE_NAME(ospf_instance)); + snprintf(state_compat_path, sizeof(state_compat_path), + OSPFD_COMPAT_INST_STATE_NAME(ospf_instance)); + } else { + snprintf(state_path, sizeof(state_path), OSPFD_STATE_NAME); + snprintf(state_compat_path, sizeof(state_compat_path), + OSPFD_COMPAT_STATE_NAME); + } + /* OSPF master init. */ ospf_master_init(frr_init());