conntrack_destroy(struct conntrack *ct)
{
    struct conn *conn;
    latch_set(&ct->clean_thread_exit);
    pthread_join(ct->clean_thread, NULL);
    latch_destroy(&ct->clean_thread_exit);

    ovs_mutex_lock(&ct->ct_lock);
    CMAP_FOR_EACH (conn, cm_node, &ct->conns) {
        conn_clean_one(ct, conn);
    }
    cmap_destroy(&ct->conns);

    struct zone_limit *zl;
    HMAP_FOR_EACH_POP (zl, node, &ct->zone_limits) {
        free(zl);
    }
    hmap_destroy(&ct->zone_limits);

    ovs_mutex_unlock(&ct->ct_lock);
    ovs_mutex_destroy(&ct->ct_lock);

    ovs_rwlock_wrlock(&ct->resources_lock);
    struct alg_exp_node *alg_exp_node;
    HMAP_FOR_EACH_POP (alg_exp_node, node, &ct->alg_expectations) {
        free(alg_exp_node);
    }
    hmap_destroy(&ct->alg_expectations);
    hindex_destroy(&ct->alg_expectation_refs);
    ovs_rwlock_unlock(&ct->resources_lock);
    ovs_rwlock_destroy(&ct->resources_lock);

    ipf_destroy(ct->ipf);
    free(ct);
}
conntrack_destroy(struct conntrack *ct)
{
    struct conn *conn;
    latch_set(&ct->clean_thread_exit);
    pthread_join(ct->clean_thread, NULL);
    latch_destroy(&ct->clean_thread_exit);

    ovs_mutex_lock(&ct->ct_lock);
    CMAP_FOR_EACH (conn, cm_node, &ct->conns) {
        conn_clean_one(ct, conn);
    }
    cmap_destroy(&ct->conns);

    struct zone_limit *zl;
    HMAP_FOR_EACH_POP (zl, node, &ct->zone_limits) {
        free(zl);
    }
    hmap_destroy(&ct->zone_limits);

    ovs_mutex_unlock(&ct->ct_lock);
    ovs_mutex_destroy(&ct->ct_lock);

    ovs_rwlock_wrlock(&ct->resources_lock);
    struct alg_exp_node *alg_exp_node;
    HMAP_FOR_EACH_POP (alg_exp_node, node, &ct->alg_expectations) {
        free(alg_exp_node);
    }
    hmap_destroy(&ct->alg_expectations);
    hindex_destroy(&ct->alg_expectation_refs);
    ovs_rwlock_unlock(&ct->resources_lock);
    ovs_rwlock_destroy(&ct->resources_lock);

    ipf_destroy(ct->ipf);
    free(ct);
}