aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-plugin/src/pcs.h
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-plugin/src/pcs.h')
-rw-r--r--hicn-plugin/src/pcs.h1166
1 files changed, 583 insertions, 583 deletions
diff --git a/hicn-plugin/src/pcs.h b/hicn-plugin/src/pcs.h
index 083efa901..2019ddb73 100644
--- a/hicn-plugin/src/pcs.h
+++ b/hicn-plugin/src/pcs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -16,25 +16,34 @@
#ifndef __HICN_PCS_H__
#define __HICN_PCS_H__
-#include "hashtb.h"
-#include "face_db.h"
#include "strategy_dpo_manager.h"
#include "error.h"
#include "cache_policies/cs_policy.h"
#include "faces/face.h"
+#include <vppinfra/bihash_24_8.h>
+
/**
* @file pcs.h
*
* This file implement the PIT and CS which are collapsed in the same
- * structure, thereore an entry is either a PIT entry of a CS entry.
- * The implementation consist of a hash table where each entry of the
- * hash table contains a PIT or CS entry, some counters to maintain the
- * status of the PIT/CS and the reference to the eviction policy for
- * the CS. The default eviction policy id FIFO.
+ * structure, therefore an entry is either a PIT entry of a CS entry.
+ * The implementation consists of a hash table where each entry of the
+ * hash table contains an index to a pool of PIT/CS entries. Each entry
+ * contains some counters to maintain the status of the PIT/CS and the
+ * reference to the eviction policy for the CS.
+ * The default eviction policy is LRU.
*/
-/* The PIT and CS are stored as a union */
+/*
+ * We need a definition of invalid index. ~0 is reasonable as we don't expect
+ * to reach that many element in the PIT.
+ */
+#define HICN_PCS_INVALID_INDEX ((u32) (~0))
+
+/*
+ * The PIT and CS are stored as a union
+ */
#define HICN_PIT_NULL_TYPE 0
#define HICN_PIT_TYPE 1
#define HICN_CS_TYPE 2
@@ -49,778 +58,769 @@
#define HICN_INFRA_SLOW_TIMER_SECS 60
#define HICN_INFRA_SLOW_TIMER_MSECS (HICN_INFRA_SLOW_TIMER_SECS * SEC_MS)
+#define HICN_CS_ENTRY_OPAQUE_SIZE 32
+
+#define HICN_FACE_DB_INLINE_FACES 8
+
+#define HICN_PIT_BITMAP_SIZE_U64 HICN_PARAM_FACES_MAX / 64
+#define HICN_PIT_N_HOP_BITMAP_SIZE HICN_PARAM_FACES_MAX
+
/*
- * Note that changing this may change alignment within the PIT struct, so be
- * careful.
+ * PCS entry. We expect this to fit in 3 cache lines, with a maximum of 8
+ * output inline faces and a bitmap of 512 bits. If more faces are needed, a
+ * vector will be allocated, but it will endup out of the 3 cache lines.
*/
-typedef struct __attribute__ ((packed)) hicn_pcs_shared_s
+typedef struct hicn_pcs_entry_s
{
+ /*
+ * First cache line - shared data
+ */
+ CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
- /* Installation/creation time (vpp float units, for now) */
+ /*
+ * Installation/creation time (vpp float units, for now).
+ * 8 Bytes
+ */
f64 create_time;
- /* Expiration time (vpp float units, for now) */
+ /*
+ * Expiration time (vpp float units, for now)
+ * 8 Bytes
+ */
f64 expire_time;
- /* Shared 'flags' octet */
- u8 entry_flags;
-
- /* Needed to align for the pit or cs portion */
- u8 padding;
-} hicn_pcs_shared_t;
-
-#define HICN_PCS_ENTRY_CS_FLAG 0x01
+ /*
+ * Name
+ * 24 bytes
+ */
+ hicn_name_t name;
-/*
- * PIT entry, unioned with a CS entry below
- */
-typedef struct __attribute__ ((packed)) hicn_pit_entry_s
-{
+ /*
+ * Cached hash of the name
+ * 8 bytes
+ */
+ u64 name_hash;
- /* Shared size 8 + 8 + 2 = 18B */
+ /*
+ * Shared 'flags' octet
+ * 1 Byte
+ */
+ u16 flags;
/*
- * Egress next hop (containes the egress face) This id refers to the
- * position of the choosen face in the next_hops array of the dpo */
- /* 18B + 1B = 19B */
- u8 pe_txnh;
+ * Number of locks on the PCS entry
+ * 2 Bytes
+ */
+ u16 locks;
- /* Array of incoming ifaces */
- /* 24B + 32B (8B*4) =56B */
- hicn_face_db_t faces;
+ /*
+ * Second cache line - PIT or CS data
+ */
+ CLIB_ALIGN_MARK (second_part, 64);
-} hicn_pit_entry_t;
+ union
+ {
+ struct
+ {
+ /*
+ * Bitmap used to check if interests are retransmission
+ */
+ u64 bitmap[HICN_PIT_BITMAP_SIZE_U64];
-#define HICN_CS_ENTRY_OPAQUE_SIZE HICN_HASH_NODE_APP_DATA_SIZE - 36
+ CLIB_ALIGN_MARK (third_part, 64);
-/*
- * CS entry, unioned with a PIT entry below
- */
-typedef struct __attribute__ ((packed)) hicn_cs_entry_s
-{
- /* 18B + 2B = 20B */
- u16 align;
+ /*
+ * Total number of faces
+ */
+ u32 n_faces;
- /* Packet buffer, if held */
- /* 20B + 4B = 24B */
- u32 cs_pkt_buf;
+ /*
+ * Array of indexes of virtual faces
+ */
+ hicn_face_id_t inline_faces[HICN_FACE_DB_INLINE_FACES];
- /* Ingress face */
- /* 24B + 4B = 28B */
- hicn_face_id_t cs_rxface;
+ /*
+ * VPP vector of indexes of additional virtual faces, allocated iff
+ * needed
+ */
+ hicn_face_id_t *faces;
+ } pit;
+ struct
+ { /*
+ * Packet buffer, if held
+ * 4 Bytes
+ */
+ u32 cs_pkt_buf;
- /* Linkage for LRU, in the form of hashtable node indexes */
- /* 28B + 8B = 36B */
- u32 cs_lru_prev;
- u32 cs_lru_next;
+ /*
+ * Linkage for LRU, in the form of hashtable node indexes
+ * 8 Bytes
+ */
+ u32 cs_lru_prev;
+ u32 cs_lru_next;
+ } cs;
+ } u;
+} hicn_pcs_entry_t;
- /* Reserved for implementing cache policy different than LRU */
- /* 36B + (64 - 36)B = 64B */
- u8 opaque[HICN_CS_ENTRY_OPAQUE_SIZE];
+STATIC_ASSERT (sizeof (hicn_pcs_entry_t) <= 3 * CLIB_CACHE_LINE_BYTES,
+ "hicn_pcs_entry_t does not fit in 3 cache lines.");
+
+STATIC_ASSERT (0 == offsetof (hicn_pcs_entry_t, cacheline0),
+ "Cacheline0 must be at the beginning of hicn_pcs_entry_t");
+STATIC_ASSERT (64 == offsetof (hicn_pcs_entry_t, second_part),
+ "second_part must be at byte 64 of hicn_pcs_entry_t");
+STATIC_ASSERT (64 == offsetof (hicn_pcs_entry_t, u.pit.bitmap),
+ "u.pit.bitmap must be at byte 64 of hicn_pcs_entry_t");
+STATIC_ASSERT (64 == offsetof (hicn_pcs_entry_t, u.pit.bitmap),
+ "cs_pkt_buf must be at byte 64 of hicn_pcs_entry_t");
+STATIC_ASSERT (128 == offsetof (hicn_pcs_entry_t, u.pit.third_part),
+ "third_part must be at byte 128 of hicn_pcs_entry_t");
+STATIC_ASSERT (128 == offsetof (hicn_pcs_entry_t, u.pit.n_faces),
+ "u.pit.n_faces must be at byte 128 of hicn_pcs_entry_t");
-} __attribute__ ((packed)) hicn_cs_entry_t;
+#define HICN_PCS_ENTRY_CS_FLAG 0x01
/*
- * Combined PIT/CS entry data structure, embedded in a hashtable entry after
- * the common hashtable preamble struct. This MUST fit in the available
- * (fixed) space in a hashtable node.
+ * Forward declarations
*/
-typedef struct hicn_pcs_entry_s
-{
+always_inline void hicn_pcs_delete_internal (hicn_pit_cs_t *pitcs,
+ hicn_pcs_entry_t *pcs_entry);
- hicn_pcs_shared_t shared;
-
- union
- {
- hicn_pit_entry_t pit;
- hicn_cs_entry_t cs;
- } u;
-} hicn_pcs_entry_t;
+always_inline void hicn_pcs_entry_remove_lock (hicn_pit_cs_t *pitcs,
+ hicn_pcs_entry_t *pcs_entry);
/*
- * Overall PIT/CS table, based on the common hashtable
+ * Overall PIT/CS table.
*/
typedef struct hicn_pit_cs_s
{
+ // Hash table mapping name to hash entry index
+ clib_bihash_24_8_t pcs_table;
+
+ // Total size of PCS
+ u32 max_pit_size;
- hicn_hashtb_t *pcs_table;
+ // Pool of pcs entries
+ hicn_pcs_entry_t *pcs_entries_pool;
/* Counters for PIT/CS sentries */
u32 pcs_pit_count;
u32 pcs_cs_count;
- u32 pcs_cs_dealloc;
- u32 pcs_pit_dealloc;
-
- /* Total size of PCS */
- u32 pcs_size;
+ u32 pcs_pcs_alloc;
+ u32 pcs_pcs_dealloc;
hicn_cs_policy_t policy_state;
- hicn_cs_policy_vft_t policy_vft;
-
} hicn_pit_cs_t;
-/* Functions declarations */
-int hicn_pit_create (hicn_pit_cs_t *p, u32 num_elems);
-
-always_inline void hicn_pit_to_cs (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t *pcs_entry,
- hicn_hash_entry_t *hash_entry,
- hicn_hash_node_t *node,
- const hicn_dpo_vft_t *dpo_vft,
- dpo_id_t *hicn_dpo_id,
- hicn_face_id_t inface_id, u8 is_appface);
-
-always_inline void hicn_pcs_cs_update (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t *old_entry,
- hicn_pcs_entry_t *entry,
- hicn_hash_node_t *node);
-
-always_inline void hicn_pcs_cs_delete (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t **pcs_entry,
- hicn_hash_node_t **node,
- hicn_hash_entry_t *hash_entry,
- const hicn_dpo_vft_t *dpo_vft,
- dpo_id_t *hicn_dpo_id);
-
-always_inline int
-hicn_pcs_cs_insert (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t *entry, hicn_hash_node_t *node,
- hicn_hash_entry_t **hash_entry, u64 hashval, u32 *node_id,
- index_t *dpo_ctx_id, u8 *vft_id, u8 *is_cs,
- u8 *hash_entry_id, u32 *bucket_id, u8 *bucket_is_overflow);
-
-always_inline int hicn_pcs_cs_insert_update (
- vlib_main_t *vm, hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *entry,
- hicn_hash_node_t *node, hicn_hash_entry_t **hash_entry, u64 hashval,
- u32 *node_id, index_t *dpo_ctx_id, u8 *vft_id, u8 *is_cs, u8 *hash_entry_id,
- u32 *bucket_id, u8 *bucket_is_overflow, hicn_face_id_t inface);
-
-always_inline int
-hicn_pcs_pit_insert (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *entry,
- hicn_hash_node_t *node, hicn_hash_entry_t **hash_entry,
- u64 hashval, u32 *node_id, index_t *dpo_ctx_id,
- u8 *vft_id, u8 *is_cs, u8 *hash_entry_id, u32 *bucket_id,
- u8 *bucket_is_overflow);
-
-always_inline void
-hicn_pcs_pit_delete (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t **pcs_entryp,
- hicn_hash_node_t **node, vlib_main_t *vm,
- hicn_hash_entry_t *hash_entry,
- const hicn_dpo_vft_t *dpo_vft, dpo_id_t *hicn_dpo_id);
-
-always_inline int hicn_pcs_insert (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t *entry,
- hicn_hash_node_t *node,
- hicn_hash_entry_t **hash_entry, u64 hashval,
- u32 *node_id, index_t *dpo_ctx_id,
- u8 *vft_id, u8 *is_cs, u8 *hash_entry_id,
- u32 *bucket_id, u8 *bucket_is_overflow);
-
-always_inline void hicn_pcs_delete (hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t **pcs_entryp,
- hicn_hash_node_t **node, vlib_main_t *vm,
- hicn_hash_entry_t *hash_entry,
- const hicn_dpo_vft_t *dpo_vft,
- dpo_id_t *hicn_dpo_id);
+/************************************************************************
+ **************************** Create / Destroy **************************
+ ************************************************************************/
-always_inline void
-hicn_pcs_remove_lock (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t **pcs_entryp,
- hicn_hash_node_t **node, vlib_main_t *vm,
- hicn_hash_entry_t *hash_entry,
- const hicn_dpo_vft_t *dpo_vft, dpo_id_t *hicn_dpo_id);
+void hicn_pit_create (hicn_pit_cs_t *p, u32 max_pit_elt, u32 max_cs_elt);
+void hicn_pit_destroy (hicn_pit_cs_t *p);
-always_inline void hicn_cs_delete_trimmed (hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t **pcs_entryp,
- hicn_hash_entry_t *hash_entry,
- hicn_hash_node_t **node,
- vlib_main_t *vm);
+/************************************************************************
+ **************************** Counters getters **************************
+ ************************************************************************/
-/* Function implementation */
-/* Accessor for pit/cs data inside hash table node */
-static inline hicn_pcs_entry_t *
-hicn_pit_get_data (hicn_hash_node_t *node)
+always_inline u32
+hicn_pcs_get_pit_count (const hicn_pit_cs_t *pcs)
{
- return (hicn_pcs_entry_t *) (hicn_hashtb_node_data (node));
+ return pcs->pcs_pit_count;
}
-/* Init pit/cs data block (usually inside hash table node) */
-static inline void
-hicn_pit_init_data (hicn_pcs_entry_t *p)
+always_inline u32
+hicn_pcs_get_cs_count (const hicn_pit_cs_t *pcs)
{
- p->shared.entry_flags = 0;
- p->u.pit.faces.n_faces = 0;
- p->u.pit.faces.is_overflow = 0;
- hicn_face_bucket_t *face_bkt;
- pool_get (hicn_face_bucket_pool, face_bkt);
+ return pcs->pcs_cs_count;
+}
- p->u.pit.faces.next_bucket = face_bkt - hicn_face_bucket_pool;
+always_inline u32
+hicn_pcs_get_pcs_alloc (const hicn_pit_cs_t *pcs)
+{
+ return pcs->pcs_pcs_alloc;
}
-/* Init pit/cs data block (usually inside hash table node) */
-static inline void
-hicn_cs_init_data (hicn_pcs_entry_t *p)
+always_inline u32
+hicn_pcs_get_pcs_dealloc (const hicn_pit_cs_t *pcs)
{
- p->shared.entry_flags = 0;
- p->u.pit.faces.n_faces = 0;
- p->u.pit.faces.is_overflow = 0;
+ return pcs->pcs_pcs_dealloc;
}
-static inline f64
+always_inline f64
hicn_pcs_get_exp_time (f64 cur_time_sec, u64 lifetime_msec)
{
return (cur_time_sec + ((f64) lifetime_msec) / SEC_MS);
}
/*
- * Configure CS LRU limit. Zero is accepted, means 'no limit', probably not a
- * good choice.
+ * Create key from the name struct.
*/
-static inline void
-hicn_pit_set_lru_max (hicn_pit_cs_t *p, u32 limit)
+always_inline void
+hicn_pcs_get_key_from_name (clib_bihash_kv_24_8_t *kv, const hicn_name_t *name)
{
- p->policy_state.max = limit;
+ kv->key[0] = name->prefix.v6.as_u64[0];
+ kv->key[1] = name->prefix.v6.as_u64[1];
+ kv->key[2] = name->suffix;
+}
+
+/************************************************************************
+ **************************** LRU Helpers *******************************
+ ************************************************************************/
+
+always_inline hicn_cs_policy_t *
+hicn_pcs_get_policy_state (hicn_pit_cs_t *pcs)
+{
+ return &pcs->policy_state;
}
/*
- * Accessor for PIT interest counter.
+ * Update the CS LRU, moving this item to the head
*/
-static inline u32
-hicn_pit_get_int_count (const hicn_pit_cs_t *pitcs)
+always_inline void
+hicn_pcs_cs_update_lru (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *entry)
{
- return (pitcs->pcs_pit_count);
+ hicn_cs_policy_t *policy_state = hicn_pcs_get_policy_state (pitcs);
+ hicn_cs_policy_update (policy_state, pitcs, entry);
}
/*
- * Accessor for PIT cs entries counter.
+ * Update the CS LRU, inserting a new item and checking if we need to evict
*/
-static inline u32
-hicn_pit_get_cs_count (const hicn_pit_cs_t *pitcs)
+always_inline void
+hicn_pcs_cs_insert_lru (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *entry)
{
- return (pitcs->pcs_cs_count);
+ hicn_cs_policy_t *policy_state = hicn_pcs_get_policy_state (pitcs);
+ hicn_cs_policy_insert (policy_state, pitcs, entry);
+ pitcs->pcs_cs_count++;
+
+ // If we reached the MAX size of the CS, let's evict one
+ if (policy_state->count > policy_state->max)
+ {
+ // We reached the mac number of CS entry. We need to trim one.
+ hicn_pcs_entry_t *pcs_entry;
+ hicn_cs_policy_delete_get (policy_state, pitcs, &pcs_entry);
+
+ // Delete evicted entry from hash table
+ hicn_pcs_entry_remove_lock (pitcs, pcs_entry);
+ }
}
-static inline u32
-hicn_pcs_get_ntw_count (const hicn_pit_cs_t *pitcs)
+/*
+ * Dequeue an entry from the CS LRU
+ */
+always_inline void
+hicn_pcs_cs_dequeue_lru (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *entry)
{
- return (pitcs->policy_state.count);
+ // Dequeue the CS entry
+ hicn_cs_policy_t *policy_state = hicn_pcs_get_policy_state (pitcs);
+ hicn_cs_policy_dequeue (policy_state, pitcs, entry);
}
-static inline u32
-hicn_pit_get_htb_bucket_count (const hicn_pit_cs_t *pitcs)
+/************************************************************************
+ **************************** PCS Entry APIs ****************************
+ ************************************************************************/
+
+/*
+ * Create new PCS entry
+ */
+always_inline hicn_pcs_entry_t *
+_hicn_pcs_entry_get (hicn_pit_cs_t *pitcs)
{
- return (pitcs->pcs_table->ht_overflow_buckets_used);
+ hicn_pcs_entry_t *e;
+ pool_get (pitcs->pcs_entries_pool, e);
+ pitcs->pcs_pcs_alloc++;
+
+ return e;
}
-static inline int
-hicn_cs_enabled (hicn_pit_cs_t *pit)
+/*
+ * Init pit/cs data block
+ */
+always_inline void
+hicn_pcs_entry_init_data (hicn_pcs_entry_t *p, f64 tnow)
{
- switch (HICN_FEATURE_CS)
- {
- case 0:
- default:
- return (0);
- case 1:
- return (pit->policy_state.max > 0);
- }
+ p->flags = 0;
+ p->u.pit.n_faces = 0;
+ p->locks = 1;
+ p->create_time = tnow;
}
/*
- * Delete a PIT/CS entry from the hashtable, freeing the hash node struct.
- * The caller's pointers are zeroed! If cs_trim is true, entry has already
- * been removed from lru list The main purpose of this wrapper is helping
- * maintain the per-PIT stats.
+ * Free PCS entry
*/
always_inline void
-hicn_pcs_delete_internal (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t **pcs_entryp,
- hicn_hash_entry_t *hash_entry,
- hicn_hash_node_t **node, vlib_main_t *vm,
- const hicn_dpo_vft_t *dpo_vft, dpo_id_t *hicn_dpo_id)
+hicn_pcs_entry_put (hicn_pit_cs_t *pitcs, const hicn_pcs_entry_t *entry)
{
- hicn_pcs_entry_t *pcs = *pcs_entryp;
+ pitcs->pcs_pcs_dealloc++;
+ pool_put (pitcs->pcs_entries_pool, entry);
+}
- ASSERT (pcs == hicn_hashtb_node_data (*node));
+/*
+ * Get index from the entry.
+ */
+always_inline u32
+hicn_pcs_entry_get_index (const hicn_pit_cs_t *pitcs,
+ const hicn_pcs_entry_t *entry)
+{
+ ASSERT (!pool_is_free (pitcs->pcs_entries_pool, entry));
+ return (u32) (entry - pitcs->pcs_entries_pool);
+}
- if (hash_entry->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY)
- {
- pitcs->pcs_cs_dealloc++;
- /* Free any associated packet buffer */
- vlib_buffer_free_one (vm, pcs->u.cs.cs_pkt_buf);
- pcs->u.cs.cs_pkt_buf = ~0;
- ASSERT ((pcs->u.cs.cs_lru_prev == 0) &&
- (pcs->u.cs.cs_lru_prev == pcs->u.cs.cs_lru_next));
- }
- else
- {
- pitcs->pcs_pit_dealloc++;
- hicn_strategy_dpo_ctx_unlock (hicn_dpo_id);
+/*
+ * Get index from the entry.
+ */
+always_inline hicn_pcs_entry_t *
+hicn_pcs_entry_get_entry_from_index (const hicn_pit_cs_t *pitcs, u32 index)
+{
+ ASSERT (!pool_is_free_index (pitcs->pcs_entries_pool, index));
+ return pool_elt_at_index (pitcs->pcs_entries_pool, index);
+}
- /* Flush faces */
- hicn_faces_flush (&(pcs->u.pit.faces));
- }
+always_inline hicn_pcs_entry_t *
+hicn_pcs_entry_get_entry_from_index_safe (const hicn_pit_cs_t *pitcs,
+ u32 index)
+{
+ if (!pool_is_free_index (pitcs->pcs_entries_pool, index))
+ return pool_elt_at_index (pitcs->pcs_entries_pool, index);
- hicn_hashtb_delete (pitcs->pcs_table, node, hash_entry->he_msb64);
- *pcs_entryp = NULL;
+ return NULL;
}
/*
- * Convert a PIT entry into a CS entry (assumes that the entry is already in
- * the hashtable.) This is primarily here to maintain the internal counters.
+ * Check if pcs entry is a content store entry
*/
-always_inline void
-hicn_pit_to_cs (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t *pcs_entry, hicn_hash_entry_t *hash_entry,
- hicn_hash_node_t *node, const hicn_dpo_vft_t *dpo_vft,
- dpo_id_t *hicn_dpo_id, hicn_face_id_t inface_id, u8 is_appface)
+always_inline int
+hicn_pcs_entry_is_cs (const hicn_pcs_entry_t *entry)
{
+ ASSERT (entry);
+ return (entry->flags & HICN_PCS_ENTRY_CS_FLAG);
+}
- /*
- * Different from the insert node. In here we don't need to add a new
- * hash entry.
- */
- pitcs->pcs_pit_count--;
- hicn_strategy_dpo_ctx_unlock (hicn_dpo_id);
- /* Flush faces */
- hicn_faces_flush (&(pcs_entry->u.pit.faces));
+/*
+ * Add lock to PIT entry
+ */
+always_inline void
+hicn_pcs_entry_add_lock (hicn_pcs_entry_t *pcs_entry)
+{
+ pcs_entry->locks++;
+}
- hash_entry->he_flags |= HICN_HASH_ENTRY_FLAG_CS_ENTRY;
- node->hn_flags |= HICN_HASH_NODE_CS_FLAGS;
- pcs_entry->shared.entry_flags |= HICN_PCS_ENTRY_CS_FLAG;
+/*
+ * Get/Set expire time from the entry
+ */
+always_inline f64
+hicn_pcs_entry_get_expire_time (hicn_pcs_entry_t *pcs_entry)
+{
+ return pcs_entry->expire_time;
+}
- pcs_entry->u.cs.cs_rxface = inface_id;
+always_inline void
+hicn_pcs_entry_set_expire_time (hicn_pcs_entry_t *pcs_entry, f64 expire_time)
+{
+ pcs_entry->expire_time = expire_time;
+}
- /* Update the CS according to the policy */
- hicn_cs_policy_t *policy_state;
- hicn_cs_policy_vft_t *policy_vft;
+/*
+ * Get/Set create time from the entry
+ */
+always_inline f64
+hicn_pcs_entry_get_create_time (hicn_pcs_entry_t *pcs_entry)
+{
+ return pcs_entry->create_time;
+}
- policy_state = &pitcs->policy_state;
- policy_vft = &pitcs->policy_vft;
+always_inline void
+hicn_pcs_entry_set_create_time (hicn_pcs_entry_t *pcs_entry, f64 create_time)
+{
+ pcs_entry->create_time = create_time;
+}
- policy_vft->hicn_cs_insert (pitcs, node, pcs_entry, policy_state);
- pitcs->pcs_cs_count++;
+/*
+ * Remove a lock in the entry and delete it if there are no pending lock and
+ * the entry is marked as to be deleted
+ */
+always_inline void
+hicn_pcs_entry_remove_lock (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *pcs_entry)
+{
+ // Make sure we are removing a lock on a valid entry
+ ASSERT (pcs_entry->locks > 0);
- if (policy_state->count > policy_state->max)
+ if (--pcs_entry->locks == 0)
{
- hicn_hash_node_t *node;
- hicn_pcs_entry_t *pcs_entry;
- hicn_hash_entry_t *hash_entry;
- policy_vft->hicn_cs_delete_get (pitcs, policy_state, &node, &pcs_entry,
- &hash_entry);
-
- /*
- * We don't have to decrease the lock (therefore we cannot
- * use hicn_pcs_cs_delete function)
- */
- policy_vft->hicn_cs_dequeue (pitcs, node, pcs_entry, policy_state);
-
- hicn_cs_delete_trimmed (pitcs, &pcs_entry, hash_entry, &node, vm);
-
- /* Update the global CS counter */
- pitcs->pcs_cs_count--;
+ hicn_pcs_delete_internal (pitcs, pcs_entry);
}
}
-/* Functions specific for PIT or CS */
+/************************************************************************
+ **************************** CS Entry APIs *****************************
+ ************************************************************************/
-always_inline void
-hicn_pcs_cs_update (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t *old_entry, hicn_pcs_entry_t *entry,
- hicn_hash_node_t *node)
+/*
+ * Create new CS entry
+ */
+always_inline hicn_pcs_entry_t *
+hicn_pcs_entry_cs_get (hicn_pit_cs_t *pitcs, f64 tnow, u32 buffer_index)
{
- hicn_cs_policy_t *policy_state;
- hicn_cs_policy_vft_t *policy_vft;
+ hicn_pcs_entry_t *ret = _hicn_pcs_entry_get (pitcs);
+ hicn_pcs_entry_init_data (ret, tnow);
+ ret->flags = HICN_PCS_ENTRY_CS_FLAG;
+ ret->u.cs.cs_lru_next = HICN_CS_POLICY_END_OF_CHAIN;
+ ret->u.cs.cs_lru_prev = HICN_CS_POLICY_END_OF_CHAIN;
- policy_state = &pitcs->policy_state;
- policy_vft = &pitcs->policy_vft;
+ return ret;
+}
- if (entry->u.cs.cs_rxface != old_entry->u.cs.cs_rxface)
- {
- /* Dequeue content from the old queue */
- policy_vft->hicn_cs_dequeue (pitcs, node, old_entry, policy_state);
-
- old_entry->u.cs.cs_rxface = entry->u.cs.cs_rxface;
- policy_state = &pitcs->policy_state;
- policy_vft = &pitcs->policy_vft;
-
- policy_vft->hicn_cs_insert (pitcs, node, old_entry, policy_state);
-
- if (policy_state->count > policy_state->max)
- {
- hicn_hash_node_t *node;
- hicn_pcs_entry_t *pcs_entry;
- hicn_hash_entry_t *hash_entry;
- policy_vft->hicn_cs_delete_get (pitcs, policy_state, &node,
- &pcs_entry, &hash_entry);
-
- /*
- * We don't have to decrease the lock (therefore we cannot
- * use hicn_pcs_cs_delete function)
- */
- policy_vft->hicn_cs_dequeue (pitcs, node, pcs_entry, policy_state);
-
- hicn_cs_delete_trimmed (pitcs, &pcs_entry, hash_entry, &node, vm);
-
- /* Update the global CS counter */
- pitcs->pcs_cs_count--;
- }
- }
- else
- /* Update the CS LRU, moving this item to the head */
- policy_vft->hicn_cs_update (pitcs, node, old_entry, policy_state);
+always_inline u32
+hicn_pcs_entry_cs_get_buffer (hicn_pcs_entry_t *pcs_entry)
+{
+ return pcs_entry->u.cs.cs_pkt_buf;
}
always_inline void
-hicn_pcs_cs_delete (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t **pcs_entryp, hicn_hash_node_t **nodep,
- hicn_hash_entry_t *hash_entry,
- const hicn_dpo_vft_t *dpo_vft, dpo_id_t *hicn_dpo_id)
+hicn_pcs_entry_cs_set_buffer (hicn_pcs_entry_t *pcs_entry, u32 buffer_index)
{
- if (!(hash_entry->he_flags & HICN_HASH_ENTRY_FLAG_DELETED))
- {
- hicn_cs_policy_t *policy_state;
- hicn_cs_policy_vft_t *policy_vft;
+ pcs_entry->u.cs.cs_pkt_buf = buffer_index;
+}
- policy_state = &pitcs->policy_state;
- policy_vft = &pitcs->policy_vft;
+always_inline u32
+hicn_pcs_entry_cs_get_next (hicn_pcs_entry_t *pcs_entry)
+{
+ return pcs_entry->u.cs.cs_lru_next;
+}
- policy_vft->hicn_cs_dequeue (pitcs, (*nodep), (*pcs_entryp),
- policy_state);
+always_inline void
+hicn_pcs_entry_cs_set_next (hicn_pcs_entry_t *pcs_entry, u32 next)
+{
+ pcs_entry->u.cs.cs_lru_next = next;
+}
- /* Update the global CS counter */
- pitcs->pcs_cs_count--;
- }
+always_inline u32
+hicn_pcs_entry_cs_get_prev (hicn_pcs_entry_t *pcs_entry)
+{
+ return pcs_entry->u.cs.cs_lru_prev;
+}
- /* A data could have been inserted in the CS through a push. In this case
- * locks == 0 */
- hash_entry->locks--;
- if (hash_entry->locks == 0)
- {
- hicn_pcs_delete_internal (pitcs, pcs_entryp, hash_entry, nodep, vm,
- dpo_vft, hicn_dpo_id);
- }
- else
- {
- hash_entry->he_flags |= HICN_HASH_ENTRY_FLAG_DELETED;
- }
+always_inline void
+hicn_pcs_entry_cs_set_prev (hicn_pcs_entry_t *pcs_entry, u32 prev)
+{
+ pcs_entry->u.cs.cs_lru_prev = prev;
}
-always_inline int
-hicn_pcs_cs_insert (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t *entry, hicn_hash_node_t *node,
- hicn_hash_entry_t **hash_entry, u64 hashval, u32 *node_id,
- index_t *dpo_ctx_id, u8 *vft_id, u8 *is_cs,
- u8 *hash_entry_id, u32 *bucket_id, u8 *bucket_is_overflow)
+/* Init pit/cs data block (usually inside hash table node) */
+always_inline void
+hicn_pcs_entry_cs_free_data (hicn_pcs_entry_t *p)
{
- ASSERT (entry == hicn_hashtb_node_data (node));
+ CLIB_UNUSED (u32 bi) = hicn_pcs_entry_cs_get_buffer (p);
- int ret = hicn_hashtb_insert (pitcs->pcs_table, node, hash_entry, hashval,
- node_id, dpo_ctx_id, vft_id, is_cs,
- hash_entry_id, bucket_id, bucket_is_overflow);
+#ifndef HICN_PCS_TESTING
+ // Release buffer
+ vlib_buffer_free_one (vlib_get_main (), bi);
+#endif
- if (PREDICT_TRUE (ret == HICN_ERROR_NONE))
- {
- /* Mark the entry as a CS entry */
- node->hn_flags |= HICN_HASH_NODE_CS_FLAGS;
- entry->shared.entry_flags |= HICN_PCS_ENTRY_CS_FLAG;
- (*hash_entry)->he_flags |= HICN_HASH_ENTRY_FLAG_CS_ENTRY;
-
- hicn_cs_policy_t *policy_state;
- hicn_cs_policy_vft_t *policy_vft;
-
- policy_state = &pitcs->policy_state;
- policy_vft = &pitcs->policy_vft;
-
- policy_vft->hicn_cs_insert (pitcs, node, entry, policy_state);
- pitcs->pcs_cs_count++;
-
- if (policy_state->count > policy_state->max)
- {
- hicn_hash_node_t *node;
- hicn_pcs_entry_t *pcs_entry;
- hicn_hash_entry_t *hash_entry;
- policy_vft->hicn_cs_delete_get (pitcs, policy_state, &node,
- &pcs_entry, &hash_entry);
-
- /*
- * We don't have to decrease the lock (therefore we cannot
- * use hicn_pcs_cs_delete function)
- */
- policy_vft->hicn_cs_dequeue (pitcs, node, pcs_entry, policy_state);
-
- hicn_cs_delete_trimmed (pitcs, &pcs_entry, hash_entry, &node, vm);
-
- /* Update the global CS counter */
- pitcs->pcs_cs_count--;
- }
- }
- return ret;
+ // Reset the vlib_buffer index
+ hicn_pcs_entry_cs_set_buffer (p, ~0);
}
+/************************************************************************
+ **************************** PIT Entry APIs ****************************
+ ************************************************************************/
+
/*
- * Insert CS entry into the hashtable The main purpose of this wrapper is
- * helping maintain the per-PIT stats.
+ * Init pit/cs data block
*/
-always_inline int
-hicn_pcs_cs_insert_update (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t *entry, hicn_hash_node_t *node,
- hicn_hash_entry_t **hash_entry, u64 hashval,
- u32 *node_id, index_t *dpo_ctx_id, u8 *vft_id,
- u8 *is_cs, u8 *hash_entry_id, u32 *bucket_id,
- u8 *bucket_is_overflow, hicn_face_id_t inface)
+always_inline hicn_pcs_entry_t *
+hicn_pcs_entry_pit_get (hicn_pit_cs_t *pitcs, f64 tnow,
+ hicn_lifetime_t lifetime)
{
- int ret;
-
- ASSERT (entry == hicn_hashtb_node_data (node));
+ hicn_pcs_entry_t *ret = _hicn_pcs_entry_get (pitcs);
+ hicn_pcs_entry_init_data (ret, tnow);
+ clib_memset_u64 (ret->u.pit.bitmap, 0, HICN_PIT_BITMAP_SIZE_U64);
+ ret->u.pit.n_faces = 0;
+ ret->expire_time = hicn_pcs_get_exp_time (tnow, lifetime);
- entry->u.cs.cs_rxface = inface;
- ret = hicn_pcs_cs_insert (vm, pitcs, entry, node, hash_entry, hashval,
- node_id, dpo_ctx_id, vft_id, is_cs, hash_entry_id,
- bucket_id, bucket_is_overflow);
-
- /* A content already exists in CS with the same name */
- if (ret == HICN_ERROR_HASHTB_EXIST && *is_cs)
- {
- /* Update the entry */
- hicn_hash_node_t *existing_node =
- hicn_hashtb_node_from_idx (pitcs->pcs_table, *node_id);
- hicn_pcs_entry_t *pitp = hicn_pit_get_data (existing_node);
-
- /* Free associated packet buffer and update counter */
- pitcs->pcs_cs_dealloc++;
- vlib_buffer_free_one (vm, pitp->u.cs.cs_pkt_buf);
-
- pitp->shared.create_time = entry->shared.create_time;
- pitp->shared.expire_time = entry->shared.expire_time;
- pitp->u.cs.cs_pkt_buf = entry->u.cs.cs_pkt_buf;
+ return ret;
+}
- hicn_pcs_cs_update (vm, pitcs, pitp, entry, existing_node);
- }
+/*
+ * Free pit/cs data block
+ */
+always_inline void
+hicn_pcs_entry_pit_free_data (hicn_pcs_entry_t *p)
+{
+ // Nothing to do for the moment
+}
- return (ret);
+always_inline u32
+hicn_pcs_entry_pit_get_n_faces (hicn_pcs_entry_t *p)
+{
+ return p->u.pit.n_faces;
}
/*
- * Insert PIT entry into the hashtable The main purpose of this wrapper is
- * helping maintain the per-PIT stats.
+ * Get face id at index index
*/
-always_inline int
-hicn_pcs_pit_insert (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *entry,
- hicn_hash_node_t *node, hicn_hash_entry_t **hash_entry,
- u64 hashval, u32 *node_id, index_t *dpo_ctx_id,
- u8 *vft_id, u8 *is_cs, u8 *hash_entry_id, u32 *bucket_id,
- u8 *bucket_is_overflow)
+always_inline hicn_face_id_t
+hicn_pcs_entry_pit_get_dpo_face (const hicn_pcs_entry_t *pit_entry, u32 index)
{
- ASSERT (entry == hicn_hashtb_node_data (node));
-
- int ret = hicn_hashtb_insert (pitcs->pcs_table, node, hash_entry, hashval,
- node_id, dpo_ctx_id, vft_id, is_cs,
- hash_entry_id, bucket_id, bucket_is_overflow);
+ // Make sure the entry is PIT
+ ASSERT (!hicn_pcs_entry_is_cs (pit_entry));
- if (PREDICT_TRUE (ret == HICN_ERROR_NONE))
- pitcs->pcs_pit_count++;
+ // Make sure the index is valid
+ ASSERT (index < pit_entry->u.pit.n_faces);
- return ret;
+ if (index < HICN_FACE_DB_INLINE_FACES)
+ return pit_entry->u.pit.inline_faces[index];
+ else
+ return pit_entry->u.pit.faces[index - HICN_FACE_DB_INLINE_FACES];
}
always_inline void
-hicn_pcs_pit_delete (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t **pcs_entryp,
- hicn_hash_node_t **node, vlib_main_t *vm,
- hicn_hash_entry_t *hash_entry,
- const hicn_dpo_vft_t *dpo_vft, dpo_id_t *hicn_dpo_id)
+hicn_pcs_entry_pit_add_face (hicn_pcs_entry_t *pit_entry,
+ hicn_face_id_t face_id)
{
- hash_entry->locks--;
- if (hash_entry->locks == 0)
+ ASSERT (face_id < HICN_PARAM_FACES_MAX);
+
+ if (pit_entry->u.pit.n_faces < HICN_FACE_DB_INLINE_FACES)
{
- pitcs->pcs_pit_count--;
- hicn_pcs_delete_internal (pitcs, pcs_entryp, hash_entry, node, vm,
- dpo_vft, hicn_dpo_id);
+ pit_entry->u.pit.inline_faces[pit_entry->u.pit.n_faces] = face_id;
}
else
{
- hash_entry->he_flags |= HICN_HASH_ENTRY_FLAG_DELETED;
+ vec_validate_aligned (pit_entry->u.pit.faces,
+ pit_entry->u.pit.n_faces -
+ HICN_FACE_DB_INLINE_FACES,
+ CLIB_CACHE_LINE_BYTES);
+ pit_entry->u.pit
+ .faces[pit_entry->u.pit.n_faces - HICN_FACE_DB_INLINE_FACES] = face_id;
}
-}
-/* Generic functions for PIT/CS */
+ pit_entry->u.pit.n_faces++;
+
+ clib_bitmap_set_no_check (pit_entry->u.pit.bitmap, face_id, 1);
+}
/*
- * Insert PIT/CS entry into the hashtable The main purpose of this wrapper is
- * helping maintain the per-PIT stats.
+ * Search face in db
+ */
+always_inline u8
+hicn_pcs_entry_pit_search (const hicn_pcs_entry_t *pit_entry,
+ hicn_face_id_t face_id)
+{
+ ASSERT (face_id < HICN_PARAM_FACES_MAX);
+ return clib_bitmap_get_no_check ((uword *) pit_entry->u.pit.bitmap, face_id);
+}
+
+/************************************************************************
+ **************************** Lookup API ********************************
+ ************************************************************************/
+
+/**
+ * @brief Perform one lookup in the PIT/CS table using the provided name.
+ *
+ * @param pitcs the PIT/CS table
+ * @param name the name to lookup
+ * @param pcs_entry [RETURN] if the entry exists, the entry is returned
+ * @return HICN_ERROR_NONE if the entry is found, HICN_ERROR_PCS_NOT_FOUND
+ * otherwise
*/
always_inline int
-hicn_pcs_insert (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t *entry, hicn_hash_node_t *node,
- hicn_hash_entry_t **hash_entry, u64 hashval, u32 *node_id,
- index_t *dpo_ctx_id, u8 *vft_id, u8 *is_cs, u8 *hash_entry_id,
- u32 *bucket_id, u8 *bucket_is_overflow)
+hicn_pcs_lookup_one (hicn_pit_cs_t *pitcs, const hicn_name_t *name,
+ hicn_pcs_entry_t **pcs_entry)
{
int ret;
- if ((*hash_entry)->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY)
+ // Construct the lookup key
+ clib_bihash_kv_24_8_t kv;
+ hicn_pcs_get_key_from_name (&kv, name);
+
+ // Do a search in the has table
+ ret = clib_bihash_search_inline_24_8 (&pitcs->pcs_table, &kv);
+
+ if (PREDICT_FALSE (ret != 0))
{
- ret = hicn_pcs_cs_insert (vm, pitcs, entry, node, hash_entry, hashval,
- node_id, dpo_ctx_id, vft_id, is_cs,
- hash_entry_id, bucket_id, bucket_is_overflow);
+ *pcs_entry = NULL;
+ return HICN_ERROR_PCS_NOT_FOUND;
}
- else
+
+ // Retrieve entry from pool
+ *pcs_entry = hicn_pcs_entry_get_entry_from_index (pitcs, (u32) (kv.value));
+
+ // If the search is successful, we MUST find the entry in the pool.
+ ALWAYS_ASSERT (pcs_entry);
+
+ // If entry found and it is a CS entry, let's update the LRU
+ if (hicn_pcs_entry_is_cs (*pcs_entry))
{
- ret = hicn_pcs_pit_insert (pitcs, entry, node, hash_entry, hashval,
- node_id, dpo_ctx_id, vft_id, is_cs,
- hash_entry_id, bucket_id, bucket_is_overflow);
+ hicn_pcs_cs_update_lru (pitcs, *pcs_entry);
}
- return (ret);
+ // If the entry is found, return it
+ return HICN_ERROR_NONE;
}
+/************************************************************************
+ **************************** PCS Delete API ****************************
+ ************************************************************************/
+
/*
- * Delete entry if there are no pending lock on the entry, otherwise mark it
- * as to delete.
+ * Delete a PIT/CS entry from the hashtable.
+ * The caller's pointers are zeroed! If cs_trim is true, entry has already
+ * been removed from lru list The main purpose of this wrapper is helping
+ * maintain the per-PIT stats.
*/
always_inline void
-hicn_pcs_delete (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t **pcs_entryp,
- hicn_hash_node_t **nodep, vlib_main_t *vm,
- hicn_hash_entry_t *hash_entry, const hicn_dpo_vft_t *dpo_vft,
- dpo_id_t *hicn_dpo_id)
+hicn_pcs_delete_internal (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *pcs_entry)
{
- /*
- * If the entry has already been marked as deleted, it has already
- * been dequeue
- */
- if (hash_entry->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY)
+ if (pcs_entry->flags & HICN_PCS_ENTRY_CS_FLAG)
{
- hicn_pcs_cs_delete (vm, pitcs, pcs_entryp, nodep, hash_entry, dpo_vft,
- hicn_dpo_id);
- }
- else
- {
- hicn_pcs_pit_delete (pitcs, pcs_entryp, nodep, vm, hash_entry, dpo_vft,
- hicn_dpo_id);
- }
-}
+ // Remove entry from LRU list
+ hicn_pcs_cs_dequeue_lru (pitcs, pcs_entry);
-/*
- * Remove a lock in the entry and delete it if there are no pending lock and
- * the entry is marked as to be deleted
- */
-always_inline void
-hicn_pcs_remove_lock (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t **pcs_entryp,
- hicn_hash_node_t **node, vlib_main_t *vm,
- hicn_hash_entry_t *hash_entry,
- const hicn_dpo_vft_t *dpo_vft, dpo_id_t *hicn_dpo_id)
-{
- hash_entry->locks--;
- if (hash_entry->locks == 0 &&
- (hash_entry->he_flags & HICN_HASH_ENTRY_FLAG_DELETED))
- {
- hicn_pcs_delete_internal (pitcs, pcs_entryp, hash_entry, node, vm,
- dpo_vft, hicn_dpo_id);
- }
-}
+ // Update counters
+ pitcs->pcs_cs_count--;
-/*
- * Delete entry which has already been bulk-removed from lru list
- */
-always_inline void
-hicn_cs_delete_trimmed (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t **pcs_entryp,
- hicn_hash_entry_t *hash_entry, hicn_hash_node_t **node,
- vlib_main_t *vm)
-{
+ // Free data
+ hicn_pcs_entry_cs_free_data (pcs_entry);
- if (hash_entry->locks == 0)
- {
- const hicn_dpo_vft_t *dpo_vft = hicn_dpo_get_vft (hash_entry->vft_id);
- dpo_id_t hicn_dpo_id = { .dpoi_type = dpo_vft->hicn_dpo_get_type (),
- .dpoi_proto = 0,
- .dpoi_next_node = 0,
- .dpoi_index = hash_entry->dpo_ctx_id };
-
- hicn_pcs_delete_internal (pitcs, pcs_entryp, hash_entry, node, vm,
- dpo_vft, &hicn_dpo_id);
+ // Sanity check
+ ASSERT ((pcs_entry->u.cs.cs_lru_prev == HICN_CS_POLICY_END_OF_CHAIN) &&
+ (pcs_entry->u.cs.cs_lru_prev == pcs_entry->u.cs.cs_lru_next));
}
else
{
- hash_entry->he_flags |= HICN_HASH_ENTRY_FLAG_DELETED;
+ // Update counters
+ pitcs->pcs_pit_count--;
+ // Flush faces
+ // hicn_faces_flush (&(pcs_entry->u.pit.faces));
}
-}
-/*
- * wrappable counter math (assumed uint16_t): return sum of addends
- */
-always_inline u16
-hicn_infra_seq16_sum (u16 addend1, u16 addend2)
-{
- return (addend1 + addend2);
+ // Delete entry from hash table
+ clib_bihash_kv_24_8_t kv;
+ hicn_pcs_get_key_from_name (&kv, &pcs_entry->name);
+ clib_bihash_add_del_24_8 (&pitcs->pcs_table, &kv, 0 /* is_add */);
+
+ // Free pool entry
+ hicn_pcs_entry_put (pitcs, pcs_entry);
}
-/*
- * for comparing wrapping numbers, return lt,eq,gt 0 for a lt,eq,gt b
- */
+/************************************************************************
+ **************************** PCS Insert API ****************************
+ ************************************************************************/
+
always_inline int
-hicn_infra_seq16_cmp (u16 a, u16 b)
+hicn_pcs_insert (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *entry,
+ const hicn_name_t *name)
{
- return ((int16_t) (a - b));
+ clib_bihash_kv_24_8_t kv;
+ u32 index = hicn_pcs_entry_get_index (pitcs, entry);
+
+ // Construct KV pair and try to add it to hash table
+ hicn_pcs_get_key_from_name (&kv, name);
+ kv.value = index;
+
+ // Get name hash
+ entry->name_hash = clib_bihash_hash_24_8 (&kv);
+ entry->name = *name;
+
+ return clib_bihash_add_del_24_8 (&pitcs->pcs_table, &kv,
+ 2 /* add_but_not_replace */);
}
-/*
- * below are wrappers for lt, le, gt, ge seq16 comparators
+/**
+ * @brief Insert a CS entry in the PIT/CS table. This function DOES NOT check
+ * if the KV is already present in the table. It expects the caller to check
+ * this before trying to insert the new entry.
+ *
+ * @param pitcs the PIT/CS table
+ * @param entry the entry to insert
+ * @param name the name to use to compute the key
+ * @return always_inline
*/
always_inline int
-hicn_infra_seq16_lt (u16 a, u16 b)
+hicn_pcs_cs_insert (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *entry,
+ const hicn_name_t *name)
{
- return (hicn_infra_seq16_cmp (a, b) < 0);
-}
+ // Make sure this is a CS entry
+ ASSERT (hicn_pcs_entry_is_cs (entry));
-always_inline int
-hicn_infra_seq16_le (u16 a, u16 b)
-{
- return (hicn_infra_seq16_cmp (a, b) <= 0);
-}
+ int ret = hicn_pcs_insert (pitcs, entry, name);
-always_inline int
-hicn_infra_seq16_gt (u16 a, u16 b)
-{
- return (hicn_infra_seq16_cmp (a, b) > 0);
+ // Make sure insertion happened
+ ASSERT (ret == 0);
+
+ // New entry, update LRU
+ hicn_pcs_cs_insert_lru (pitcs, entry);
+
+ return HICN_ERROR_NONE;
}
+/**
+ * @brief Insert a PIT entry in the PIT/CS table. This function DOES NOT check
+ * if the KV is already present in the table. It is expected the caller checks
+ * this before trying to insert the new entry.
+ *
+ * @param pitcs
+ * @param name
+ * @param pcs_entry_index
+ * @param dpo_ctx_id
+ * @param vft_id
+ * @param is_cs
+ * @return always_inline
+ */
always_inline int
-hicn_infra_seq16_ge (u16 a, u16 b)
+hicn_pcs_pit_insert (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *entry,
+ const hicn_name_t *name)
{
- return (hicn_infra_seq16_cmp (a, b) >= 0);
-}
+ // Insert entry into hash table
+ int ret = hicn_pcs_insert (pitcs, entry, name);
-extern u16 hicn_infra_fast_timer; /* Counts at 1 second intervals */
-extern u16 hicn_infra_slow_timer; /* Counts at 1 minute intervals */
+ // Make sure insertion happened
+ ASSERT (ret == 0);
-/*
- * Utilities to convert lifetime into expiry time based on compressed clock,
- * suitable for the opportunistic hashtable entry timeout processing.
- */
+ // Increment the number of PIT entries if insertion happened
+ pitcs->pcs_pit_count++;
-// convert time in msec to time in clicks
-always_inline u16
-hicn_infra_ms2clicks (u64 time_ms, u64 ms_per_click)
-{
- f64 time_clicks =
- ((f64) (time_ms + ms_per_click - 1)) / ((f64) ms_per_click);
- return ((u16) time_clicks);
+ return HICN_ERROR_NONE;
}
-always_inline u16
-hicn_infra_get_fast_exp_time (u64 lifetime_ms)
-{
- u16 lifetime_clicks =
- hicn_infra_ms2clicks (lifetime_ms, HICN_INFRA_FAST_TIMER_MSECS);
- return (hicn_infra_seq16_sum (hicn_infra_fast_timer, lifetime_clicks));
-}
+/************************************************************************
+ ************************** PCS Conversion API **************************
+ ************************************************************************/
-always_inline u16
-hicn_infra_get_slow_exp_time (u64 lifetime_ms)
+/**
+ * @brief Convert a PIT entry to a CS entry.
+ *
+ * @param vm
+ * @param pitcs
+ * @param pcs_entry
+ * @param hash_entry
+ * @param node
+ * @param dpo_vft
+ * @param hicn_dpo_id
+ * @return always_inline
+ */
+always_inline void
+hicn_pit_to_cs (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *pit_entry,
+ u32 buffer_index)
{
- u16 lifetime_clicks =
- hicn_infra_ms2clicks (lifetime_ms, HICN_INFRA_SLOW_TIMER_MSECS);
- return (hicn_infra_seq16_sum (hicn_infra_slow_timer, lifetime_clicks));
+ // Different from the insert node. In here we don't need to add a new
+ // hash entry.
+ pitcs->pcs_pit_count--;
+
+ // Flush faces
+ // hicn_faces_flush (&(pit_entry->u.pit.faces));
+
+ // Set the flags
+ pit_entry->flags = HICN_PCS_ENTRY_CS_FLAG;
+
+ // Set the buffer index
+ pit_entry->u.cs.cs_pkt_buf = buffer_index;
+
+ hicn_pcs_cs_insert_lru (pitcs, pit_entry);
}
-#endif /* // __HICN_PCS_H__ */
+#endif /* __HICN_PCS_H__ */
/*
* fd.io coding-style-patch-verification: ON