aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-light/src/hicn/core/packet_cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light/src/hicn/core/packet_cache.c')
-rw-r--r--hicn-light/src/hicn/core/packet_cache.c547
1 files changed, 547 insertions, 0 deletions
diff --git a/hicn-light/src/hicn/core/packet_cache.c b/hicn-light/src/hicn/core/packet_cache.c
new file mode 100644
index 000000000..203ad4a63
--- /dev/null
+++ b/hicn-light/src/hicn/core/packet_cache.c
@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file packet_cache.c
+ * \brief Implementation of hICN packet cache
+ */
+
+#include "packet_cache.h"
+
+pkt_cache_t *pkt_cache_create(size_t cs_size) {
+ pkt_cache_t *pkt_cache = (pkt_cache_t *)malloc(sizeof(pkt_cache_t));
+
+ pkt_cache->pit = pit_create();
+ if (!pkt_cache->pit) return NULL;
+ pkt_cache->cs = cs_create(cs_size);
+ if (!pkt_cache->cs) return NULL;
+
+ pkt_cache->index_by_name = kh_init(pkt_cache_name);
+ pool_init(pkt_cache->entries, DEFAULT_PKT_CACHE_SIZE, 0);
+
+ return pkt_cache;
+}
+
+void pkt_cache_free(pkt_cache_t *pkt_cache) {
+ assert(pkt_cache);
+
+ // Free hashmap
+ const Name *k_name;
+ unsigned v;
+ (void)v;
+ kh_foreach(pkt_cache->index_by_name, k_name, v, { free((Name *)k_name); });
+ kh_destroy(pkt_cache_name, pkt_cache->index_by_name);
+
+ // Free pool
+ pool_free(pkt_cache->entries);
+
+ // Free PIT and CS
+ pit_free(pkt_cache->pit);
+ cs_free(pkt_cache->cs);
+
+ free(pkt_cache);
+}
+
+pit_t *pkt_cache_get_pit(pkt_cache_t *pkt_cache) { return pkt_cache->pit; }
+
+cs_t *pkt_cache_get_cs(pkt_cache_t *pkt_cache) { return pkt_cache->cs; }
+
+pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, const Name *name,
+ msgbuf_pool_t *msgbuf_pool,
+ pkt_cache_lookup_t *lookup_result,
+ off_t *entry_id,
+ bool is_serve_from_cs_enabled) {
+ Name name_key = name_key_factory(name);
+ khiter_t k = kh_get_pkt_cache_name(pkt_cache->index_by_name, &name_key);
+ if (k == kh_end(pkt_cache->index_by_name)) {
+ *lookup_result = PKT_CACHE_LU_NONE;
+ return NULL;
+ }
+
+ off_t index = kh_val(pkt_cache->index_by_name, k);
+ pkt_cache_entry_t *entry = pkt_cache_at(pkt_cache, index);
+ assert(entry);
+ bool expired = false;
+ if (entry->has_expire_ts && ticks_now() >= entry->expire_ts) {
+ expired = true;
+ }
+
+ if (entry->entry_type == PKT_CACHE_CS_TYPE) {
+ if (expired)
+ *lookup_result = PKT_CACHE_LU_DATA_EXPIRED;
+ else
+ *lookup_result = PKT_CACHE_LU_DATA_NOT_EXPIRED;
+ } else { // PKT_CACHE_PIT_TYPE
+ if (expired)
+ *lookup_result = PKT_CACHE_LU_INTEREST_EXPIRED;
+ else
+ *lookup_result = PKT_CACHE_LU_INTEREST_NOT_EXPIRED;
+ }
+
+ *entry_id = index;
+ return entry;
+}
+
+void pkt_cache_cs_remove_entry(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ msgbuf_pool_t *msgbuf_pool, bool is_evicted) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_CS_TYPE);
+
+ off_t msgbuf_id = entry->u.cs_entry.msgbuf_id;
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
+ Name name_key = name_key_factory(msgbuf_get_name(msgbuf));
+ khiter_t k = kh_get_pkt_cache_name(pkt_cache->index_by_name, &name_key);
+ assert(k != kh_end(pkt_cache->index_by_name));
+ free((Name *)kh_key(pkt_cache->index_by_name, k));
+ kh_del(pkt_cache_name, pkt_cache->index_by_name, k);
+
+ // Do not update the LRU cache for evicted entries
+ if (!is_evicted) cs_vft[pkt_cache->cs->type]->remove_entry(pkt_cache, entry);
+
+ pkt_cache->cs->num_entries--;
+ pool_put(pkt_cache->entries, entry);
+
+ WITH_DEBUG({
+ char *name_str = name_ToString(msgbuf_get_name(msgbuf));
+ DEBUG("Packet %s removed from CS", name_str);
+ free(name_str);
+ })
+
+ msgbuf_pool_release(msgbuf_pool, &msgbuf);
+}
+
+void pkt_cache_pit_remove_entry(pkt_cache_t *pkt_cache,
+ pkt_cache_entry_t *entry, const Name *name) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_PIT_TYPE);
+
+ Name name_key = name_key_factory(name);
+ khiter_t k = kh_get_pkt_cache_name(pkt_cache->index_by_name, &name_key);
+ assert(k != kh_end(pkt_cache->index_by_name));
+ free((Name *)kh_key(pkt_cache->index_by_name, k));
+ kh_del(pkt_cache_name, pkt_cache->index_by_name, k);
+
+ pool_put(pkt_cache->entries, entry);
+
+ WITH_DEBUG({
+ char *name_str = name_ToString(name);
+ DEBUG("Packet %s removed from PIT", name_str);
+ free(name_str);
+ })
+}
+
+void _pkt_cache_add_to_cs(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf,
+ off_t msgbuf_id, off_t entry_id) {
+ entry->u.cs_entry =
+ (cs_entry_t){.msgbuf_id = msgbuf_id,
+ .lru = {.prev = INVALID_ENTRY_ID, .next = INVALID_ENTRY_ID}};
+ entry->create_ts = ticks_now();
+ entry->expire_ts = ticks_now() + msgbuf_get_data_expiry_time(msgbuf);
+ entry->has_expire_ts = true;
+ entry->entry_type = PKT_CACHE_CS_TYPE;
+
+ pkt_cache->cs->num_entries++;
+
+ int tail_id = pkt_cache->cs->lru.tail;
+ int result = cs_vft[pkt_cache->cs->type]->add_entry(pkt_cache, entry_id);
+ if (result == LRU_EVICTION) {
+ // Remove tail (already removed from LRU cache)
+ pkt_cache_entry_t *tail = pkt_cache_entry_at(pkt_cache, tail_id);
+ assert(tail->entry_type == PKT_CACHE_CS_TYPE);
+ pkt_cache_cs_remove_entry(pkt_cache, tail, msgbuf_pool, true);
+ }
+
+ // Acquired by CS
+ msgbuf_pool_acquire(msgbuf);
+}
+
+void pkt_cache_pit_to_cs(pkt_cache_t *pkt_cache,
+ pkt_cache_entry_t *interest_entry,
+ msgbuf_pool_t *msgbuf_pool, msgbuf_t *data_msgbuf,
+ off_t data_msgbuf_id, off_t entry_id) {
+ assert(pkt_cache);
+ assert(interest_entry);
+ assert(interest_entry->entry_type == PKT_CACHE_PIT_TYPE);
+
+ _pkt_cache_add_to_cs(pkt_cache, interest_entry, msgbuf_pool, data_msgbuf,
+ data_msgbuf_id, entry_id);
+}
+
+void _pkt_cache_add_to_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ const msgbuf_t *msgbuf) {
+ entry->u.pit_entry = (pit_entry_t){
+ .ingressIdSet = NEXTHOPS_EMPTY,
+ .egressIdSet = NEXTHOPS_EMPTY,
+ .fib_entry = NULL,
+ };
+ pit_entry_ingress_add(&entry->u.pit_entry, msgbuf_get_connection_id(msgbuf));
+
+ entry->create_ts = ticks_now();
+ entry->expire_ts = ticks_now() + msgbuf_get_interest_lifetime(msgbuf);
+ entry->has_expire_ts = true;
+ entry->entry_type = PKT_CACHE_PIT_TYPE;
+}
+
+void pkt_cache_cs_to_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ msgbuf_pool_t *msgbuf_pool, const msgbuf_t *msgbuf,
+ off_t msgbuf_id, off_t entry_id) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_CS_TYPE);
+
+ // Release data associated with expired CS entry
+ off_t cs_entry_msgbuf_id = entry->u.cs_entry.msgbuf_id;
+ msgbuf_t *cs_entry_msgbuf = msgbuf_pool_at(msgbuf_pool, cs_entry_msgbuf_id);
+ msgbuf_pool_release(msgbuf_pool, &cs_entry_msgbuf);
+
+ cs_vft[pkt_cache->cs->type]->remove_entry(pkt_cache, entry);
+ _pkt_cache_add_to_pit(pkt_cache, entry, msgbuf);
+ pkt_cache->cs->num_entries--;
+}
+
+void pkt_cache_update_cs(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
+ pkt_cache_entry_t *entry, msgbuf_t *msgbuf,
+ off_t msgbuf_id) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_CS_TYPE);
+
+ // Release previous msgbuf and acquire new one
+ msgbuf_t *prev_msgbuf =
+ msgbuf_pool_at(msgbuf_pool, entry->u.cs_entry.msgbuf_id);
+ msgbuf_pool_release(msgbuf_pool, &prev_msgbuf);
+ msgbuf_pool_acquire(msgbuf);
+
+ entry->u.cs_entry.msgbuf_id = msgbuf_id;
+ entry->create_ts = ticks_now();
+ entry->expire_ts = ticks_now() + msgbuf_get_data_expiry_time(msgbuf);
+ entry->has_expire_ts = true;
+
+ cs_vft[pkt_cache->cs->type]->update_entry(pkt_cache, entry);
+}
+
+pkt_cache_entry_t *pkt_cache_add_to_pit(pkt_cache_t *pkt_cache,
+ const msgbuf_t *msgbuf) {
+ assert(pkt_cache);
+
+ pkt_cache_entry_t *entry =
+ pkt_cache_allocate(pkt_cache, msgbuf_get_name(msgbuf));
+ _pkt_cache_add_to_pit(pkt_cache, entry, msgbuf);
+ return entry;
+}
+
+pkt_cache_entry_t *pkt_cache_add_to_cs(pkt_cache_t *pkt_cache,
+ msgbuf_pool_t *msgbuf_pool,
+ msgbuf_t *msgbuf, off_t msgbuf_id) {
+ assert(pkt_cache);
+
+ pkt_cache_entry_t *entry =
+ pkt_cache_allocate(pkt_cache, msgbuf_get_name(msgbuf));
+ off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
+ _pkt_cache_add_to_cs(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id,
+ entry_id);
+
+ return entry;
+}
+
+void pkt_cache_update_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ const msgbuf_t *msgbuf) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_PIT_TYPE);
+
+ pit_entry_t *pit_entry = &entry->u.pit_entry;
+ fib_entry_t *fib_entry = pit_entry_get_fib_entry(pit_entry);
+ if (fib_entry)
+ fib_entry_on_timeout(fib_entry, pit_entry_get_egress(pit_entry));
+
+ _pkt_cache_add_to_pit(pkt_cache, entry, msgbuf);
+}
+
+bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache,
+ pkt_cache_entry_t *entry,
+ const msgbuf_t *msgbuf) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_PIT_TYPE);
+
+ pit_entry_t *pit_entry = &entry->u.pit_entry;
+
+ // Extend entry lifetime
+ Ticks expire_ts = ticks_now() + msgbuf_get_interest_lifetime(msgbuf);
+ if (expire_ts > entry->expire_ts) entry->expire_ts = expire_ts;
+
+ // Check if the reverse path is already present
+ // in the PIT entry (i.e. it is a retransmission)
+ unsigned connection_id = msgbuf_get_connection_id(msgbuf);
+ bool is_aggregated = !pit_entry_ingress_contains(pit_entry, connection_id);
+ if (is_aggregated) pit_entry_ingress_add(pit_entry, connection_id);
+
+ WITH_DEBUG({
+ char *name_str = name_ToString(msgbuf_get_name(msgbuf));
+ if (is_aggregated) {
+ DEBUG("Interest %s already existing (expiry %lu): aggregate", name_str,
+ entry->expire_ts);
+ } else {
+ DEBUG("Interest %s already existing (expiry %lu): retransmit", name_str,
+ entry->expire_ts);
+ }
+ free(name_str);
+ })
+
+ return is_aggregated;
+}
+
+nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache,
+ msgbuf_pool_t *msgbuf_pool, off_t msgbuf_id,
+ bool is_cs_store_enabled,
+ bool is_connection_local, bool *wrong_egress,
+ pkt_cache_verdict_t *verdict) {
+ assert(pkt_cache);
+ assert(msgbuf_id_is_valid(msgbuf_id));
+
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA);
+
+ *wrong_egress = false;
+ off_t entry_id;
+ pkt_cache_lookup_t lookup_result;
+ pkt_cache_entry_t *entry =
+ pkt_cache_lookup(pkt_cache, msgbuf_get_name(msgbuf), msgbuf_pool,
+ &lookup_result, &entry_id, true);
+
+ pit_entry_t *pit_entry;
+ fib_entry_t *fib_entry;
+ nexthops_t *nexthops = NULL;
+ nexthops_t *nexthops_copy;
+ switch (lookup_result) {
+ case PKT_CACHE_LU_INTEREST_NOT_EXPIRED:
+ pit_entry = &entry->u.pit_entry;
+ fib_entry = pit_entry_get_fib_entry(pit_entry);
+ if (fib_entry)
+ fib_entry_on_data(fib_entry, pit_entry_get_egress(pit_entry), msgbuf,
+ entry->create_ts, ticks_now());
+
+ // Check if the data is coming from the exepected connection
+ nexthops_t *egressIdSet = pit_entry_get_egress(pit_entry);
+ unsigned egress_connection = msgbuf_get_connection_id(msgbuf);
+ if (!nexthops_contains(egressIdSet, egress_connection)) {
+ *wrong_egress = true;
+ return NULL;
+ }
+
+ // XXX TODO : be sure nexthops are valid b/c pit entry is removed
+ // XXX TODO eventually pass holding structure as parameter
+ nexthops = pit_entry_get_ingress(pit_entry);
+ assert(nexthops);
+
+ nexthops_copy = (nexthops_t *)malloc(sizeof(*nexthops_copy));
+ *nexthops_copy = *nexthops;
+
+ if (is_cs_store_enabled) {
+ pkt_cache_pit_to_cs(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id,
+ entry_id);
+ *verdict = PKT_CACHE_VERDICT_FORWARD_DATA;
+ } else {
+ pkt_cache_pit_remove_entry(pkt_cache, entry, msgbuf_get_name(msgbuf));
+ *verdict = PKT_CACHE_VERDICT_CLEAR_DATA;
+ }
+
+ return nexthops_copy;
+
+ // Data packets are stored in the content store even in the case
+ // where there is no match in the PIT, to allow applications to push
+ // content to the forwarder's CS. This behavior is allowed only for
+ // local faces.
+ case PKT_CACHE_LU_INTEREST_EXPIRED:
+ if (is_cs_store_enabled && is_connection_local) {
+ pkt_cache_pit_to_cs(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id,
+ entry_id);
+ *verdict = PKT_CACHE_VERDICT_STORE_DATA;
+ } else {
+ pkt_cache_pit_remove_entry(pkt_cache, entry, msgbuf_get_name(msgbuf));
+ *verdict = PKT_CACHE_VERDICT_CLEAR_DATA;
+ }
+ return NULL;
+
+ case PKT_CACHE_LU_NONE:
+ *verdict = PKT_CACHE_VERDICT_IGNORE_DATA;
+ if (is_cs_store_enabled && is_connection_local) {
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, msgbuf_id);
+ *verdict = PKT_CACHE_VERDICT_STORE_DATA;
+ }
+ return NULL;
+
+ case PKT_CACHE_LU_DATA_EXPIRED:
+ if (is_cs_store_enabled && is_connection_local) {
+ pkt_cache_update_cs(pkt_cache, msgbuf_pool, entry, msgbuf, msgbuf_id);
+ *verdict = PKT_CACHE_VERDICT_UPDATE_DATA;
+ } else {
+ pkt_cache_cs_remove_entry(pkt_cache, entry, msgbuf_pool, false);
+ *verdict = PKT_CACHE_VERDICT_CLEAR_DATA;
+ }
+ return NULL;
+
+ case PKT_CACHE_LU_DATA_NOT_EXPIRED:
+ *verdict = PKT_CACHE_VERDICT_IGNORE_DATA;
+ if (is_cs_store_enabled && is_connection_local) {
+ pkt_cache_update_cs(pkt_cache, msgbuf_pool, entry, msgbuf, msgbuf_id);
+ *verdict = PKT_CACHE_VERDICT_UPDATE_DATA;
+ }
+ return NULL;
+
+ default:
+ ERROR("Inivalid packet cache content");
+ return NULL;
+ }
+}
+
+void pkt_cache_on_interest(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
+ off_t msgbuf_id, pkt_cache_verdict_t *verdict,
+ off_t *data_msgbuf_id, pkt_cache_entry_t **entry_ptr,
+ bool is_serve_from_cs_enabled) {
+ assert(pkt_cache);
+ assert(msgbuf_id_is_valid(msgbuf_id));
+
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
+
+ off_t entry_id;
+ pkt_cache_lookup_t lookup_result;
+ pkt_cache_entry_t *entry =
+ pkt_cache_lookup(pkt_cache, msgbuf_get_name(msgbuf), msgbuf_pool,
+ &lookup_result, &entry_id, is_serve_from_cs_enabled);
+ *entry_ptr = entry;
+
+ cs_entry_t *cs_entry = NULL;
+ bool is_cs_miss = true;
+ bool is_aggregated;
+ switch (lookup_result) {
+ case PKT_CACHE_LU_NONE:
+ *verdict = PKT_CACHE_VERDICT_FORWARD_INTEREST;
+ break;
+
+ case PKT_CACHE_LU_DATA_NOT_EXPIRED:
+ if (!is_serve_from_cs_enabled) goto PKT_CACHE_LU_DATA_EXPIRED;
+
+ cs_entry = &entry->u.cs_entry;
+ *data_msgbuf_id = cs_entry->msgbuf_id;
+
+ *verdict = PKT_CACHE_VERDICT_FORWARD_DATA;
+ is_cs_miss = false;
+ break;
+
+ case PKT_CACHE_LU_INTEREST_NOT_EXPIRED:
+ is_aggregated = pkt_cache_try_aggregate_in_pit(pkt_cache, entry, msgbuf);
+
+ *verdict = is_aggregated ? PKT_CACHE_VERDICT_AGGREGATE_INTEREST
+ : PKT_CACHE_VERDICT_RETRANSMIT_INTEREST;
+ break;
+
+ case PKT_CACHE_LU_INTEREST_EXPIRED:
+ pkt_cache_update_pit(pkt_cache, entry, msgbuf);
+
+ *verdict = PKT_CACHE_VERDICT_INTEREST_EXPIRED_FORWARD_INTEREST;
+ break;
+
+ case PKT_CACHE_LU_DATA_EXPIRED:
+ PKT_CACHE_LU_DATA_EXPIRED:
+ pkt_cache_cs_to_pit(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id,
+ entry_id);
+
+ *verdict = PKT_CACHE_VERDICT_DATA_EXPIRED_FORWARD_INTEREST;
+ break;
+
+ default:
+ *verdict = PKT_CACHE_VERDICT_ERROR;
+ }
+ is_cs_miss ? cs_miss(pkt_cache->cs) : cs_hit(pkt_cache->cs);
+}
+
+void pkt_cache_cs_clear(pkt_cache_t *pkt_cache) {
+ assert(pkt_cache);
+
+ const Name *k_name;
+ unsigned v_pool_pos;
+ kh_foreach(pkt_cache->index_by_name, k_name, v_pool_pos,
+ {
+ khiter_t k =
+ kh_get_pkt_cache_name(pkt_cache->index_by_name, k_name);
+ assert(k != kh_end(pkt_cache->index_by_name));
+
+ pkt_cache_entry_t *entry = pkt_cache_at(pkt_cache, v_pool_pos);
+ if (entry->entry_type == PKT_CACHE_CS_TYPE) {
+ // Remove from hashmap
+ free((Name *)kh_key(pkt_cache->index_by_name, k));
+ kh_del(pkt_cache_name, pkt_cache->index_by_name, k);
+
+ // Remove from pool
+ pool_put(pkt_cache->entries, entry);
+ }
+ })
+
+ // Re-create CS
+ cs_clear(pkt_cache->cs);
+}
+
+size_t pkt_cache_get_size(pkt_cache_t *pkt_cache) {
+ uint64_t hashmap_size = kh_size(pkt_cache->index_by_name);
+ return hashmap_size;
+}
+
+size_t pkt_cache_get_cs_size(pkt_cache_t *pkt_cache) {
+ return pkt_cache->cs->num_entries;
+}
+
+size_t pkt_cache_get_num_cs_stale_entries(pkt_cache_t *pkt_cache) {
+ size_t num_stale_entries = 0;
+ Ticks now = ticks_now();
+ pkt_cache_entry_t *entry;
+
+ pool_foreach(pkt_cache->entries, entry, {
+ if (entry->entry_type == PKT_CACHE_CS_TYPE && entry->has_expire_ts &&
+ now >= entry->expire_ts) {
+ num_stale_entries++;
+ }
+ });
+
+ return num_stale_entries;
+}
+
+int pkt_cache_set_cs_size(pkt_cache_t *pkt_cache, size_t size) {
+ if (pkt_cache->cs->num_entries > size) return -1;
+
+ pkt_cache->cs->max_size = size;
+ return 0;
+}
+
+size_t pkt_cache_get_pit_size(pkt_cache_t *pkt_cache) {
+ uint64_t hashmap_size = kh_size(pkt_cache->index_by_name);
+ uint64_t pit_size = hashmap_size - pkt_cache->cs->num_entries;
+ return pit_size;
+}
+
+void pkt_cache_log(pkt_cache_t *pkt_cache) {
+ uint64_t hashmap_size = kh_size(pkt_cache->index_by_name);
+ uint64_t pit_size = hashmap_size - pkt_cache->cs->num_entries;
+ DEBUG("Packet cache: total size = %lu, PIT size = %lu, CS size = %u",
+ hashmap_size, pit_size, pkt_cache->cs->num_entries);
+
+ cs_log(pkt_cache->cs);
+}