static void bs_neighbour_admin_down_handler(struct bfd_session *bfd,
uint8_t diag);
+/**
+ * Remove BFD profile from all BFD sessions so we don't leave dangling
+ * pointers.
+ */
+static void bfd_profile_detach(struct bfd_profile *bp);
+
/* Zeroed array with the size of an IPv6 address. */
struct in6_addr zero_addr;
void bfd_profile_free(struct bfd_profile *bp)
{
+ /* Detach from any session. */
+ bfd_profile_detach(bp);
+
+ /* Remove from global list. */
TAILQ_REMOVE(&bplist, bp, entry);
free(bp);
}
void bfd_shutdown(void)
{
+ struct bfd_profile *bp;
+
/*
* Close and free all BFD sessions.
*
/* Now free the hashes themselves. */
hash_free(bfd_id_hash);
hash_free(bfd_key_hash);
+
+ /* Free all profile allocations. */
+ while ((bp = TAILQ_FIRST(&bplist)) != NULL)
+ bfd_profile_free(bp);
}
struct bfd_session_iterator {
hash_iterate(bfd_key_hash, _bfd_profile_update, bp);
}
+static void _bfd_profile_detach(struct hash_bucket *hb, void *arg)
+{
+ struct bfd_profile *bp = arg;
+ struct bfd_session *bs = hb->data;
+
+ /* This session is not using the profile. */
+ if (bs->profile_name == NULL || strcmp(bs->profile_name, bp->name) != 0)
+ return;
+
+ bfd_profile_remove(bs);
+}
+
+static void bfd_profile_detach(struct bfd_profile *bp)
+{
+ hash_iterate(bfd_key_hash, _bfd_profile_detach, bp);
+}
+
/*
* VRF related functions.
*/