]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ospf6d: fix GR & auth seqno state location
authorDavid Lamparter <equinox@opensourcerouting.org>
Thu, 25 Jan 2024 18:37:26 +0000 (19:37 +0100)
committerDavid Lamparter <equinox@opensourcerouting.org>
Sat, 27 Jan 2024 18:02:52 +0000 (19:02 +0100)
Unfortunately, `ospf6d` is much worse than `ospfd` and `isisd` regarding
its state saving, due to the existence of the auth trailer code.

Again, this belongs in `/var/lib`, not `/var/run`.

Merge both state files into one, and add reconciliation code for the
auth seqno.

I'm gonna save my comment on the fact that `ospf6_auth_seqno_nvm_delete`
is not in fact used anywhere.  Which is now a warning because it's
`static`.  Well.  It probably should be used somewhere, so leave it in.

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
configure.ac
ospf6d/ospf6_auth_trailer.c
ospf6d/ospf6_auth_trailer.h
ospf6d/ospf6_gr.c
ospf6d/ospf6_main.c
ospf6d/ospf6_top.c

index 141f0612d70a70597e6c2e8a7de4917531f63d4a..38f6624c7f0e13c359973a457a0048ad2ec7400d 100644 (file)
@@ -2741,8 +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([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])
 
 dnl various features
index 54b951654aa31dcbf1ec9d597358bbd5a0aa3b45..8d9eff409e63c055c9d723637b9cca550c715f3a 100644 (file)
 #include "ospf6_zebra.h"
 #include "lib/keychain.h"
 
+#define OSPF6D_COMPAT_AUTHSEQ_NAME "%s/ospf6d-at-seq-no.dat", frr_runstatedir
+
 unsigned char conf_debug_ospf6_auth[2];
 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_HASH_XOR, "OSPF6 auth hash xor");
 
+static void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6);
+
 /*Apad is the hexadecimal value 0x878FE1F3. */
 const uint8_t ospf6_hash_apad_max[KEYCHAIN_MAX_HASH_SIZE] = {
        0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1,
@@ -862,23 +866,11 @@ void install_element_ospf6_clear_intf_auth(void)
        install_element(ENABLE_NODE, &clear_ipv6_ospf6_intf_auth_cmd);
 }
 
-enum ospf6_auth_err ospf6_auth_nvm_file_exist(void)
-{
-       struct stat buffer;
-       int exist;
-
-       exist = stat(OSPF6_AUTH_SEQ_NUM_FILE, &buffer);
-       if (exist == 0)
-               return OSPF6_AUTH_FILE_EXIST;
-       else
-               return OSPF6_AUTH_FILE_DO_NOT_EXIST;
-}
-
 /*
  * Record in non-volatile memory the given ospf6 process,
  * authentication trailer higher order sequence number.
  */
-void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6)
+static void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6)
 {
        const char *inst_name;
        json_object *json;
@@ -890,9 +882,7 @@ void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6)
 
        inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
 
-       json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE);
-       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) {
@@ -912,49 +902,82 @@ void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6)
         */
        json_object_int_add(json_instance, "sequence_number", ospf6->seqnum_h);
 
-       json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json,
-                               JSON_C_TO_STRING_PRETTY);
-       json_object_free(json);
+       frr_daemon_state_save(&json);
 }
 
 /*
  * Delete authentication sequence number for a given OSPF6 process
  * from non-volatile memory.
  */
-void ospf6_auth_seqno_nvm_delete(struct ospf6 *ospf6)
+__attribute__((unused)) static void
+ospf6_auth_seqno_nvm_delete(struct ospf6 *ospf6)
 {
        const char *inst_name;
        json_object *json;
        json_object *json_instances;
+       json_object *json_instance;
 
        zlog_err("Higher order sequence number delete for %s process",
                 ospf6->name);
 
        inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
 
-       json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE);
-       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) {
-               json_instances = json_object_new_object();
-               json_object_object_add(json, "instances", json_instances);
+               json_object_put(json);
+               return;
+       }
+
+       json_object_object_get_ex(json_instances, inst_name, &json_instance);
+       if (json_instance) {
+               json_object_put(json);
+               return;
        }
 
-       json_object_object_del(json_instances, inst_name);
+       json_object_object_del(json_instance, "sequence_number");
 
-       json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json,
-                               JSON_C_TO_STRING_PRETTY);
-       json_object_free(json);
+       frr_daemon_state_save(&json);
 }
 
 
+static struct json_object *ospf6_auth_seqno_compat_read(const char *inst_name)
+{
+       /* try legacy location */
+       char compat_path[512];
+       json_object *json;
+       json_object *json_instances = NULL;
+       json_object *json_instance = NULL;
+       json_object *json_seqnum = NULL;
+
+       snprintf(compat_path, sizeof(compat_path), OSPF6D_COMPAT_AUTHSEQ_NAME);
+       json = json_object_from_file(compat_path);
+
+       if (json)
+               json_object_object_get_ex(json, "instances", &json_instances);
+       if (json_instances)
+               json_object_object_get_ex(json_instances, inst_name,
+                                         &json_instance);
+       if (json_instance)
+               json_object_object_get_ex(json_instance, "sequence_number",
+                                         &json_seqnum);
+       if (json_seqnum)
+               /* => free the file-level object and still return this */
+               json_seqnum = json_object_get(json_seqnum);
+
+       if (json) {
+               json_object_free(json);
+               unlink(compat_path);
+       }
+       return json_seqnum;
+}
+
 /*
  * Fetch from non-volatile memory the stored ospf6 process
  * authentication sequence number.
  */
-void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6)
+static void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6)
 {
        const char *inst_name;
        json_object *json;
@@ -964,9 +987,7 @@ void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6)
 
        inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
 
-       json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE);
-       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) {
@@ -983,13 +1004,34 @@ void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6)
 
        json_object_object_get_ex(json_instance, "sequence_number",
                                  &json_seqnum);
-       ospf6->seqnum_h = json_object_get_int(json_seqnum);
+
+       if (json_seqnum)
+               /* cf. reference taken in compat_read above */
+               json_seqnum = json_object_get(json_seqnum);
+       else
+               json_seqnum = ospf6_auth_seqno_compat_read(inst_name);
+
+       ospf6->seqnum_l = 0;
+       if (json_seqnum) {
+               ospf6->seqnum_h = json_object_get_int(json_seqnum);
+               ospf6->seqnum_h += 1;
+       } else {
+               ospf6->seqnum_h = 0;
+       }
+
+       if (json_seqnum)
+               json_object_put(json_seqnum);
 
        zlog_err("Higher order sequence number %d read for %s process %s",
                 ospf6->seqnum_h, ospf6->name, strerror(errno));
 
-       json_object_object_del(json_instances, inst_name);
-       json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json,
-                               JSON_C_TO_STRING_PRETTY);
-       json_object_free(json);
+       json_object_object_del(json_instance, "sequence_number");
+
+       frr_daemon_state_save(&json);
+}
+
+void ospf6_auth_init(struct ospf6 *o)
+{
+       ospf6_auth_seqno_nvm_read(o);
+       ospf6_auth_seqno_nvm_update(o);
 }
index 3f82a7b19774e08b795ba011d4c913b4cf68302a..9073ae47dd68a7ec5e921922502cb65b9903511b 100644 (file)
@@ -48,10 +48,10 @@ enum ospf6_auth_err {
        OSPF6_AUTH_VALIDATE_SUCCESS = 0,
        OSPF6_AUTH_VALIDATE_FAILURE,
        OSPF6_AUTH_PROCESS_NORMAL,
-       OSPF6_AUTH_FILE_EXIST,
-       OSPF6_AUTH_FILE_DO_NOT_EXIST
 };
 
+void ospf6_auth_init(struct ospf6 *o);
+
 void ospf6_auth_hdr_dump_send(struct ospf6_header *ospfh, uint16_t length);
 void ospf6_auth_hdr_dump_recv(struct ospf6_header *ospfh, uint16_t length,
                              unsigned int lls_len);
@@ -73,8 +73,5 @@ void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi,
 void install_element_ospf6_debug_auth(void);
 int config_write_ospf6_debug_auth(struct vty *vty);
 void install_element_ospf6_clear_intf_auth(void);
-enum ospf6_auth_err ospf6_auth_nvm_file_exist(void);
-void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6);
-void ospf6_auth_seqno_nvm_delete(struct ospf6 *ospf6);
-void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6);
+
 #endif /* __OSPF6_AUTH_TRAILER_H__ */
index 69230e572b06628f5c4e5c779af59c96700ac116..34cb9706bd387771612b7e449e1aa33a856bb10b 100644 (file)
@@ -561,9 +561,7 @@ static void ospf6_gr_nvm_update(struct ospf6 *ospf6, bool prepare)
 
        inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
 
-       json = json_object_from_file((char *)OSPF6D_GR_STATE);
-       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) {
@@ -591,9 +589,7 @@ static void ospf6_gr_nvm_update(struct ospf6 *ospf6, bool prepare)
                json_object_int_add(json_instance, "timestamp",
                                    time(NULL) + ospf6->gr_info.grace_period);
 
-       json_object_to_file_ext((char *)OSPF6D_GR_STATE, json,
-                               JSON_C_TO_STRING_PRETTY);
-       json_object_free(json);
+       frr_daemon_state_save(&json);
 }
 
 /*
@@ -608,9 +604,7 @@ void ospf6_gr_nvm_delete(struct ospf6 *ospf6)
 
        inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
 
-       json = json_object_from_file((char *)OSPF6D_GR_STATE);
-       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) {
@@ -620,9 +614,7 @@ void ospf6_gr_nvm_delete(struct ospf6 *ospf6)
 
        json_object_object_del(json_instances, inst_name);
 
-       json_object_to_file_ext((char *)OSPF6D_GR_STATE, json,
-                               JSON_C_TO_STRING_PRETTY);
-       json_object_free(json);
+       frr_daemon_state_save(&json);
 }
 
 /*
@@ -641,9 +633,7 @@ void ospf6_gr_nvm_read(struct ospf6 *ospf6)
 
        inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
 
-       json = json_object_from_file((char *)OSPF6D_GR_STATE);
-       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) {
@@ -687,11 +677,10 @@ void ospf6_gr_nvm_read(struct ospf6 *ospf6)
                                               ospf6->gr_info.grace_period);
        }
 
-       json_object_object_del(json_instances, inst_name);
+       json_object_object_del(json_instance, "gracePeriod");
+       json_object_object_del(json_instance, "timestamp");
 
-       json_object_to_file_ext((char *)OSPF6D_GR_STATE, json,
-                               JSON_C_TO_STRING_PRETTY);
-       json_object_free(json);
+       frr_daemon_state_save(&json);
 }
 
 void ospf6_gr_unplanned_start_interface(struct ospf6_interface *oi)
index 9d802531ba53191de86f6fc2a95753f388520b97..6449d6845326961b3a724733db41fb0ad8ff76c4 100644 (file)
 /* Default configuration file name for ospf6d. */
 #define OSPF6_DEFAULT_CONFIG       "ospf6d.conf"
 
+/* GR and auth trailer persistent state */
+#define OSPF6D_STATE_NAME       "%s/ospf6d.json", frr_libstatedir
+#define OSPF6D_COMPAT_STATE_NAME "%s/ospf6d-gr.json", frr_runstatedir
+/* for extra confusion, "ospf6d-at-seq-no.dat" is handled directly in
+ * ospf6_auth_trailer.c;  the alternative would be somehow merging JSON which
+ * is excessive for just supporting a legacy compatibility file location
+ */
+
 /* Default port values. */
 #define OSPF6_VTY_PORT             2606
 
@@ -166,6 +174,15 @@ static const struct frr_yang_module_info *const ospf6d_yang_modules[] = {
        &frr_ospf6_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(ospf6d, OSPF6,
        .vty_port = OSPF6_VTY_PORT,
@@ -178,6 +195,8 @@ FRR_DAEMON_INFO(ospf6d, OSPF6,
 
        .yang_modules = ospf6d_yang_modules,
        .n_yang_modules = array_size(ospf6d_yang_modules),
+
+       .state_paths = state_paths,
 );
 /* clang-format on */
 
@@ -237,6 +256,10 @@ int main(int argc, char *argv[], char *envp[])
                exit(1);
        }
 
+       snprintf(state_path, sizeof(state_path), OSPF6D_STATE_NAME);
+       snprintf(state_compat_path, sizeof(state_compat_path),
+                OSPF6D_COMPAT_STATE_NAME);
+
        /* OSPF6 master init. */
        ospf6_master_init(frr_init());
 
index 63672a96e7a20e69ad704486665112f2db102969..a3fb2053749ee17ba4fba20e3ffea35f5b36f4c2 100644 (file)
@@ -430,17 +430,7 @@ static struct ospf6 *ospf6_create(const char *name)
        /* Make ospf protocol socket. */
        ospf6_serv_sock(o);
 
-       /* If sequence number is stored in persistent storage, read it.
-        */
-       if (ospf6_auth_nvm_file_exist() == OSPF6_AUTH_FILE_EXIST) {
-               ospf6_auth_seqno_nvm_read(o);
-               o->seqnum_h = o->seqnum_h + 1;
-               ospf6_auth_seqno_nvm_update(o);
-       } else {
-               o->seqnum_l = o->seqnum_h = 0;
-               ospf6_auth_seqno_nvm_update(o);
-       }
-
+       ospf6_auth_init(o);
        return o;
 }