aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-plugin/src
diff options
context:
space:
mode:
authorLuca Muscariello <lumuscar@cisco.com>2022-06-30 13:58:25 +0200
committerMauro Sardara <msardara@cisco.com>2022-07-01 12:11:33 +0200
commit012843b1c0bc0838e69085ed83a79ec8b6f97360 (patch)
tree4fa320673884488e4a1bf879ec144e99f134a3fb /hicn-plugin/src
parent6b94663b2455e212009a544ae23bb6a8c55407f8 (diff)
Revision and refactor of the VPP plugin with fixes for the
packet generator. Hash table for the packet cache has been changed with the bihash. Co-authored-by: Mauro Sardara <msardara@cisco.com> Signed-off-by: Luca Muscariello <muscariello@ieee.org> Change-Id: I0e0191a9f109d37081d32cc55d577ea43533f8c0 Signed-off-by: Mauro Sardara <msardara@cisco.com>
Diffstat (limited to 'hicn-plugin/src')
-rw-r--r--hicn-plugin/src/CMakeLists.txt9
-rw-r--r--hicn-plugin/src/cache_policies/cs_lru.c204
-rw-r--r--hicn-plugin/src/cache_policies/cs_lru.h40
-rw-r--r--hicn-plugin/src/cache_policies/cs_policy.h184
-rw-r--r--hicn-plugin/src/cli.c24
-rw-r--r--hicn-plugin/src/data_fwd.h9
-rw-r--r--hicn-plugin/src/data_fwd_node.c542
-rw-r--r--hicn-plugin/src/data_input_node.c82
-rw-r--r--hicn-plugin/src/data_pcslookup_node.c81
-rw-r--r--hicn-plugin/src/face_db.h152
-rw-r--r--hicn-plugin/src/faces/app/face_app_cli.c2
-rw-r--r--hicn-plugin/src/faces/app/face_prod_node.c1
-rw-r--r--hicn-plugin/src/faces/face_node.c2
-rw-r--r--hicn-plugin/src/faces/iface_node.c1
-rw-r--r--hicn-plugin/src/hashtb.c1006
-rw-r--r--hicn-plugin/src/hashtb.h536
-rw-r--r--hicn-plugin/src/hicn.api6
-rw-r--r--hicn-plugin/src/hicn.c28
-rw-r--r--hicn-plugin/src/hicn.h38
-rw-r--r--hicn-plugin/src/infra.h2
-rw-r--r--hicn-plugin/src/interest_hitcs_node.c107
-rw-r--r--hicn-plugin/src/interest_hitpit_node.c256
-rw-r--r--hicn-plugin/src/interest_pcslookup_node.c77
-rw-r--r--hicn-plugin/src/parser.h191
-rw-r--r--hicn-plugin/src/pcs.c44
-rw-r--r--hicn-plugin/src/pcs.h1115
-rw-r--r--hicn-plugin/src/pg_node.c51
-rw-r--r--hicn-plugin/src/state.h54
-rw-r--r--hicn-plugin/src/strategies/strategy_mw.c18
-rw-r--r--hicn-plugin/src/strategies/strategy_rp.c12
-rw-r--r--hicn-plugin/src/strategies/strategy_rr.c18
-rw-r--r--hicn-plugin/src/strategy.h7
-rw-r--r--hicn-plugin/src/strategy_node.c264
-rw-r--r--hicn-plugin/src/test/CMakeLists.txt67
-rw-r--r--hicn-plugin/src/test/main.c31
-rw-r--r--hicn-plugin/src/test/test_pcs.c622
-rw-r--r--hicn-plugin/src/test/vpp.c555
-rw-r--r--hicn-plugin/src/test/vpp.h21
38 files changed, 2907 insertions, 3552 deletions
diff --git a/hicn-plugin/src/CMakeLists.txt b/hicn-plugin/src/CMakeLists.txt
index e071b3b9d..d232b4ab1 100644
--- a/hicn-plugin/src/CMakeLists.txt
+++ b/hicn-plugin/src/CMakeLists.txt
@@ -34,7 +34,6 @@ set(HICN_PLUGIN_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/hicn.c
${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.c
${CMAKE_CURRENT_SOURCE_DIR}/cli.c
- ${CMAKE_CURRENT_SOURCE_DIR}/hashtb.c
${CMAKE_CURRENT_SOURCE_DIR}/infra.c
${CMAKE_CURRENT_SOURCE_DIR}/mgmt.c
${CMAKE_CURRENT_SOURCE_DIR}/pcs.c
@@ -78,7 +77,6 @@ set(HICN_PLUGIN_SOURCE_FILES
set(HICN_PLUGIN_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/hicn_all_api_h.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn_logging.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hashtb.h
${CMAKE_CURRENT_SOURCE_DIR}/mgmt.h
${CMAKE_CURRENT_SOURCE_DIR}/params.h
${CMAKE_CURRENT_SOURCE_DIR}/pcs.h
@@ -245,3 +243,10 @@ build_module(${HICN_API_TEST_PLUGIN}
COMPILE_OPTIONS ${COMPILER_OPTIONS}
INSTALL_RPATH "${VPP_INSTALL_PLUGIN}:${HICN_INSTALL_PREFIX}:${VPP_HOME}/lib"
)
+
+##############################################################
+# Unit tests
+##############################################################
+if (${BUILD_TESTS})
+ add_subdirectory(test)
+endif() \ No newline at end of file
diff --git a/hicn-plugin/src/cache_policies/cs_lru.c b/hicn-plugin/src/cache_policies/cs_lru.c
index e65f487e1..07c4916fb 100644
--- a/hicn-plugin/src/cache_policies/cs_lru.c
+++ b/hicn-plugin/src/cache_policies/cs_lru.c
@@ -13,7 +13,6 @@
* limitations under the License.
*/
-#include "../hashtb.h"
#include "../strategy_dpo_manager.h"
#include "../error.h"
#include "cs_lru.h"
@@ -32,129 +31,112 @@ hicn_cs_policy_vft_t hicn_cs_lru = {
* Insert a new CS element at the head of the CS LRU
*/
void
-hicn_cs_lru_insert (hicn_pit_cs_t *p, hicn_hash_node_t *node,
- hicn_pcs_entry_t *pcs, hicn_cs_policy_t *policy_state)
+hicn_cs_lru_insert (hicn_cs_policy_t *lru_policy, hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t *pcs_entry)
{
- hicn_hash_node_t *lrunode;
hicn_pcs_entry_t *lrupcs;
u32 idx;
- idx = hicn_hashtb_node_idx_from_node (p->pcs_table, node);
+ idx = hicn_pcs_entry_get_index (pcs, pcs_entry);
- if (policy_state->head != 0)
+ if (lru_policy->head != HICN_CS_POLICY_END_OF_CHAIN)
{
- lrunode = hicn_hashtb_node_from_idx (p->pcs_table, policy_state->head);
- lrupcs = hicn_pit_get_data (lrunode);
+ lrupcs = hicn_pcs_entry_get_entry_from_index (pcs, lru_policy->head);
- ASSERT (lrupcs->u.cs.cs_lru_prev == 0);
+ ASSERT (lrupcs->u.cs.cs_lru_prev == HICN_CS_POLICY_END_OF_CHAIN);
lrupcs->u.cs.cs_lru_prev = idx;
- pcs->u.cs.cs_lru_prev = 0;
- pcs->u.cs.cs_lru_next = policy_state->head;
+ pcs_entry->u.cs.cs_lru_prev = HICN_CS_POLICY_END_OF_CHAIN;
+ pcs_entry->u.cs.cs_lru_next = lru_policy->head;
- policy_state->head = idx;
+ lru_policy->head = idx;
}
else
{
- ASSERT (policy_state->tail == 0); /* We think the list is
- * empty */
+ // The list should be empty
+ ASSERT (lru_policy->tail == HICN_CS_POLICY_END_OF_CHAIN);
- policy_state->head = policy_state->tail = idx;
+ lru_policy->head = lru_policy->tail = idx;
- pcs->u.cs.cs_lru_next = pcs->u.cs.cs_lru_prev = 0;
+ pcs_entry->u.cs.cs_lru_next = pcs_entry->u.cs.cs_lru_prev =
+ HICN_CS_POLICY_END_OF_CHAIN;
}
- policy_state->count++;
+ lru_policy->count++;
}
void
-hicn_cs_lru_delete_get (hicn_pit_cs_t *p, hicn_cs_policy_t *policy_state,
- hicn_hash_node_t **nodep, hicn_pcs_entry_t **pcs_entry,
- hicn_hash_entry_t **hash_entry)
+hicn_cs_lru_delete_get (hicn_cs_policy_t *lru_policy, const hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t **pcs_entry)
{
- *nodep = hicn_hashtb_node_from_idx (p->pcs_table, policy_state->tail);
- *pcs_entry = hicn_pit_get_data (*nodep);
-
- *hash_entry = hicn_hashtb_get_entry (
- p->pcs_table, (*nodep)->entry_idx, (*nodep)->bucket_id,
- (*nodep)->hn_flags & HICN_HASH_NODE_OVERFLOW_BUCKET);
+ *pcs_entry = hicn_pcs_entry_get_entry_from_index (pcs, lru_policy->tail);
}
/*
* Dequeue an LRU element, for example when it has expired.
*/
void
-hicn_cs_lru_dequeue (hicn_pit_cs_t *pit, hicn_hash_node_t *pnode,
- hicn_pcs_entry_t *pcs, hicn_cs_policy_t *lru)
+hicn_cs_lru_dequeue (hicn_cs_policy_t *lru_policy, hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t *pcs_entry)
{
- hicn_hash_node_t *lrunode;
hicn_pcs_entry_t *lrupcs;
- if (pcs->u.cs.cs_lru_prev != 0)
+ if (pcs_entry->u.cs.cs_lru_prev != HICN_CS_POLICY_END_OF_CHAIN)
{
/* Not already on the head of the LRU */
- lrunode =
- hicn_hashtb_node_from_idx (pit->pcs_table, pcs->u.cs.cs_lru_prev);
- lrupcs = hicn_pit_get_data (lrunode);
+ lrupcs =
+ hicn_pcs_entry_get_entry_from_index (pcs, pcs_entry->u.cs.cs_lru_prev);
- lrupcs->u.cs.cs_lru_next = pcs->u.cs.cs_lru_next;
+ lrupcs->u.cs.cs_lru_next = pcs_entry->u.cs.cs_lru_next;
}
else
{
- ASSERT (lru->head ==
- hicn_hashtb_node_idx_from_node (pit->pcs_table, pnode));
- lru->head = pcs->u.cs.cs_lru_next;
+ ASSERT (lru_policy->head == hicn_pcs_entry_get_index (pcs, pcs_entry));
+ lru_policy->head = pcs_entry->u.cs.cs_lru_next;
}
- if (pcs->u.cs.cs_lru_next != 0)
+ if (pcs_entry->u.cs.cs_lru_next != HICN_CS_POLICY_END_OF_CHAIN)
{
/* Not already the end of the LRU */
- lrunode =
- hicn_hashtb_node_from_idx (pit->pcs_table, pcs->u.cs.cs_lru_next);
- lrupcs = hicn_pit_get_data (lrunode);
+ lrupcs =
+ hicn_pcs_entry_get_entry_from_index (pcs, pcs_entry->u.cs.cs_lru_next);
- lrupcs->u.cs.cs_lru_prev = pcs->u.cs.cs_lru_prev;
+ lrupcs->u.cs.cs_lru_prev = pcs_entry->u.cs.cs_lru_prev;
}
else
{
/* This was the last LRU element */
- ASSERT (lru->tail ==
- hicn_hashtb_node_idx_from_node (pit->pcs_table, pnode));
- lru->tail = pcs->u.cs.cs_lru_prev;
+ ASSERT (lru_policy->tail == hicn_pcs_entry_get_index (pcs, pcs_entry));
+ lru_policy->tail = pcs_entry->u.cs.cs_lru_prev;
}
- pcs->u.cs.cs_lru_next = pcs->u.cs.cs_lru_prev = 0;
- lru->count--;
+ pcs_entry->u.cs.cs_lru_next = pcs_entry->u.cs.cs_lru_prev =
+ HICN_CS_POLICY_END_OF_CHAIN;
+ lru_policy->count--;
}
/*
- * Move a CS LRU element to the head, probably after it's been used.
+ * Move a CS LRU element to the head. The element must be part of the LRU list.
*/
void
-hicn_cs_lru_update_head (hicn_pit_cs_t *pit, hicn_hash_node_t *pnode,
- hicn_pcs_entry_t *pcs, hicn_cs_policy_t *lru)
+hicn_cs_lru_update_head (hicn_cs_policy_t *lru_policy, hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t *pcs_entry)
{
- if (pcs->u.cs.cs_lru_prev != 0)
+ if (pcs_entry->u.cs.cs_lru_prev != HICN_CS_POLICY_END_OF_CHAIN)
{
/*
* Not already on the head of the LRU, detach it from its
* current position
*/
- hicn_cs_lru_dequeue (pit, pnode, pcs, lru);
+ hicn_cs_lru_dequeue (lru_policy, pcs, pcs_entry);
/* Now detached from the list; attach at head */
- hicn_cs_lru_insert (pit, pnode, pcs, lru);
+ hicn_cs_lru_insert (lru_policy, pcs, pcs_entry);
}
else
{
- /* The element is already dequeue */
- if (pcs->u.cs.cs_lru_next == 0)
- {
- /* Now detached from the list; attach at head */
- hicn_cs_lru_insert (pit, pnode, pcs, lru);
- }
- ASSERT (lru->head ==
- hicn_hashtb_node_idx_from_node (pit->pcs_table, pnode));
+ // The element must be already at the head of the LRU
+ ASSERT (lru_policy->head == hicn_pcs_entry_get_index (pcs, pcs_entry));
}
}
@@ -164,96 +146,86 @@ hicn_cs_lru_update_head (hicn_pit_cs_t *pit, hicn_hash_node_t *pnode,
* CS's limit. Return the number of removed nodes.
*/
int
-hicn_cs_lru_trim (hicn_pit_cs_t *pit, u32 *node_list, int sz,
- hicn_cs_policy_t *lru)
+hicn_cs_lru_trim (hicn_cs_policy_t *lru_policy, hicn_pit_cs_t *pcs,
+ u32 *node_list, size_t sz)
{
- hicn_hash_node_t *lrunode;
hicn_pcs_entry_t *lrupcs;
u32 idx;
int i;
- idx = lru->tail;
+ idx = lru_policy->tail;
- for (i = 0; i < sz; i++)
+ for (i = 0; i < sz && idx > 0; i++)
{
-
- if (idx == 0)
- {
- break;
- }
- lrunode = hicn_hashtb_node_from_idx (pit->pcs_table, idx);
- lrupcs = hicn_pit_get_data (lrunode);
+ lrupcs = hicn_pcs_entry_get_entry_from_index (pcs, idx);
node_list[i] = idx;
idx = lrupcs->u.cs.cs_lru_prev;
- lrupcs->u.cs.cs_lru_prev = 0;
- lrupcs->u.cs.cs_lru_next = 0;
+ lrupcs->u.cs.cs_lru_prev = HICN_CS_POLICY_END_OF_CHAIN;
+ lrupcs->u.cs.cs_lru_next = HICN_CS_POLICY_END_OF_CHAIN;
}
- lru->count -= i;
+ lru_policy->count -= i;
+ lru_policy->tail = idx;
- lru->tail = idx;
- if (idx != 0)
+ if (idx != HICN_CS_POLICY_END_OF_CHAIN)
{
- lrunode = hicn_hashtb_node_from_idx (pit->pcs_table, idx);
- lrupcs = hicn_pit_get_data (lrunode);
-
- lrupcs->u.cs.cs_lru_next = 0;
+ lrupcs = hicn_pcs_entry_get_entry_from_index (pcs, idx);
+ lrupcs->u.cs.cs_lru_next = HICN_CS_POLICY_END_OF_CHAIN;
}
else
{
/* If the tail is empty, the whole lru is empty */
- lru->head = 0;
+ lru_policy->head = HICN_CS_POLICY_END_OF_CHAIN;
}
- return (i);
+ return i;
}
int
-hicn_cs_lru_flush (vlib_main_t *vm, struct hicn_pit_cs_s *pitcs,
- hicn_cs_policy_t *state)
+hicn_cs_lru_flush (hicn_cs_policy_t *lru_policy, hicn_pit_cs_t *pcs)
{
- if (state->head == 0 && state->tail == 0)
+ if (lru_policy->head == HICN_CS_POLICY_END_OF_CHAIN &&
+ lru_policy->tail == HICN_CS_POLICY_END_OF_CHAIN)
return 0;
- hicn_hash_node_t *lrunode;
- hicn_pcs_entry_t *lrupcs;
+ hicn_pcs_entry_t *pcs_entry;
u32 idx;
int i = 0;
- idx = state->tail;
+ idx = lru_policy->tail;
- while (idx != 0)
+ while (idx != HICN_CS_POLICY_END_OF_CHAIN)
{
- lrunode = hicn_hashtb_node_from_idx (pitcs->pcs_table, idx);
- lrupcs = hicn_pit_get_data (lrunode);
-
- u64 hashval = 0;
- hicn_hashtb_fullhash ((u8 *) &(lrunode->hn_key.ks.key),
- lrunode->hn_keysize, &hashval);
- hicn_hash_bucket_t *bucket = NULL;
- if ((hashval & (pitcs->pcs_table->ht_bucket_count - 1)) ==
- lrunode->bucket_id)
- {
- // The bucket is in the non overflown
- bucket = pitcs->pcs_table->ht_buckets + lrunode->bucket_id;
- }
- else
- {
- bucket = pool_elt_at_index (pitcs->pcs_table->ht_overflow_buckets,
- lrunode->bucket_id);
- }
- hicn_hash_entry_t *hash_entry =
- &(bucket->hb_entries[lrunode->entry_idx]);
- hash_entry->locks++;
- hicn_pcs_cs_delete (vm, pitcs, &lrupcs, &lrunode, hash_entry, NULL,
- NULL);
- idx = state->tail;
+ // Get tail entry
+ pcs_entry = hicn_pcs_entry_get_entry_from_index (pcs, idx);
+
+ // Delete entry from the PCS. This will also update the LRU.
+ hicn_pcs_entry_remove_lock (pcs, pcs_entry);
+
+ // Set index to the new tail (updated in the previous call)
+ idx = lru_policy->tail;
+
+ // Advance counter
i++;
}
- return (i);
+ return i;
+}
+
+hicn_cs_policy_t
+hicn_cs_lru_create (u32 max_elts)
+{
+ hicn_cs_policy_t policy = {
+ .vft = hicn_cs_lru,
+ .head = HICN_CS_POLICY_END_OF_CHAIN,
+ .tail = HICN_CS_POLICY_END_OF_CHAIN,
+ .count = 0,
+ .max = max_elts,
+ };
+
+ return policy;
}
/*
diff --git a/hicn-plugin/src/cache_policies/cs_lru.h b/hicn-plugin/src/cache_policies/cs_lru.h
index 35b82ff2c..1e67cb547 100644
--- a/hicn-plugin/src/cache_policies/cs_lru.h
+++ b/hicn-plugin/src/cache_policies/cs_lru.h
@@ -17,7 +17,6 @@
#define __LRU_H__
#include "../pcs.h"
-#include "../hashtb.h"
#include "cs_policy.h"
/**
@@ -28,39 +27,46 @@
extern hicn_cs_policy_vft_t hicn_cs_lru;
-/*
- * Insert a new CS element at the head of the CS LRU
+/**
+ * @brief Insert a new CS element at the head of the CS LRU
+ *
+ * @param policy the cs insertion/eviction policy - LRU
+ * @param pcs the PCS table
+ * @param pcs_entry the PCS entry to insert
+ * @return 0 on success, -1 on overflow
*/
-void hicn_cs_lru_insert (hicn_pit_cs_t *pcs, hicn_hash_node_t *pnode,
- hicn_pcs_entry_t *entry, hicn_cs_policy_t *lru);
+void hicn_cs_lru_insert (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t *pcs_entry);
/*
* Dequeue an LRU element, for example when it has expired.
*/
-void hicn_cs_lru_dequeue (hicn_pit_cs_t *pcs, hicn_hash_node_t *pnode,
- hicn_pcs_entry_t *entry, hicn_cs_policy_t *lru);
+void hicn_cs_lru_dequeue (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t *pcs_entry);
/*
* Move a CS LRU element to the head, probably after it's been used.
*/
-void hicn_cs_lru_update_head (hicn_pit_cs_t *pcs, hicn_hash_node_t *pnode,
- hicn_pcs_entry_t *entry, hicn_cs_policy_t *lru);
+void hicn_cs_lru_update_head (hicn_cs_policy_t *lru, hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t *entry);
-void hicn_cs_lru_delete_get (hicn_pit_cs_t *p, hicn_cs_policy_t *policy,
- hicn_hash_node_t **node, hicn_pcs_entry_t **pcs,
- hicn_hash_entry_t **hash_entry);
+void hicn_cs_lru_delete_get (hicn_cs_policy_t *policy,
+ const hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t **pcs_entry);
/*
* Remove a batch of nodes from the CS LRU, copying their node indexes into
* the caller's array. We expect this is done when the LRU size exceeds the
* CS's limit. Return the number of removed nodes.
*/
-int hicn_cs_lru_trim (hicn_pit_cs_t *pcs, u32 *node_list, int sz,
- hicn_cs_policy_t *lru);
+int hicn_cs_lru_trim (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs,
+ u32 *node_list, size_t sz);
+
+int hicn_cs_lru_flush (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs);
+
+hicn_cs_policy_t hicn_cs_lru_create (u32 max_elts);
-int hicn_cs_lru_flush (vlib_main_t *vm, struct hicn_pit_cs_s *pitcs,
- hicn_cs_policy_t *state);
-#endif /* // __LRU_H__ */
+#endif /* __LRU_H__ */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/cache_policies/cs_policy.h b/hicn-plugin/src/cache_policies/cs_policy.h
index 73f3de107..5280a59c2 100644
--- a/hicn-plugin/src/cache_policies/cs_policy.h
+++ b/hicn-plugin/src/cache_policies/cs_policy.h
@@ -16,7 +16,9 @@
#ifndef __HICN_CS_POLICY_H__
#define __HICN_CS_POLICY_H__
-#include "../hashtb.h"
+#include <vppinfra/types.h>
+#include <vppinfra/clib.h>
+#include <stddef.h>
/**
* @file cs_policy.h
@@ -24,25 +26,10 @@
* This file provides the needed structures to implement a CS policy
*/
-/*
- * Structure
- */
-typedef struct hicn_cs_policy_s
-{
- u32 max;
- u32 count;
-
- /* Indexes to hashtable nodes forming CS LRU */
- u32 head;
- u32 tail;
-
-} hicn_cs_policy_t;
-
/* Forward declaration */
-struct hicn_pit_cs_s;
-struct hicn_hash_node_s;
-struct hicn_pcs_entry_s;
-struct hicn_cs_policy_s;
+typedef struct hicn_pit_cs_s hicn_pit_cs_t;
+typedef struct hicn_pcs_entry_s hicn_pcs_entry_t;
+typedef struct hicn_cs_policy_s hicn_cs_policy_t;
/**
* @brief Definition of the virtual functin table for a cache policy.
@@ -51,40 +38,143 @@ struct hicn_cs_policy_s;
* - insert: add a new element
* - update: update the position of an existing element
* - dequeue: remove an element from the list
- * - delete_get: return the next element that should be removed trim
+ * - delete_get: return the next element that should be removed
+ * - trim: trim last sz elements from the list
* - flush: clean the cs
*/
typedef struct hicn_cs_policy_vft_s
{
- void (*hicn_cs_insert) (struct hicn_pit_cs_s *p,
- struct hicn_hash_node_s *node,
- struct hicn_pcs_entry_s *pcs,
- hicn_cs_policy_t *policy);
-
- void (*hicn_cs_update) (struct hicn_pit_cs_s *p,
- struct hicn_hash_node_s *node,
- struct hicn_pcs_entry_s *pcs,
- hicn_cs_policy_t *policy);
-
- void (*hicn_cs_dequeue) (struct hicn_pit_cs_s *p,
- struct hicn_hash_node_s *node,
- struct hicn_pcs_entry_s *pcs,
- hicn_cs_policy_t *policy);
-
- void (*hicn_cs_delete_get) (struct hicn_pit_cs_s *p,
- hicn_cs_policy_t *policy,
- struct hicn_hash_node_s **node,
- struct hicn_pcs_entry_s **pcs,
- struct hicn_hash_entry_s **hash_entry);
-
- int (*hicn_cs_trim) (struct hicn_pit_cs_s *p, u32 *node_list, int sz,
- hicn_cs_policy_t *policy);
-
- int (*hicn_cs_flush) (vlib_main_t *vm, struct hicn_pit_cs_s *p,
- hicn_cs_policy_t *policy_state);
+ void (*hicn_cs_insert) (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t *pcs_entry);
+
+ void (*hicn_cs_update) (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t *pcs_entry);
+
+ void (*hicn_cs_dequeue) (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t *pcs_entry);
+
+ void (*hicn_cs_delete_get) (hicn_cs_policy_t *policy,
+ const hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t **pcs_entry);
+
+ int (*hicn_cs_trim) (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs,
+ u32 *node_list, size_t sz);
+
+ int (*hicn_cs_flush) (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs);
} hicn_cs_policy_vft_t;
-#endif /* // __HICN_POLICY_H__ */
+/*
+ * CS policy
+ */
+typedef struct hicn_cs_policy_s
+{
+#define HICN_CS_POLICY_END_OF_CHAIN (u32) (~0)
+
+ /*
+ * VFT implementing the CS eviction/insertion policy. This must be the first
+ * element of the structure.
+ */
+ hicn_cs_policy_vft_t vft;
+
+ /*
+ * Max number of element in CS
+ */
+ u32 max;
+
+ /*
+ * Number of element in CS
+ */
+ u32 count;
+
+ /*
+ * Head element of the CS (i.e. the most recent element used for LRU)
+ */
+ u32 head;
+
+ /*
+ * Tail element of the LRU (i.e. the next element to evict for LRU)
+ */
+ u32 tail;
+} hicn_cs_policy_t;
+
+/*
+ * Get the max number of element in the CS
+ */
+always_inline u32
+hicn_cs_policy_get_max (const hicn_cs_policy_t *policy)
+{
+ return policy->max;
+}
+
+/*
+ * Get the number of element in the CS
+ */
+always_inline u32
+hicn_cs_policy_get_count (const hicn_cs_policy_t *policy)
+{
+ return policy->count;
+}
+
+/*
+ * Get the head element of the CS
+ */
+always_inline u32
+hicn_cs_policy_get_head (const hicn_cs_policy_t *policy)
+{
+ return policy->head;
+}
+
+/*
+ * Get the tail element of the CS
+ */
+always_inline u32
+hicn_cs_policy_get_tail (const hicn_cs_policy_t *policy)
+{
+ return policy->tail;
+}
+
+always_inline void
+hicn_cs_policy_insert (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t *pcs_entry)
+{
+ return policy->vft.hicn_cs_insert (policy, pcs, pcs_entry);
+}
+
+always_inline void
+hicn_cs_policy_update (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t *pcs_entry)
+{
+ return policy->vft.hicn_cs_update (policy, pcs, pcs_entry);
+}
+
+always_inline void
+hicn_cs_policy_dequeue (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t *pcs_entry)
+{
+ return policy->vft.hicn_cs_dequeue (policy, pcs, pcs_entry);
+}
+
+always_inline void
+hicn_cs_policy_delete_get (hicn_cs_policy_t *policy, const hicn_pit_cs_t *pcs,
+ hicn_pcs_entry_t **pcs_entry)
+{
+ return policy->vft.hicn_cs_delete_get (policy, pcs, pcs_entry);
+}
+
+always_inline int
+hicn_cs_policy_trim (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs,
+ u32 *node_list, int sz)
+{
+ return policy->vft.hicn_cs_trim (policy, pcs, node_list, sz);
+}
+
+always_inline int
+hicn_cs_policy_flush (hicn_cs_policy_t *policy, hicn_pit_cs_t *pcs)
+{
+ return policy->vft.hicn_cs_flush (policy, pcs);
+}
+
+#endif /* __HICN_POLICY_H__ */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/cli.c b/hicn-plugin/src/cli.c
index f743f6362..70fe3307a 100644
--- a/hicn-plugin/src/cli.c
+++ b/hicn-plugin/src/cli.c
@@ -215,7 +215,7 @@ static clib_error_t *
hicn_cli_show_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
vlib_cli_command_t *cmd)
{
- int face_p = 0, fib_p = 0, all_p = 0, internal_p = 0, strategies_p = 0,
+ int face_p = 0, fib_p = 0, all_p = 0, strategies_p = 0,
ret = HICN_ERROR_NONE;
/* Get a line of input. */
@@ -228,14 +228,6 @@ hicn_cli_show_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
{
face_p = 1;
}
- else if (unformat (line_input, "internal"))
- {
- /*
- * We consider 'internal' a superset, so
- * include 'detail' too
- */
- internal_p = 1;
- }
else if (unformat (line_input, "strategies"))
{
/*
@@ -335,20 +327,6 @@ hicn_cli_show_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
vlib_cli_output (vm, (char *) strbuf);
}
done:
- if (all_p && internal_p && ret == HICN_ERROR_NONE)
- {
- vlib_cli_output (vm, "Plugin features: cs:%d\n", HICN_FEATURE_CS);
- vlib_cli_output (vm,
- "Removed CS entries (and freed vlib buffers) %d, "
- "Removed PIT entries %d\n",
- hicn_main.pitcs.pcs_cs_dealloc,
- hicn_main.pitcs.pcs_pit_dealloc);
- vlib_cli_output (vm,
- "Bucke count %d, Overflow buckets count %d, used %d\n",
- hicn_main.pitcs.pcs_table->ht_bucket_count,
- hicn_main.pitcs.pcs_table->ht_overflow_bucket_count,
- hicn_main.pitcs.pcs_table->ht_overflow_buckets_used);
- }
return (ret == HICN_ERROR_NONE) ?
0 :
clib_error_return (0, "%s\n", get_error_string (ret));
diff --git a/hicn-plugin/src/data_fwd.h b/hicn-plugin/src/data_fwd.h
index b21fa0a2f..129ca5b73 100644
--- a/hicn-plugin/src/data_fwd.h
+++ b/hicn-plugin/src/data_fwd.h
@@ -62,6 +62,15 @@ typedef enum
HICN_DATA_FWD_N_NEXT,
} hicn_data_fwd_next_t;
+/*
+ * Node context data; we think this is per-thread/instance
+ */
+typedef struct hicn_data_fwd_runtime_s
+{
+ int id;
+ hicn_pit_cs_t *pitcs;
+} hicn_data_fwd_runtime_t;
+
/**
* @brief Create a maximum of 256 clones of buffer and store them
* in the supplied array. Unlike the original function in the vlib
diff --git a/hicn-plugin/src/data_fwd_node.c b/hicn-plugin/src/data_fwd_node.c
index a3f1a592f..f909ae536 100644
--- a/hicn-plugin/src/data_fwd_node.c
+++ b/hicn-plugin/src/data_fwd_node.c
@@ -32,291 +32,6 @@ static char *hicn_data_fwd_error_strings[] = {
};
/* Declarations */
-always_inline void drop_packet (vlib_main_t *vm, u32 bi0, u32 *n_left_to_next,
- u32 *next0, u32 **to_next, u32 *next_index,
- vlib_node_runtime_t *node);
-
-always_inline int
-hicn_satisfy_faces (vlib_main_t *vm, u32 b0, hicn_pcs_entry_t *pitp,
- u32 *n_left_to_next, u32 **to_next, u32 *next_index,
- vlib_node_runtime_t *node, u8 isv6,
- vl_api_hicn_api_node_stats_get_reply_t *stats);
-
-always_inline void
-clone_data_to_cs (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t *pitp, hicn_header_t *hicn0, f64 tnow,
- hicn_hash_node_t *nodep, vlib_buffer_t *b0,
- hicn_hash_entry_t *hash_entry, u64 name_hash,
- hicn_buffer_t *hicnb, const hicn_dpo_vft_t *dpo_vft,
- dpo_id_t *hicn_dpo_id, hicn_lifetime_t dmsg_lifetime);
-
-/* packet trace format function */
-always_inline u8 *hicn_data_fwd_format_trace (u8 *s, va_list *args);
-
-vlib_node_registration_t hicn_data_fwd_node;
-
-/*
- * ICN forwarder node for interests: handling of Data delivered based on ACL.
- * - 1 packet at a time - ipv4/tcp ipv6/tcp
- */
-static uword
-hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
- vlib_frame_t *frame)
-{
-
- u32 n_left_from, *from, *to_next;
- hicn_data_fwd_next_t next_index;
- hicn_pit_cs_t *pitcs = &hicn_main.pitcs;
- vl_api_hicn_api_node_stats_get_reply_t stats = { 0 };
- f64 tnow;
- u32 data_received = 1;
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- /* Capture time in vpp terms */
- tnow = vlib_time_now (vm);
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- vlib_buffer_t *b0;
- u8 isv6;
- u8 *nameptr;
- u16 namelen;
- u32 bi0;
- u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP;
- hicn_header_t *hicn0;
- hicn_buffer_t *hicnb0;
- hicn_hash_node_t *node0;
- const hicn_strategy_vft_t *strategy_vft0;
- const hicn_dpo_vft_t *dpo_vft0;
- u8 dpo_ctx_id0;
- hicn_pcs_entry_t *pitp;
- hicn_hash_entry_t *hash_entry0;
- int ret = HICN_ERROR_NONE;
-
- /* Prefetch for next iteration. */
- if (n_left_from > 1)
- {
- vlib_buffer_t *b1;
- b1 = vlib_get_buffer (vm, from[1]);
- CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, STORE);
- }
- /* Dequeue a packet buffer */
- /*
- * Do not copy the index in the next buffer, we'll do
- * it later. The packet might be cloned, so the buffer to move
- * to next must be the cloned one
- */
- bi0 = from[0];
- from += 1;
- n_left_from -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- /* Get hicn buffer and state */
- hicnb0 = hicn_get_buffer (b0);
- hicn0 = (hicn_header_t *) (vlib_buffer_get_current (b0));
- hicn_get_internal_state (hicnb0, pitcs, &node0, &strategy_vft0,
- &dpo_vft0, &dpo_ctx_id0, &hash_entry0);
-
- hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen);
- isv6 = hicn_buffer_is_v6 (b0);
- pitp = hicn_pit_get_data (node0);
-
- if (PREDICT_FALSE (
- !hicn_node_compare (nameptr, namelen, node0) ||
- (hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY)))
- {
- /*
- * Remove the lock acquired from
- * data_pcslookup node
- */
- dpo_id_t hicn_dpo_id0 = { .dpoi_type =
- dpo_vft0->hicn_dpo_get_type (),
- .dpoi_proto = 0,
- .dpoi_next_node = 0,
- .dpoi_index = dpo_ctx_id0 };
- hicn_pcs_remove_lock (pitcs, &pitp, &node0, vm, hash_entry0,
- dpo_vft0, &hicn_dpo_id0);
-
- drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next,
- &next_index, node);
-
- goto end_processing;
- }
- /*
- * Check if the hit is instead a collision in the
- * hash table. Unlikely to happen.
- */
- /*
- * there is no guarantee that the type of entry has
- * not changed from the lookup.
- */
-
- if (tnow > pitp->shared.expire_time ||
- (hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED))
- {
- dpo_id_t hicn_dpo_id0 = { .dpoi_type =
- dpo_vft0->hicn_dpo_get_type (),
- .dpoi_proto = 0,
- .dpoi_next_node = 0,
- .dpoi_index = dpo_ctx_id0 };
- hicn_pcs_delete (pitcs, &pitp, &node0, vm, hash_entry0, dpo_vft0,
- &hicn_dpo_id0);
-
- drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next,
- &next_index, node);
- stats.pit_expired_count++;
-
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
- (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- hicn_data_fwd_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = HICN_PACKET_TYPE_DATA;
- t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- t->next_index = next0;
- clib_memcpy (t->packet_data, vlib_buffer_get_current (b0),
- sizeof (t->packet_data));
- }
- }
- else
- {
- ASSERT ((hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED) ==
- 0);
-
- data_received++;
- /*
- * We do not check if the data is coming from
- * the outgoing interest face.
- */
-
- /* Prepare the buffer for the cloning */
- ret =
- hicn_satisfy_faces (vm, bi0, pitp, &n_left_to_next, &to_next,
- &next_index, node, isv6, &stats);
-
- dpo_id_t hicn_dpo_id0 = { .dpoi_type =
- dpo_vft0->hicn_dpo_get_type (),
- .dpoi_proto = 0,
- .dpoi_next_node = 0,
- .dpoi_index = dpo_ctx_id0 };
-
- if (PREDICT_FALSE (ret != HICN_ERROR_NONE))
- {
- hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, hash_entry0,
- dpo_vft0, &hicn_dpo_id0);
- continue;
- }
- /*
- * Call the strategy callback since the
- * interest has been satisfied
- */
- strategy_vft0->hicn_receive_data (dpo_ctx_id0,
- pitp->u.pit.pe_txnh);
-
-#if HICN_FEATURE_CS
- hicn_lifetime_t dmsg_lifetime;
-
- hicn_type_t type = hicnb0->type;
- hicn_ops_vft[type.l1]->get_lifetime (type, &hicn0->protocol,
- &dmsg_lifetime);
-
- if (dmsg_lifetime)
- {
- /*
- * Clone data packet in the content store and
- * convert the PIT entry into a CS entry
- */
- clone_data_to_cs (vm, pitcs, pitp, hicn0, tnow, node0, b0,
- hash_entry0, hicnb0->name_hash, hicnb0,
- dpo_vft0, &hicn_dpo_id0, dmsg_lifetime);
-
- hicn_pcs_remove_lock (pitcs, &pitp, &node0, vm, hash_entry0,
- NULL, NULL);
- }
- else
- {
- /*
- * If the packet is copied and not cloned, we need to free
- * the vlib_buffer
- */
- if (hicnb0->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL)
- {
- vlib_buffer_free_one (vm, bi0);
- }
- else
- {
- /*
- * Remove one reference as the buffer is no
- * longer in any frame. The vlib_buffer will be freed
- * when all its cloned vlib_buffer will be freed.
- */
- b0->ref_count--;
- }
-
- /* Delete the PIT entry */
- hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, hash_entry0,
- dpo_vft0, &hicn_dpo_id0);
- }
-#else
- ASSERT (pitp == hicn_pit_get_data (node0));
- /*
- * If the packet is copied and not cloned, we need to free the
- * vlib_buffer
- */
- if (hicnb0->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL)
- {
- vlib_buffer_free_one (vm, bi0);
- }
- else
- {
- /*
- * Remove one reference as the buffer is no
- * longer in any frame. The vlib_buffer will be freed when
- * all its cloned vlib_buffer will be freed.
- */
- b0->ref_count--;
- }
-
- /* Delete the PIT entry */
- hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, hash_entry0,
- dpo_vft0, &hicn_dpo_id0);
-#endif
- }
- end_processing:
-
- /* Incr packet counter */
- stats.pkts_processed += 1;
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
- u32 pit_int_count = hicn_pit_get_int_count (pitcs);
- u32 pit_cs_count = hicn_pit_get_cs_count (pitcs);
-
- vlib_node_increment_counter (vm, hicn_data_fwd_node.index,
- HICNFWD_ERROR_DATAS, stats.pkts_data_count);
-
- update_node_counter (vm, hicn_data_fwd_node.index, HICNFWD_ERROR_INT_COUNT,
- pit_int_count);
- update_node_counter (vm, hicn_data_fwd_node.index, HICNFWD_ERROR_CS_COUNT,
- pit_cs_count);
- update_node_counter (vm, hicn_data_fwd_node.index,
- HICNFWD_ERROR_INTEREST_AGG_ENTRY,
- stats.pkts_data_count / data_received);
-
- return (frame->n_vectors);
-}
-
always_inline void
drop_packet (vlib_main_t *vm, u32 bi0, u32 *n_left_to_next, u32 *next0,
u32 **to_next, u32 *next_index, vlib_node_runtime_t *node)
@@ -339,7 +54,8 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp,
{
int found = 0;
int ret = HICN_ERROR_NONE;
- u32 *clones = NULL, *header = NULL;
+ u32 inline_clones[HICN_FACE_DB_INLINE_FACES];
+ u32 *clones = inline_clones, *header = NULL;
u32 n_left_from = 0;
u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP,
next1 = HICN_DATA_FWD_NEXT_ERROR_DROP;
@@ -354,8 +70,11 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp,
* need to be careful to clone it only 254 times as the buffer
* already has n_add_reds=1.
*/
- vec_alloc (clones, pitp->u.pit.faces.n_faces);
- header = clones;
+ if (hicn_pcs_entry_pit_get_n_faces (pitp) > HICN_FACE_DB_INLINE_FACES)
+ {
+ vec_alloc (clones, hicn_pcs_entry_pit_get_n_faces (pitp));
+ header = clones;
+ }
/* Clone bi0 */
vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0);
@@ -378,7 +97,7 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp,
{
/* Add one reference to maintain the buffer in the CS.
* b0->ref_count == 0 has two meaning: it has 1 buffer or no buffer
- * chained to it. vlib_buffer_clone2 add a number of reference equalt to
+ * chained to it. vlib_buffer_clone2 add a number of reference equal to
* pitp->u.pit.faces.n_faces - 1 as vlib_buffer_clone does. So after all
* the packet are forwarded the buffer stored in the CS will have
* ref_count == 0;
@@ -386,17 +105,16 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp,
b0->ref_count++;
}
- found = n_left_from = vlib_buffer_clone2 (
- vm, bi0, clones, pitp->u.pit.faces.n_faces, buffer_advance);
+ found = n_left_from =
+ vlib_buffer_clone2 (vm, bi0, clones, pitp->u.pit.n_faces, buffer_advance);
- ASSERT (n_left_from == pitp->u.pit.faces.n_faces);
+ ASSERT (n_left_from == hicn_pcs_entry_pit_get_n_faces (pitp));
/* Index to iterate over the faces */
int i = 0;
while (n_left_from > 0)
{
-
// Dual loop, X2
while (n_left_from >= 4 && *n_left_to_next >= 2)
{
@@ -413,8 +131,11 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp,
CLIB_PREFETCH (h3, 2 * CLIB_CACHE_LINE_BYTES, STORE);
}
- face0 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces);
- face1 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces);
+ face0 = hicn_pcs_entry_pit_get_dpo_face (pitp, i);
+ face1 = hicn_pcs_entry_pit_get_dpo_face (pitp, i + 1);
+
+ // Increment index
+ i += 2;
h0 = vlib_get_buffer (vm, clones[0]);
h1 = vlib_get_buffer (vm, clones[1]);
@@ -469,7 +190,8 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp,
u32 hi0;
hicn_face_id_t face0;
- face0 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces);
+ face0 = hicn_pcs_entry_pit_get_dpo_face (pitp, i);
+ i += 1;
h0 = vlib_get_buffer (vm, clones[0]);
@@ -530,36 +252,28 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp,
}
always_inline void
-clone_data_to_cs (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
- hicn_pcs_entry_t *pitp, hicn_header_t *hicn0, f64 tnow,
- hicn_hash_node_t *nodep, vlib_buffer_t *b0,
- hicn_hash_entry_t *hash_entry, u64 name_hash,
- hicn_buffer_t *hicnb, const hicn_dpo_vft_t *dpo_vft,
- dpo_id_t *hicn_dpo_id, hicn_lifetime_t dmsg_lifetime)
+clone_data_to_cs (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *pcs_entry,
+ u32 buffer_index, hicn_header_t *hicn0, f64 tnow,
+ hicn_lifetime_t dmsg_lifetime)
{
/*
* At this point we think we're safe to proceed. Store the CS buf in
* the PIT/CS hashtable entry
*/
- /*
- * Start turning the PIT into a CS. Note that we may be stepping on
- * the PIT part of the union as we update the CS part, so don't
- * expect the PIT part to be valid after this point.
- */
- hicn_pit_to_cs (vm, pitcs, pitp, hash_entry, nodep, dpo_vft, hicn_dpo_id);
-
- pitp->shared.create_time = tnow;
+ // Start turning the PIT into a CS. Note that we may be stepping on the PIT
+ // part of the union as we update the CS part, so don't expect the PIT part
+ // to be valid after this point.
+ hicn_pit_to_cs (pitcs, pcs_entry, buffer_index);
+ hicn_pcs_entry_set_create_time (pcs_entry, tnow);
if (dmsg_lifetime < HICN_PARAM_CS_LIFETIME_MIN ||
dmsg_lifetime > HICN_PARAM_CS_LIFETIME_MAX)
{
dmsg_lifetime = HICN_PARAM_CS_LIFETIME_DFLT;
}
- pitp->shared.expire_time = hicn_pcs_get_exp_time (tnow, dmsg_lifetime);
-
- /* Store the original packet buffer in the CS node */
- pitp->u.cs.cs_pkt_buf = vlib_get_buffer_index (vm, b0);
+ hicn_pcs_entry_set_expire_time (pcs_entry,
+ hicn_pcs_get_exp_time (tnow, dmsg_lifetime));
}
/* packet trace format function */
@@ -579,6 +293,206 @@ hicn_data_fwd_format_trace (u8 *s, va_list *args)
return (s);
}
+vlib_node_registration_t hicn_data_fwd_node;
+
+/*
+ * ICN forwarder node for interests: handling of Data delivered based on ACL.
+ * - 1 packet at a time - ipv4/tcp ipv6/tcp
+ */
+static uword
+hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
+{
+
+ u32 n_left_from, *from, *to_next;
+ hicn_data_fwd_next_t next_index;
+ hicn_data_fwd_runtime_t *rt;
+ vl_api_hicn_api_node_stats_get_reply_t stats = { 0 };
+ f64 tnow;
+ u32 data_received = 1;
+ vlib_buffer_t *b0;
+ u8 isv6;
+ u32 bi0;
+ u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP;
+ hicn_header_t *hicn0;
+ hicn_buffer_t *hicnb0;
+ const hicn_strategy_vft_t *strategy_vft0 = NULL;
+ const hicn_dpo_vft_t *dpo_vft0;
+ u8 dpo_ctx_id0 = ~0;
+ u32 pcs_entry_id;
+ hicn_pcs_entry_t *pcs_entry = NULL;
+ hicn_lifetime_t dmsg_lifetime;
+ int ret = HICN_ERROR_NONE;
+
+ rt = vlib_node_get_runtime_data (vm, node->node_index);
+
+ if (PREDICT_FALSE (rt->pitcs == NULL))
+ {
+ rt->pitcs = &hicn_main.pitcs;
+ }
+
+ from = vlib_frame_vector_args (frame);
+ n_left_from = frame->n_vectors;
+ next_index = node->cached_next_index;
+
+ /* Capture time in vpp terms */
+ tnow = vlib_time_now (vm);
+
+ while (n_left_from > 0)
+ {
+ u32 n_left_to_next;
+ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
+
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ /* Prefetch for next iteration. */
+ if (n_left_from > 1)
+ {
+ vlib_buffer_t *b1;
+ b1 = vlib_get_buffer (vm, from[1]);
+ CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, STORE);
+ }
+
+ // Dequeue a packet buffer. Do not copy the index in the next buffer,
+ // we'll do it later. The packet might be cloned, so the buffer to
+ // move to next must be the cloned one
+ bi0 = from[0];
+ from += 1;
+ n_left_from -= 1;
+
+ b0 = vlib_get_buffer (vm, bi0);
+
+ // Get hicn buffer and state
+ hicnb0 = hicn_get_buffer (b0);
+ hicn0 = (hicn_header_t *) (vlib_buffer_get_current (b0));
+
+ hicn_get_internal_state (hicnb0, &pcs_entry_id, &strategy_vft0,
+ &dpo_vft0, &dpo_ctx_id0);
+
+ // Get PCS entry
+ pcs_entry =
+ hicn_pcs_entry_get_entry_from_index (rt->pitcs, pcs_entry_id);
+
+ isv6 = hicn_buffer_is_v6 (b0);
+
+ // If PCS entry is CS, drop the packet
+ if (PREDICT_FALSE (hicn_pcs_entry_is_cs (pcs_entry)))
+ {
+ drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next,
+ &next_index, node);
+
+ goto end_processing;
+ }
+
+ // We are sure the entry is a PIT entry. Check whether it is expired.
+ if (tnow > hicn_pcs_entry_get_expire_time (pcs_entry))
+ {
+ // Entry expired. Release lock
+ hicn_pcs_entry_remove_lock (rt->pitcs, pcs_entry);
+
+ // Drop packet
+ drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next,
+ &next_index, node);
+
+ // Update stats
+ stats.pit_expired_count++;
+
+ // Trace
+ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
+ (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ hicn_data_fwd_trace_t *t =
+ vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->pkt_type = HICN_PACKET_TYPE_DATA;
+ t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ t->next_index = next0;
+ clib_memcpy (t->packet_data, vlib_buffer_get_current (b0),
+ sizeof (t->packet_data));
+ }
+ }
+ else
+ {
+ // Update stats
+ data_received++;
+
+ /*
+ * We do not check if the data is coming from
+ * the outgoing interest face.
+ */
+
+ // Prepare the buffer for the cloning
+ ret =
+ hicn_satisfy_faces (vm, bi0, pcs_entry, &n_left_to_next,
+ &to_next, &next_index, node, isv6, &stats);
+
+ if (PREDICT_FALSE (ret != HICN_ERROR_NONE))
+ {
+ hicn_pcs_entry_remove_lock (rt->pitcs, pcs_entry);
+ continue;
+ }
+
+ // Call the strategy callback since the interest has been
+ // satisfied
+ strategy_vft0->hicn_receive_data (
+ dpo_ctx_id0, vnet_buffer (b0)->ip.adj_index[VLIB_RX]);
+
+ dmsg_lifetime = hicn_buffer_get_lifetime (b0);
+
+ if (dmsg_lifetime)
+ {
+ // Clone data packet in the content store and convert the PIT
+ // entry into a CS entry
+ clone_data_to_cs (rt->pitcs, pcs_entry, bi0, hicn0, tnow,
+ dmsg_lifetime);
+ }
+ else
+ {
+ /*
+ * If the packet is copied and not cloned, we need to free
+ * the vlib_buffer
+ */
+ if (hicnb0->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL)
+ {
+ vlib_buffer_free_one (vm, bi0);
+ }
+ else
+ {
+ /*
+ * Remove one reference as the buffer is no
+ * longer in any frame. The vlib_buffer will be freed
+ * when all its cloned vlib_buffer will be freed.
+ */
+ b0->ref_count--;
+ }
+ // Delete the PIT entry
+ hicn_pcs_entry_remove_lock (rt->pitcs, pcs_entry);
+ }
+ }
+ end_processing:
+
+ /* Incr packet counter */
+ stats.pkts_processed += 1;
+ }
+
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+ u32 pit_int_count = hicn_pcs_get_pit_count (rt->pitcs);
+ u32 pit_cs_count = hicn_pcs_get_cs_count (rt->pitcs);
+
+ vlib_node_increment_counter (vm, hicn_data_fwd_node.index,
+ HICNFWD_ERROR_DATAS, stats.pkts_data_count);
+
+ update_node_counter (vm, hicn_data_fwd_node.index, HICNFWD_ERROR_INT_COUNT,
+ pit_int_count);
+ update_node_counter (vm, hicn_data_fwd_node.index, HICNFWD_ERROR_CS_COUNT,
+ pit_cs_count);
+ update_node_counter (vm, hicn_data_fwd_node.index,
+ HICNFWD_ERROR_INTEREST_AGG_ENTRY,
+ stats.pkts_data_count / data_received);
+
+ return (frame->n_vectors);
+}
+
/*
* Node registration for the data forwarder node
*/
diff --git a/hicn-plugin/src/data_input_node.c b/hicn-plugin/src/data_input_node.c
index 65bba7b1b..dbf49de54 100644
--- a/hicn-plugin/src/data_input_node.c
+++ b/hicn-plugin/src/data_input_node.c
@@ -105,6 +105,15 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
u32 n_left_from, n_left_to_next, *from, *to_next;
ip_lookup_next_t next;
u32 thread_index = vm->thread_index;
+ vlib_buffer_t *p0, *p1;
+ u32 pi0, pi1, lbi0, lbi1, wrong_next;
+ ip_lookup_next_t next0, next1;
+ ip6_header_t *ip0, *ip1;
+ ip6_address_t *src_addr0, *src_addr1;
+ ip46_address_t dst_addr0, dst_addr1;
+ const dpo_id_t *dpo0, *dpo1;
+ const load_balance_t *lb0, *lb1;
+ hicn_buffer_t *hicnb0, *hicnb1;
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
@@ -116,15 +125,6 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
while (n_left_from >= 4 && n_left_to_next >= 2)
{
- vlib_buffer_t *p0, *p1;
- u32 pi0, pi1, lbi0, lbi1, wrong_next;
- ip_lookup_next_t next0, next1;
- ip6_header_t *ip0, *ip1;
- ip6_address_t *src_addr0, *src_addr1;
- ip46_address_t dst_addr0, dst_addr1;
- const dpo_id_t *dpo0, *dpo1;
- const load_balance_t *lb0, *lb1;
-
/* Prefetch next iteration. */
{
vlib_buffer_t *p2, *p3;
@@ -144,6 +144,9 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
p0 = vlib_get_buffer (vm, pi0);
p1 = vlib_get_buffer (vm, pi1);
+ hicnb0 = hicn_get_buffer (p0);
+ hicnb1 = hicn_get_buffer (p1);
+
ip0 = vlib_buffer_get_current (p0);
ip1 = vlib_buffer_get_current (p1);
@@ -177,6 +180,7 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
if (dpo_is_hicn (dpo0))
{
next0 = (ip_lookup_next_t) HICN_DATA_INPUT_IP6_NEXT_FACE;
+ hicnb0->dpo_ctx_id = dpo0->dpoi_index;
hicn_data_input_set_adj_index (
p0, &dst_addr0, hicn_strategy_dpo_ctx_get (dpo0->dpoi_index));
}
@@ -186,6 +190,7 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
if (dpo_is_hicn (dpo1))
{
next1 = (ip_lookup_next_t) HICN_DATA_INPUT_IP6_NEXT_FACE;
+ hicnb1->dpo_ctx_id = dpo1->dpoi_index;
hicn_data_input_set_adj_index (
p1, &dst_addr1, hicn_strategy_dpo_ctx_get (dpo1->dpoi_index));
}
@@ -267,6 +272,7 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
u32 pi0, lbi0;
ip_lookup_next_t next0;
load_balance_t *lb0;
+ hicn_buffer_t *hicnb0;
ip6_address_t *src_addr0;
ip46_address_t dst_addr0;
const dpo_id_t *dpo0;
@@ -275,6 +281,7 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
to_next[0] = pi0;
p0 = vlib_get_buffer (vm, pi0);
+ hicnb0 = hicn_get_buffer (p0);
ip0 = vlib_buffer_get_current (p0);
src_addr0 = &ip0->src_address;
ip46_address_set_ip6 (&dst_addr0, &ip0->dst_address);
@@ -294,6 +301,7 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
next0 = (ip_lookup_next_t) HICN_DATA_INPUT_IP6_NEXT_FACE;
hicn_data_input_set_adj_index (
p0, &dst_addr0, hicn_strategy_dpo_ctx_get (dpo0->dpoi_index));
+ hicnb0->dpo_ctx_id = dpo0->dpoi_index;
}
else
next0 = (ip_lookup_next_t) HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL;
@@ -365,6 +373,13 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
vlib_buffer_t **b = bufs;
u16 nexts[VLIB_FRAME_SIZE], *next;
+ ip4_header_t *ip0, *ip1, *ip2, *ip3;
+ const load_balance_t *lb0, *lb1, *lb2, *lb3;
+ ip4_address_t *src_addr0, *src_addr1, *src_addr2, *src_addr3;
+ ip46_address_t dst_addr0, dst_addr1, dst_addr2, dst_addr3;
+ u32 lb_index0, lb_index1, lb_index2, lb_index3;
+ const dpo_id_t *dpo0, *dpo1, *dpo2, *dpo3;
+ hicn_buffer_t *hicnb0, *hicnb1, *hicnb2, *hicnb3;
from = vlib_frame_vector_args (frame);
n_left = frame->n_vectors;
@@ -374,13 +389,6 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
#if (CLIB_N_PREFETCHES >= 8)
while (n_left >= 4)
{
- ip4_header_t *ip0, *ip1, *ip2, *ip3;
- const load_balance_t *lb0, *lb1, *lb2, *lb3;
- ip4_address_t *src_addr0, *src_addr1, *src_addr2, *src_addr3;
- ip46_address_t dst_addr0, dst_addr1, dst_addr2, dst_addr3;
- u32 lb_index0, lb_index1, lb_index2, lb_index3;
- const dpo_id_t *dpo0, *dpo1, *dpo2, *dpo3;
-
/* Prefetch next iteration. */
if (n_left >= 8)
{
@@ -400,6 +408,11 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
ip2 = vlib_buffer_get_current (b[2]);
ip3 = vlib_buffer_get_current (b[3]);
+ hicnb0 = hicn_get_buffer (b[0]);
+ hicnb1 = hicn_get_buffer (b[1]);
+ hicnb2 = hicn_get_buffer (b[2]);
+ hicnb3 = hicn_get_buffer (b[3]);
+
src_addr0 = &ip0->src_address;
src_addr1 = &ip1->src_address;
src_addr2 = &ip2->src_address;
@@ -444,6 +457,7 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
if (dpo_is_hicn (dpo0))
{
next[0] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicnb0->dpo_ctx_id = dpo0->dpoi_index;
hicn_data_input_set_adj_index (
b[0], &dst_addr0, hicn_strategy_dpo_ctx_get (dpo0->dpoi_index));
}
@@ -453,6 +467,7 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
if (dpo_is_hicn (dpo1))
{
next[1] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicnb1->dpo_ctx_id = dpo1->dpoi_index;
hicn_data_input_set_adj_index (
b[1], &dst_addr1, hicn_strategy_dpo_ctx_get (dpo1->dpoi_index));
}
@@ -462,6 +477,7 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
if (dpo_is_hicn (dpo2))
{
next[2] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicnb2->dpo_ctx_id = dpo2->dpoi_index;
hicn_data_input_set_adj_index (
b[2], &dst_addr2, hicn_strategy_dpo_ctx_get (dpo2->dpoi_index));
}
@@ -471,6 +487,7 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
if (dpo_is_hicn (dpo3))
{
next[3] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicnb3->dpo_ctx_id = dpo3->dpoi_index;
hicn_data_input_set_adj_index (
b[3], &dst_addr3, hicn_strategy_dpo_ctx_get (dpo3->dpoi_index));
}
@@ -533,15 +550,6 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
#elif (CLIB_N_PREFETCHES >= 4)
while (n_left >= 4)
{
- ip4_header_t *ip0, *ip1;
- const load_balance_t *lb0, *lb1;
- ip4_address_t *src_addr0, *src_addr1;
- ip46_address_t dst_addr0, dst_addr1;
- u32 lb_index0, lb_index1;
- flow_hash_config_t flow_hash_config0, flow_hash_config1;
- u32 hash_c0, hash_c1;
- const dpo_id_t *dpo0, *dpo1;
-
/* Prefetch next iteration. */
{
vlib_prefetch_buffer_header (b[2], LOAD);
@@ -554,6 +562,9 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
ip0 = vlib_buffer_get_current (b[0]);
ip1 = vlib_buffer_get_current (b[1]);
+ hicnb0 = hicn_get_buffer (b[0]);
+ hicnb1 = hicn_get_buffer (b[1]);
+
src_addr0 = &ip0->src_address;
src_addr1 = &ip1->src_address;
@@ -582,6 +593,7 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
if (dpo_is_hicn (dpo0))
{
next[0] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicnb0->dpo_ctx_id = dpo0->dpoi_index;
hicn_data_input_set_adj_index (
b[0], &dst_addr0, hicn_strategy_dpo_ctx_get (dpo0->dpoi_index));
}
@@ -591,6 +603,7 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
if (dpo_is_hicn (dpo1))
{
next[1] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicnb1->dpo_ctx_id = dpo1->dpoi_index;
hicn_data_input_set_adj_index (
b[1], &dst_addr1, hicn_strategy_dpo_ctx_get (dpo1->dpoi_index));
}
@@ -629,23 +642,17 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
#endif
while (n_left > 0)
{
- ip4_header_t *ip0;
- const load_balance_t *lb0;
- ip4_address_t *src_addr0;
- ip46_address_t dst_addr0;
- u32 lbi0;
- const dpo_id_t *dpo0;
-
ip0 = vlib_buffer_get_current (b[0]);
+ hicnb0 = hicn_get_buffer (b[0]);
src_addr0 = &ip0->src_address;
ip46_address_set_ip4 (&dst_addr0, &ip0->dst_address);
ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]);
- lbi0 = ip4_fib_forwarding_lookup (vnet_buffer (b[0])->ip.fib_index,
- src_addr0);
+ lb_index0 = ip4_fib_forwarding_lookup (vnet_buffer (b[0])->ip.fib_index,
+ src_addr0);
- ASSERT (lbi0);
- lb0 = load_balance_get (lbi0);
+ ASSERT (lb_index0);
+ lb0 = load_balance_get (lb_index0);
ASSERT (lb0->lb_n_buckets > 0);
ASSERT (is_pow2 (lb0->lb_n_buckets));
@@ -655,6 +662,7 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
if (dpo_is_hicn (dpo0))
{
next[0] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicnb0->dpo_ctx_id = dpo0->dpoi_index;
hicn_data_input_set_adj_index (
b[0], &dst_addr0, hicn_strategy_dpo_ctx_get (dpo0->dpoi_index));
}
@@ -671,7 +679,7 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
t->isv6 = 0;
}
- vlib_increment_combined_counter (cm, thread_index, lbi0, 1,
+ vlib_increment_combined_counter (cm, thread_index, lb_index0, 1,
vlib_buffer_length_in_chain (vm, b[0]));
b += 1;
diff --git a/hicn-plugin/src/data_pcslookup_node.c b/hicn-plugin/src/data_pcslookup_node.c
index 95db66f54..55ddda9c4 100644
--- a/hicn-plugin/src/data_pcslookup_node.c
+++ b/hicn-plugin/src/data_pcslookup_node.c
@@ -44,6 +44,12 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hicn_data_pcslookup_next_t next_index;
hicn_data_pcslookup_runtime_t *rt;
vl_api_hicn_api_node_stats_get_reply_t stats = { 0 };
+ vlib_buffer_t *b0;
+ u32 bi0;
+ u32 next0 = HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP;
+ hicn_pcs_entry_t *pcs_entry = NULL;
+ hicn_buffer_t *hicnb0;
+ int ret;
rt = vlib_node_get_runtime_data (vm, node->node_index);
@@ -62,21 +68,7 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
while (n_left_from > 0 && n_left_to_next > 0)
{
- vlib_buffer_t *b0;
- u8 *nameptr;
- u16 namelen;
- u32 bi0;
- u32 next0 = HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP;
- u64 name_hash = 0;
- u32 node_id0 = 0;
- index_t dpo_ctx_id0 = 0;
- u8 vft_id0 = 0;
- u8 is_cs0;
- u8 hash_entry_id = 0;
- u8 bucket_is_overflown = 0;
- u32 bucket_id = ~0;
-
- /* Prefetch for next iteration. */
+ // Prefetch for next iteration.
if (n_left_from > 1)
{
vlib_buffer_t *b1;
@@ -84,9 +76,9 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
// Prefetch two cache lines-- 128 byte-- so that we load the
// hicn_buffer_t as well
CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, LOAD);
}
- /* Dequeue a packet buffer */
+
+ // Dequeue a packet buffer
bi0 = from[0];
from += 1;
n_left_from -= 1;
@@ -95,42 +87,34 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
n_left_to_next -= 1;
b0 = vlib_get_buffer (vm, bi0);
+ hicnb0 = hicn_get_buffer (b0);
+
+ // By default go to drop
next0 = HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP;
- /* Incr packet counter */
+ // Increase packet counters
stats.pkts_processed += 1;
+ stats.pkts_data_count += 1;
- hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen);
+ // Lookup the name in the PIT
+ ret = hicn_pcs_lookup_one (rt->pitcs, hicn_buffer_get_name (b0),
+ &pcs_entry);
- if (PREDICT_TRUE (
- hicn_hashtb_fullhash (nameptr, namelen, &name_hash) ==
- HICN_ERROR_NONE))
+ if (ret == HICN_ERROR_NONE)
{
- int res = hicn_hashtb_lookup_node (
- rt->pitcs->pcs_table, nameptr, namelen, name_hash,
- 1
- /*is_data. Do not take lock if hit CS */
- ,
- &node_id0, &dpo_ctx_id0, &vft_id0, &is_cs0, &hash_entry_id,
- &bucket_id, &bucket_is_overflown);
-
- stats.pkts_data_count += 1;
-
- if (res == HICN_ERROR_NONE)
- {
- /*
- * In case the result of the lookup
- * is a CS entry, the packet is
- * dropped
- */
- next0 = HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD + is_cs0;
- }
+ ret = hicn_store_internal_state (
+ b0, hicn_pcs_entry_get_index (rt->pitcs, pcs_entry),
+ hicnb0->dpo_ctx_id);
+
+ /*
+ * In case the result of the lookup
+ * is a CS entry, the packet is
+ * dropped
+ */
+ next0 = HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD +
+ (hicn_pcs_entry_is_cs (pcs_entry) && !ret);
}
- hicn_store_internal_state (b0, name_hash, node_id0, dpo_ctx_id0,
- vft_id0, hash_entry_id, bucket_id,
- bucket_is_overflown);
-
/*
* Verify speculative enqueue, maybe switch current
* next frame
@@ -153,11 +137,13 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
t->next_index = next0;
}
}
+
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
+
/* Check the CS LRU, and trim if necessary. */
- u32 pit_int_count = hicn_pit_get_int_count (rt->pitcs);
- u32 pit_cs_count = hicn_pit_get_cs_count (rt->pitcs);
+ u32 pit_int_count = hicn_pcs_get_pit_count (rt->pitcs);
+ u32 pit_cs_count = hicn_pcs_get_cs_count (rt->pitcs);
vlib_node_increment_counter (vm, hicn_data_pcslookup_node.index,
HICNFWD_ERROR_PROCESSED, stats.pkts_processed);
@@ -169,6 +155,7 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
HICNFWD_ERROR_INT_COUNT, pit_int_count);
update_node_counter (vm, hicn_data_pcslookup_node.index,
HICNFWD_ERROR_CS_COUNT, pit_cs_count);
+
return (frame->n_vectors);
}
diff --git a/hicn-plugin/src/face_db.h b/hicn-plugin/src/face_db.h
deleted file mode 100644
index 37a2af9ca..000000000
--- a/hicn-plugin/src/face_db.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef __HICN_FACE_DB_H__
-#define __HICN_FACE_DB_H__
-
-#include <vnet/dpo/dpo.h>
-#include "faces/face.h"
-
-/**
- * @file face_db.h
- *
- * Define a face db that is store in every pit entry. A face db containes a
- * list of incoming faces for interest packets that are used to forward data
- * packets on the interests' reverse path
- */
-
-/* Must be power of two */
-#define HICN_FACE_DB_INLINE_FACES 8
-
-#define HICN_PIT_BITMAP_SIZE_BYTE HICN_PARAM_FACES_MAX / 8
-#define HICN_PIT_N_HOP_BITMAP_SIZE HICN_PARAM_FACES_MAX
-
-#define HICN_PIT_N_HOP_BUCKET \
- (HICN_PARAM_PIT_ENTRY_PHOPS_MAX - HICN_FACE_DB_INLINE_FACES)
-
-typedef struct hicn_face_bucket_s
-{
- /* Array of indexes of virtual faces */
- hicn_face_id_t faces[HICN_PIT_N_HOP_BUCKET];
-
- /* Used to check if interests are retransmission */
- u8 bitmap[HICN_PIT_BITMAP_SIZE_BYTE];
-
-} hicn_face_bucket_t;
-
-extern hicn_face_bucket_t *hicn_face_bucket_pool;
-
-typedef struct __attribute__ ((packed)) hicn_face_db_s
-{
- /* 19B + 1B = 20B */
- /* Equal to one or zero */
- u8 is_overflow;
-
- /* Number of faces in the last bucket */
- /* Or next availabe entry for storing a dpo_id_t */
- /* 20B + 4B = 24B */
- u32 n_faces;
-
- /* 24B + 32B (8*4) = 56B */
- /* Array of indexes of virtual faces */
- hicn_face_id_t inline_faces[HICN_FACE_DB_INLINE_FACES];
-
- /* 56B + 4B = 60B */
- u32 next_bucket;
-
- /* 60B + 4B = 64B */
- u32 align;
- // align back to 64
-
-} hicn_face_db_t;
-
-always_inline hicn_face_id_t
-hicn_face_db_get_dpo_face (u32 index, hicn_face_db_t *face_db)
-{
- ASSERT (index < face_db->n_faces);
-
- return index < HICN_FACE_DB_INLINE_FACES ?
- (face_db->inline_faces[index]) :
- (pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket)
- ->faces[(index - HICN_FACE_DB_INLINE_FACES) &
- (HICN_PIT_N_HOP_BUCKET - 1)]);
-}
-
-always_inline void
-hicn_face_db_init (int max_element)
-{
- pool_init_fixed (hicn_face_bucket_pool, max_element);
-}
-
-always_inline hicn_face_bucket_t *
-hicn_face_db_get_bucket (u32 bucket_index)
-{
- return pool_elt_at_index (hicn_face_bucket_pool, bucket_index);
-}
-
-always_inline void
-hicn_face_db_add_face (hicn_face_id_t face_id, hicn_face_db_t *face_db)
-{
- // ASSERT (dpo->dpoi_index != ~0);
-
- hicn_face_bucket_t *faces_bkt =
- pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket);
-
- hicn_face_id_t *element =
- face_db->n_faces < HICN_FACE_DB_INLINE_FACES ?
- &(face_db->inline_faces[face_db->n_faces]) :
- &(faces_bkt->faces[(face_db->n_faces - HICN_FACE_DB_INLINE_FACES) &
- (HICN_PIT_N_HOP_BUCKET - 1)]);
-
- *element = face_id;
-
- u32 bitmap_index = face_id % HICN_PIT_N_HOP_BITMAP_SIZE;
- u32 position_array = bitmap_index / 8;
- u8 bit_index = (u8) (bitmap_index - position_array * 8);
-
- faces_bkt->bitmap[position_array] |= (0x01 << bit_index);
- face_db->n_faces++;
-}
-
-always_inline u8
-hicn_face_search (hicn_face_id_t index, hicn_face_db_t *face_db)
-{
- hicn_face_bucket_t *faces_bkt =
- pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket);
- u32 bitmap_index = index % HICN_PIT_N_HOP_BITMAP_SIZE;
-
- u32 position_array = bitmap_index / 8;
- u8 bit_index = bitmap_index - position_array * 8;
-
- return (faces_bkt->bitmap[position_array] >> bit_index) & 0x01;
-}
-
-always_inline void
-hicn_faces_flush (hicn_face_db_t *face_db)
-{
- hicn_face_bucket_t *faces_bkt =
- pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket);
- clib_memset_u8 (&(faces_bkt->bitmap), 0, HICN_PIT_BITMAP_SIZE_BYTE);
- face_db->n_faces = 0;
- pool_put_index (hicn_face_bucket_pool, face_db->next_bucket);
-}
-
-#endif /* // __HICN_FACE_DB_H__ */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables: eval: (c-set-style "gnu") End:
- */
diff --git a/hicn-plugin/src/faces/app/face_app_cli.c b/hicn-plugin/src/faces/app/face_app_cli.c
index b3488c462..0c00eb28d 100644
--- a/hicn-plugin/src/faces/app/face_app_cli.c
+++ b/hicn-plugin/src/faces/app/face_app_cli.c
@@ -18,7 +18,7 @@
#include <vlib/vlib.h>
#include <vnet/ip/ip6_packet.h>
-//#include "../face_dpo.h"
+#include "../../params.h"
#include "../face.h"
#include "face_prod.h"
#include "face_cons.h"
diff --git a/hicn-plugin/src/faces/app/face_prod_node.c b/hicn-plugin/src/faces/app/face_prod_node.c
index e3241e477..8adb7dce7 100644
--- a/hicn-plugin/src/faces/app/face_prod_node.c
+++ b/hicn-plugin/src/faces/app/face_prod_node.c
@@ -25,6 +25,7 @@
#include "face_prod.h"
#include "../../mgmt.h"
+#include "../../parser.h"
static __clib_unused char *face_prod_input_error_strings[] = {
#define _(sym, string) string,
diff --git a/hicn-plugin/src/faces/face_node.c b/hicn-plugin/src/faces/face_node.c
index 6dedbe1c4..e2fb79d17 100644
--- a/hicn-plugin/src/faces/face_node.c
+++ b/hicn-plugin/src/faces/face_node.c
@@ -23,6 +23,7 @@
#include "../cache_policies/cs_lru.h"
#include "../infra.h"
#include "../hicn.h"
+#include "../parser.h"
/**
* @File
@@ -234,7 +235,6 @@ typedef enum
ip_hdr1 = (IP_HEADER_##ipv *) vlib_buffer_get_current (b1); \
\
/* Parse packet and cache useful info in opaque2 */ \
- /* Parse packet and cache useful info in opaque2 */ \
ret0 = hicn_data_parse_pkt (b0); \
ret1 = hicn_data_parse_pkt (b1); \
is_icmp0 = ret0 == HICN_ERROR_PARSER_MAPME_PACKET; \
diff --git a/hicn-plugin/src/faces/iface_node.c b/hicn-plugin/src/faces/iface_node.c
index 3b6634d77..2f651beb8 100644
--- a/hicn-plugin/src/faces/iface_node.c
+++ b/hicn-plugin/src/faces/iface_node.c
@@ -19,6 +19,7 @@
#include "../hicn.h"
#include "../infra.h"
#include "../cache_policies/cs_lru.h"
+#include "../parser.h"
/**
* @File
diff --git a/hicn-plugin/src/hashtb.c b/hicn-plugin/src/hashtb.c
deleted file mode 100644
index eb7da81f2..000000000
--- a/hicn-plugin/src/hashtb.c
+++ /dev/null
@@ -1,1006 +0,0 @@
-/*
- * 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.
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <assert.h>
-#include <inttypes.h>
-
-#include <vlib/vlib.h>
-#include <vppinfra/pool.h>
-
-#include "pcs.h"
-#include "hashtb.h"
-#include "parser.h"
-#include "error.h"
-
-/* return dvd/dvr, rounded up (intended for integer values) */
-#define CEIL(dvd, dvr) \
- ({ \
- __typeof__ (dvd) _dvd = (dvd); \
- __typeof__ (dvr) _dvr = (dvr); \
- (_dvd + _dvr - 1) / _dvr; \
- })
-
-#ifndef ALIGN8
-#define ALIGN8(p) (((p) + 0x7) & ~(0x7))
-#endif
-
-#ifndef ALIGNPTR8
-#define ALIGNPTR8(p) ((void *) (((u8 *) (p) + 0x7) & ~(0x7)))
-#endif
-
-#ifndef ALIGN64
-#define ALIGN64(p) (((p) + 0x3f) & ~(0x3f))
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-/*
- * Offset to aligned start of additional data (PIT/CS, FIB) embedded in each
- * node.
- */
-u32 ht_node_data_offset_aligned;
-
-/* Some support for posix vs vpp mem management */
-#define MEM_ALLOC(x) clib_mem_alloc_aligned ((x), 8)
-#define MEM_FREE(p) clib_mem_free ((p))
-
-/*
- * Internal utilities
- */
-
-/* Allocate an overflow bucket */
-static hicn_hash_bucket_t *
-alloc_overflow_bucket (hicn_hashtb_h h)
-{
- hicn_hash_bucket_t *newbkt = NULL;
-
- if (h->ht_overflow_buckets_used < h->ht_overflow_bucket_count)
- {
- pool_get_aligned (h->ht_overflow_buckets, newbkt, 8);
-
- if (newbkt)
- {
- h->ht_overflow_buckets_used++;
- }
- }
- return (newbkt);
-}
-
-/* Free an overflow bucket; clear caller's pointer */
-static void
-free_overflow_bucket (hicn_hashtb_h h, hicn_hash_bucket_t **pb)
-{
- hicn_hash_bucket_t *bkt = *pb;
-
- ASSERT (h->ht_overflow_buckets_used > 0);
-
- pool_put (h->ht_overflow_buckets, bkt);
- h->ht_overflow_buckets_used--;
- *pb = NULL;
-}
-
-/*
- * Init, allocate a new hashtable
- */
-int
-hicn_hashtb_alloc (hicn_hashtb_h *ph, u32 max_elems, size_t app_data_size)
-{
- int ret = HICN_ERROR_NONE;
- hicn_hashtb_h h = NULL;
- u32 count;
- u32 total_buckets;
- size_t sz;
- hicn_hash_node_t *nodep;
- hicn_hash_bucket_t *bucket;
-
- if (ph == NULL)
- {
- ret = HICN_ERROR_HASHTB_INVAL;
- goto done;
- }
- if (max_elems < HICN_HASHTB_MIN_ENTRIES ||
- max_elems > HICN_HASHTB_MAX_ENTRIES)
- {
- goto done;
- }
- /* Allocate and init main hashtable struct */
- h = MEM_ALLOC (sizeof (hicn_hashtb_t));
- if (h == NULL)
- {
- ret = HICN_ERROR_HASHTB_NOMEM;
- goto done;
- }
- memset (h, 0, sizeof (hicn_hashtb_t));
-
- /* Compute main table bucket (row) count and size, and allocate */
-
- /* Consider the last entry as used for containing the overflow bucket */
- total_buckets = CEIL (max_elems, HICN_HASHTB_BUCKET_ENTRIES - 1);
- count = ALIGN8 (CEIL (total_buckets, HICN_HASHTB_FILL_FACTOR));
-
- h->ht_bucket_count = count;
-
- /* We _really_ expect to have buckets aligned on cache lines ... */
- sz = sizeof (hicn_hash_bucket_t);
- assert (sz == ALIGN64 (sz));
-
- h->ht_buckets = MEM_ALLOC (count * sz);
- if (h->ht_buckets == NULL)
- {
- ret = HICN_ERROR_HASHTB_NOMEM;
- goto done;
- }
- memset (h->ht_buckets, 0, count * sz);
-
- /*
- * First time through, compute offset to aligned extra data start in
- * each node struct it's crucial that both the node struct (that the
- * base hashtable uses) and the extra data area (that's also probably
- * a struct) are aligned.
- */
- if (ht_node_data_offset_aligned == 0)
- {
- count = STRUCT_OFFSET_OF (hicn_hash_node_t, hn_data);
- ht_node_data_offset_aligned = ALIGN8 (count);
- }
- // check app struct fits into space provided(HICN_HASH_NODE_APP_DATA_SIZE)
- u32 ht_node_data_size;
- ht_node_data_size = sizeof (hicn_hash_node_t) - ht_node_data_offset_aligned;
- if (app_data_size > ht_node_data_size)
- {
- clib_error (
- "hicn hashtable: fatal error: requested app data size(%u) > hashtb "
- "node's configured bytes available(%u), sizeof(hicn_shared_t)=%u, "
- "sizeof(hicn_pit_entry_t)=%u, sizeof(hicn_cs_entry_t)=%u",
- app_data_size, ht_node_data_size, sizeof (hicn_pcs_shared_t),
- sizeof (hicn_pit_entry_t), sizeof (hicn_cs_entry_t));
- }
- /*
- * Compute entry node count and size, allocate Allocate/'Hide' the
- * zero-th node so can use zero as an 'empty' value
- */
- pool_alloc_aligned (h->ht_nodes, max_elems, 8);
- if (h->ht_nodes == NULL)
- {
- ret = HICN_ERROR_HASHTB_NOMEM;
- goto done;
- }
- pool_get_aligned (h->ht_nodes, nodep, 8);
- // alloc node 0
- (void) nodep; /* Silence 'not used' warning */
-
- h->ht_node_count = max_elems;
- h->ht_nodes_used = 1;
-
- /*
- * Compute overflow bucket count and size, allocate
- */
- // count = ALIGN8(CEIL(max_elems, HICN_HASHTB_OVERFLOW_FRACTION));
- count = ALIGN8 (total_buckets - h->ht_bucket_count);
-
- pool_alloc_aligned (h->ht_overflow_buckets, count, 8);
- if (h->ht_overflow_buckets == NULL)
- {
- ret = HICN_ERROR_HASHTB_NOMEM;
- goto done;
- }
- /* 'Hide' the zero-th node so we can use zero as an 'empty' value */
- pool_get_aligned (h->ht_overflow_buckets, bucket, 8);
- (void) bucket; /* Silence 'not used' warning */
-
- h->ht_overflow_bucket_count = count;
- h->ht_overflow_buckets_used = 1;
-
-done:
-
- if (h)
- {
- if ((ret == HICN_ERROR_NONE) && ph)
- {
- *ph = h;
- }
- else
- {
- hicn_hashtb_free (&h);
- }
- }
- return (ret);
-}
-
-/*
- * Free, de-allocate a hashtable
- */
-int
-hicn_hashtb_free (hicn_hashtb_h *ph)
-{
- int ret = 0;
-
- if (ph)
- {
- if ((*ph)->ht_nodes)
- {
- pool_free ((*ph)->ht_nodes);
- (*ph)->ht_nodes = 0;
- }
- if ((*ph)->ht_overflow_buckets)
- {
- pool_free ((*ph)->ht_overflow_buckets);
- (*ph)->ht_overflow_buckets = 0;
- }
- if ((*ph)->ht_buckets)
- {
- MEM_FREE ((*ph)->ht_buckets);
- (*ph)->ht_buckets = 0;
- }
- MEM_FREE (*ph);
-
- *ph = NULL;
- }
- return (ret);
-}
-
-/*
- * Basic api to lookup a specific hash+key tuple. This does the entire lookup
- * operation, retrieving node structs and comparing keys, so it's not
- * optimized for prefetching or high performance.
- *
- * Returns zero and mails back a node on success, errno otherwise.
- */
-int
-hicn_hashtb_lookup_node (hicn_hashtb_h h, const u8 *key, u32 keylen,
- u64 hashval, u8 is_data, 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)
-{
- return (hicn_hashtb_lookup_node_ex (
- h, key, keylen, hashval, is_data, FALSE /* deleted nodes */, node_id,
- dpo_ctx_id, vft_id, is_cs, hash_entry_id, bucket_id, bucket_is_overflow));
-}
-
-/*
- * Extended api to lookup a specific hash+key tuple. The implementation
- * allows the caller to locate nodes that are marked for deletion, which is
- * part of some hashtable applications, such as the FIB.
- *
- * This does the entire lookup operation, retrieving node structs and comparing
- * keys, so it's not optimized for prefetching or high performance.
- *
- * Returns zero and mails back a node on success, errno otherwise.
- */
-int
-hicn_hashtb_lookup_node_ex (hicn_hashtb_h h, const u8 *key, u32 keylen,
- u64 hashval, u8 is_data, int include_deleted_p,
- 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)
-{
- int i, ret = HICN_ERROR_HASHTB_HASH_NOT_FOUND;
- int found_p = FALSE;
- u32 bidx;
- hicn_hash_bucket_t *bucket;
- u32 current_bucket_id = ~0;
-
- /*
- * Use some bits of the low half of the hash to locate a row/bucket
- * in the table
- */
- current_bucket_id = bidx = (hashval & (h->ht_bucket_count - 1));
-
- bucket = h->ht_buckets + bidx;
-
- *bucket_is_overflow = 0;
- /* Check the entries in the bucket for matching hash value */
-
-loop_buckets:
-
- for (i = 0; i < HICN_HASHTB_BUCKET_ENTRIES && !found_p; i++)
- {
- /*
- * If an entry is marked for deletion, ignore it unless the
- * caller explicitly wants these nodes.
- */
- if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_DELETED)
- {
- if (!include_deleted_p)
- {
- continue;
- }
- }
- if (bucket->hb_entries[i].he_msb64 == hashval)
- {
- /*
- * Found a candidate - must retrieve the actual node
- * and check the key.
- */
- *node_id = bucket->hb_entries[i].he_node;
- *dpo_ctx_id = bucket->hb_entries[i].dpo_ctx_id;
- *vft_id = bucket->hb_entries[i].vft_id;
- *is_cs =
- bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY;
- *hash_entry_id = i;
- *bucket_id = current_bucket_id;
- /*
- * If we are doing lookup for a data, do not take a
- * lock in case of a hit with a CS entry
- */
- if (!(is_data && *is_cs))
- {
- bucket->hb_entries[i].locks++;
- }
- found_p = TRUE;
- ret = HICN_ERROR_NONE;
- goto done;
- }
- }
-
- /*
- * Be prepared to continue to an overflow bucket if necessary. We
- * only expect the last entry in a bucket to refer to an overflow
- * bucket...
- */
- i = HICN_HASHTB_BUCKET_ENTRIES - 1;
- if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW)
- {
- current_bucket_id = bucket->hb_entries[i].he_node;
- bucket = pool_elt_at_index (h->ht_overflow_buckets,
- bucket->hb_entries[i].he_node);
- *bucket_is_overflow = 1;
- goto loop_buckets;
- }
-done:
-
- return (ret);
-}
-
-/**
- * This function allows to split the hash verification from the comparison of
- * the entire key. Useful to exploit prefertching.
- * return 1 if equals, 0 otherwise
- */
-int
-hicn_node_compare (const u8 *key, u32 keylen, hicn_hash_node_t *node)
-{
-
- int ret = 0;
-
- if (key && keylen == node->hn_keysize)
- {
- ret = (memcmp (key, node->hn_key.ks.key, keylen) == 0);
- }
- return ret;
-}
-
-/*
- * Utility to init a new entry in a hashtable bucket/row. We use this to add
- * new a node+hash, and to clear out an entry during removal.
- */
-void
-hicn_hashtb_init_entry (hicn_hash_entry_t *entry, u32 nodeidx, u64 hashval,
- u32 locks)
-{
- entry->he_msb64 = hashval;
- entry->he_node = nodeidx;
-
- /* Clear out some other fields in the entry */
- entry->he_flags = 0;
- entry->locks = locks;
- entry->vft_id = 0;
- entry->dpo_ctx_id = 0;
-}
-
-/*
- * Insert a node into the hashtable. We expect the caller has a) computed the
- * hash value to use, b) initialized the node with the hash and key info, and
- * c) filled in its app-specific data portion of the node.
- */
-
-int
-hicn_hashtb_insert (hicn_hashtb_h h, hicn_hash_node_t *node,
- hicn_hash_entry_t **hash_entry, u64 hash, 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)
-{
- int i, ret = HICN_ERROR_HASHTB_INVAL;
- u32 bidx;
- hicn_hash_bucket_t *bucket, *newbkt;
- int use_seven;
- u32 current_bucket_id = ~0;
- int is_overflow = 0;
-
- *hash_entry = NULL;
-
- if (h == NULL)
- {
- goto done;
- }
- /*
- * Use some bits of the low half of the hash to locate a row/bucket
- * in the table
- */
- current_bucket_id = bidx = (hash & (h->ht_bucket_count - 1));
-
- bucket = h->ht_buckets + bidx;
-
- use_seven = (h->ht_flags & HICN_HASHTB_FLAG_USE_SEVEN);
-
- /* Locate a free entry slot in the bucket */
-
-loop_buckets:
-
- for (i = 0; i < HICN_HASHTB_BUCKET_ENTRIES; i++)
- {
-
- /*
- * If an entry is marked for deletion, ignore it
- */
- if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_DELETED)
- {
- continue;
- }
- /*
- * Be sure that we are not inserting the same entry twice
- */
- if (bucket->hb_entries[i].he_msb64 == hash)
- {
- /*
- * We hit an existing pit entry. increase lock.
- */
-
- *node_id = bucket->hb_entries[i].he_node;
- *dpo_ctx_id = bucket->hb_entries[i].dpo_ctx_id;
- *vft_id = bucket->hb_entries[i].vft_id;
- *is_cs =
- bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY;
- *hash_entry_id = i;
- *bucket_id = current_bucket_id;
- *hash_entry = &(bucket->hb_entries[i]);
- /*
- * If we are doing lookup for a data, do not take a
- * lock in case of a hit with a CS entry
- */
- if (!(*is_cs))
- bucket->hb_entries[i].locks++;
- *bucket_is_overflow = is_overflow;
- ret = HICN_ERROR_HASHTB_EXIST;
- goto done;
- }
- if ((bucket->hb_entries[i].he_msb64 == 0LL) &&
- (bucket->hb_entries[i].he_node == 0))
- {
- /* Found a candidate -- fill it in */
-
- /*
- * Special case if the application asked not to use
- * the last entry in each bucket.
- */
- if ((i != (HICN_HASHTB_BUCKET_ENTRIES - 1)) || use_seven)
- {
- hicn_hashtb_init_entry (&(bucket->hb_entries[i]),
- NODE_IDX_FROM_NODE (node, h), hash, 0);
-
- *hash_entry = &(bucket->hb_entries[i]);
-
- node->bucket_id = current_bucket_id;
- node->entry_idx = i;
- (*hash_entry)->vft_id = *vft_id;
- (*hash_entry)->dpo_ctx_id = *dpo_ctx_id;
- if (is_overflow)
- node->hn_flags |= HICN_HASH_NODE_OVERFLOW_BUCKET;
-
- ret = HICN_ERROR_NONE;
- goto done;
- }
- }
- }
- /*
- * Be prepared to continue to an overflow bucket if necessary, or to
- * add a new overflow bucket. We only expect the last entry in a
- * bucket to refer to an overflow bucket...
- */
- i = HICN_HASHTB_BUCKET_ENTRIES - 1;
- if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW)
- {
- /* Existing overflow bucket - re-start the search loop */
- current_bucket_id = bucket->hb_entries[i].he_node;
- bucket = pool_elt_at_index (h->ht_overflow_buckets, current_bucket_id);
- is_overflow = 1;
- goto loop_buckets;
- }
- else
- {
- /*
- * Overflow - reached the end of a bucket without finding a
- * free entry slot. Need to allocate an overflow bucket, and
- * connect it to this bucket.
- */
- newbkt = alloc_overflow_bucket (h);
- if (newbkt == NULL)
- {
- ret = HICN_ERROR_HASHTB_NOMEM;
- goto done;
- }
- /*
- * We're touching some more bytes than we absolutely have to
- * here, but ... that seems ok.
- */
- memset (newbkt, 0, sizeof (hicn_hash_bucket_t));
-
- if (use_seven)
- {
- /*
- * Copy existing entry into new bucket - we really
- * expect these to be properly aligned so they can be
- * treated as int.
- */
- memcpy (&(newbkt->hb_entries[0]), &(bucket->hb_entries[i]),
- sizeof (hicn_hash_entry_t));
-
- /* Update bucket id and entry_idx on the hash node */
- hicn_hash_node_t *node =
- pool_elt_at_index (h->ht_nodes, newbkt->hb_entries[0].he_node);
- node->bucket_id = (newbkt - h->ht_overflow_buckets);
- node->entry_idx = 0;
- node->hn_flags |= HICN_HASH_NODE_OVERFLOW_BUCKET;
- }
- /*
- * Connect original bucket to the index of the new overflow
- * bucket
- */
- bucket->hb_entries[i].he_flags |= HICN_HASH_ENTRY_FLAG_OVERFLOW;
- bucket->hb_entries[i].he_node = (newbkt - h->ht_overflow_buckets);
-
- /* Add new entry to new overflow bucket */
- bucket = newbkt;
-
- /*
- * Use entry [1] in the new bucket _if_ we just copied into
- * entry [zero] above.
- */
- if (use_seven)
- {
-
- hicn_hashtb_init_entry (&(bucket->hb_entries[1]),
- NODE_IDX_FROM_NODE (node, h), hash, 0);
- *hash_entry = &(bucket->hb_entries[1]);
-
- node->bucket_id = (newbkt - h->ht_overflow_buckets);
- node->entry_idx = 1;
- node->hn_flags |= HICN_HASH_NODE_OVERFLOW_BUCKET;
- (*hash_entry)->vft_id = *vft_id;
- (*hash_entry)->dpo_ctx_id = *dpo_ctx_id;
- }
- else
- {
-
- hicn_hashtb_init_entry (&(bucket->hb_entries[0]),
- NODE_IDX_FROM_NODE (node, h), hash, 0);
- *hash_entry = &(bucket->hb_entries[0]);
- node->bucket_id = (newbkt - h->ht_overflow_buckets);
- node->entry_idx = 0;
- node->hn_flags |= HICN_HASH_NODE_OVERFLOW_BUCKET;
- (*hash_entry)->vft_id = *vft_id;
- (*hash_entry)->dpo_ctx_id = *dpo_ctx_id;
- }
- }
-
- /* And we're done with the overflow bucket */
- ret = HICN_ERROR_NONE;
-
-done:
-
- return (ret);
-}
-
-/*
- * Delete a node from a hashtable using the node itself, and delete/free the
- * node. Caller's pointer is cleared on success.
- */
-void
-hicn_hashtb_delete (hicn_hashtb_h h, hicn_hash_node_t **pnode, u64 hashval)
-{
-
- hicn_hashtb_remove_node (h, *pnode, hashval);
- hicn_hashtb_free_node (h, *pnode);
- *pnode = NULL;
-}
-
-/*
- * Delete an entry from a hashtable using the node itself. If the node was
- * stored in an overflow bucket, and the bucket is empty after freeing the
- * node, the bucket is freed as well.
- */
-void
-hicn_hashtb_remove_node (hicn_hashtb_h h, hicn_hash_node_t *node, u64 hashval)
-{
- int i, count;
- u32 bidx, overflow_p;
- hicn_hash_bucket_t *bucket, *parent;
-
- if ((h == NULL) || (node == NULL))
- {
- goto done;
- }
- if (node->hn_flags & HICN_HASH_NODE_OVERFLOW_BUCKET)
- bucket = pool_elt_at_index (h->ht_overflow_buckets, node->bucket_id);
- else
- {
- /*
- * Use some bits of the low half of the hash to locate a
- * row/bucket in the table
- */
- bidx = (hashval & (h->ht_bucket_count - 1));
- ASSERT (bidx == node->bucket_id);
- bucket = h->ht_buckets + node->bucket_id;
- }
-
- overflow_p = node->hn_flags & HICN_HASH_NODE_OVERFLOW_BUCKET;
-
- /* Clear out the entry. */
- hicn_hashtb_init_entry (&(bucket->hb_entries[node->entry_idx]), 0, 0LL, 0);
-
- if (!overflow_p)
- {
- /*
- * And we're done, in the easy case where we didn't change an
- * overflow bucket
- */
- goto done;
- }
- /*
- * The special case: if this is the last remaining entry in an
- * overflow bucket, liberate the bucket. That in turn has a special
- * case if this bucket is in the middle of a chain of overflow
- * buckets.
- *
- * Note that we're not trying aggressively (yet) to condense buckets at
- * every possible opportunity.
- */
-
- /*
- * Reset this flag; we'll set it again if this bucket links to
- * another
- */
- overflow_p = FALSE;
-
- for (i = 0, count = 0; i < HICN_HASHTB_BUCKET_ENTRIES; i++)
- {
- if (bucket->hb_entries[i].he_node != 0)
- {
- count++;
- }
- if (i == (HICN_HASHTB_BUCKET_ENTRIES - 1) &&
- (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW))
- {
- count--; /* Doesn't count as a 'real' entry */
- overflow_p = TRUE;
- }
- }
-
- if (count > 0)
- {
- /* Still a (real) entry in the row */
- goto done;
- }
- /*
- * Need to locate the predecessor of 'bucket': start at the beginning
- * of the chain of buckets and move forward
- */
- bidx = (hashval & (h->ht_bucket_count - 1));
-
- for (parent = h->ht_buckets + bidx; parent != NULL;)
- {
-
- if ((parent->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)].he_flags &
- HICN_HASH_ENTRY_FLAG_OVERFLOW) == 0)
- {
- parent = NULL;
- break;
- }
- bidx = parent->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)].he_node;
-
- if (pool_elt_at_index (h->ht_overflow_buckets, bidx) == bucket)
- {
- /*
- * Found the predecessor of 'bucket'. If 'bucket' has
- * a successor, connect 'parent' to it, and take
- * 'bucket out of the middle.
- */
- if (overflow_p)
- {
- parent->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)].he_node =
- bucket->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)].he_node;
- }
- else
- {
- /*
- * Just clear the predecessor entry pointing
- * at 'bucket'
- */
- hicn_hashtb_init_entry (
- &parent->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)], 0, 0LL,
- 0);
- }
-
- break;
- }
- /*
- * After the first iteration, 'parent' will be an overflow
- * bucket too
- */
- parent = pool_elt_at_index (h->ht_overflow_buckets, bidx);
- }
-
- /* We really expect to have found the predecessor */
- ASSERT (parent != NULL);
-
- /* And now, finally, we can put 'bucket' back on the free list */
- free_overflow_bucket (h, &bucket);
-
-done:
- return;
-}
-
-/*
- * Prepare a hashtable node, supplying the key, and computed hash info.
- */
-void
-hicn_hashtb_init_node (hicn_hashtb_h h, hicn_hash_node_t *node, const u8 *key,
- u32 keylen)
-{
- assert (h != NULL);
- assert (node != NULL);
- assert (keylen <= HICN_PARAM_HICN_NAME_LEN_MAX);
-
- /* Init the node struct */
- node->hn_flags = HICN_HASH_NODE_FLAGS_DEFAULT;
- node->hn_keysize = 0;
- node->hn_keysize = keylen;
- memcpy (node->hn_key.ks.key, key, keylen);
- node->bucket_id = ~0;
- node->entry_idx = ~0;
-}
-
-/*
- * Release a hashtable node back to the free list when an entry is cleared
- */
-void
-hicn_hashtb_free_node (hicn_hashtb_h h, hicn_hash_node_t *node)
-{
- ASSERT (h->ht_nodes_used > 0);
-
- /* Return 'node' to the free list */
- pool_put (h->ht_nodes, node);
- h->ht_nodes_used--;
-}
-
-/*
- * Walk a hashtable, iterating through the nodes, keeping context in 'ctx'.
- */
-int
-hicn_hashtb_next_node (hicn_hashtb_h h, hicn_hash_node_t **pnode, u64 *ctx)
-{
- int i, j, ret = HICN_ERROR_HASHTB_INVAL;
- u32 bidx, entry;
- hicn_hash_bucket_t *bucket;
-
- if ((h == NULL) || (pnode == NULL) || (ctx == NULL))
- {
- goto done;
- }
- /* Special-case for new iteration */
- if (*ctx == HICN_HASH_WALK_CTX_INITIAL)
- {
- bidx = 0;
- bucket = &h->ht_buckets[0];
- entry = 0;
- j = 0;
- i = 0;
- goto search_table;
- }
- /* Convert context to bucket and entry indices */
- bidx = *ctx & 0xffffffffLL;
- entry = *ctx >> 32;
-
- if (bidx >= h->ht_bucket_count)
- {
- ret = HICN_ERROR_HASHTB_HASH_NOT_FOUND;
- goto done;
- }
- bucket = h->ht_buckets + bidx;
-
- /* Init total index into entries (includes fixed bucket and overflow) */
- j = 0;
-
-skip_processed_bucket_chunks:
- /*
- * Figure out where to resume the search for the next entry in the
- * table, by trying to find the last entry returned, from the cookie.
- * Loop walks one (regular or overflow) bucket chunk, label is used
- * for walking chain of chunks. Note that if there was a deletion or
- * an addition that created an overflow, iterator can skip entries or
- * return duplicate entries, for entries that are present from before
- * the walk starts until after it ends.
- */
-
- for (i = 0; i < HICN_HASHTB_BUCKET_ENTRIES; i++, j++)
- {
- if (j > entry)
- {
- /*
- * Start search for next here, use existing 'bucket'
- * and 'i'
- */
- break;
- }
- /*
- * If an entry is marked for deletion, ignore it
- */
- if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_DELETED)
- {
- continue;
- }
- /*
- * Be prepared to continue to an overflow bucket if
- * necessary. (We only expect the last entry in a bucket to
- * refer to an overflow bucket...)
- */
- if (i == (HICN_HASHTB_BUCKET_ENTRIES - 1))
- {
- if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW)
- {
- bucket = pool_elt_at_index (h->ht_overflow_buckets,
- bucket->hb_entries[i].he_node);
-
- /* Increment overall entry counter 'j' */
- j++;
-
- goto skip_processed_bucket_chunks;
- }
- /*
- * end of row (end of fixed bucket plus any
- * overflows)
- */
- i = 0;
- j = 0;
-
- bidx++;
-
- /* Special case - we're at the end */
- if (bidx >= h->ht_bucket_count)
- {
- ret = HICN_ERROR_HASHTB_HASH_NOT_FOUND;
- goto done;
- }
- bucket = h->ht_buckets + bidx;
- break;
- }
- }
-
-search_table:
-
- /*
- * Now we're searching through the table for the next entry that's
- * set
- */
-
- for (; i < HICN_HASHTB_BUCKET_ENTRIES; i++, j++)
- {
- /*
- * If an entry is marked for deletion, ignore it
- */
- if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_DELETED)
- {
- continue;
- }
- /* Is this entry set? */
- if (bucket->hb_entries[i].he_node != 0)
- {
-
- /* Retrieve the node struct */
- *pnode =
- pool_elt_at_index (h->ht_nodes, bucket->hb_entries[i].he_node);
-
- /*
- * Set 'entry' as we exit, so we can update the
- * cookie
- */
- entry = j;
- ret = HICN_ERROR_NONE;
- break;
- }
- /*
- * Be prepared to continue to an overflow bucket if
- * necessary. (We only expect the last entry in a bucket to
- * refer to an overflow bucket...)
- */
- if (i == (HICN_HASHTB_BUCKET_ENTRIES - 1))
- {
- if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW)
- {
- bucket = pool_elt_at_index (h->ht_overflow_buckets,
- bucket->hb_entries[i].he_node);
- /*
- * Reset per-bucket index 'i', here (not done
- * in iterator)
- */
- i = 0;
- /* Increment overall entry counter 'j' */
- j++;
-
- goto search_table;
- }
- else
- {
- /*
- * Move to next bucket, resetting per-bucket
- * and overall entry indexes
- */
- i = 0;
- j = 0;
-
- bidx++;
-
- /* Special case - we're at the end */
- if (bidx >= h->ht_bucket_count)
- {
- ret = HICN_ERROR_HASHTB_HASH_NOT_FOUND;
- goto done;
- }
- bucket = h->ht_buckets + bidx;
- goto search_table;
- }
- }
- }
-
-done:
-
- if (ret == HICN_ERROR_NONE)
- {
- /* Update context */
- *ctx = bidx;
- *ctx |= ((u64) entry << 32);
- }
- return (ret);
-}
-
-int
-hicn_hashtb_key_to_buf (u8 **vec_res, hicn_hashtb_h h,
- const hicn_hash_node_t *node)
-{
- int ret = HICN_ERROR_NONE;
- u8 *vec = *vec_res;
-
- if (node->hn_keysize <= HICN_HASH_KEY_BYTES)
- {
- vec_add (vec, node->hn_key.ks.key, node->hn_keysize);
- }
- *vec_res = vec;
- return (ret);
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables: eval: (c-set-style "gnu") End:
- */
diff --git a/hicn-plugin/src/hashtb.h b/hicn-plugin/src/hashtb.h
deleted file mode 100644
index 4b787e2d7..000000000
--- a/hicn-plugin/src/hashtb.h
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef __HICN_HASHTB_H__
-#define __HICN_HASHTB_H__
-
-#include <stdint.h>
-#include <vppinfra/bihash_8_8.h>
-#include <vppinfra/bihash_24_8.h>
-
-#include "params.h"
-#include "parser.h"
-#include "error.h"
-
-/**
- * @file hashtb.h
- * Lookup is finding a hashtable record whose name matches the name being
- * looked up. Most of the lookup work is based on the hash value of the two
- * names. Note that the intel cache line size is 64 bytes, and some platforms
- * load in 2 cache lines together.
- * - first step is to match a record at the bucket/slot level (htab has an
- * array of htbucket_t/htbc_elmt, where each bucket has 7 slots to hold
- * indices for entries.) Matching at this level implies
- * - the hashes of the lookup name and the record map to the same bucket
- * - the high 32 bits of the hashes (slot bce_hash_msb32s) match. Read
- * cost (on the hash table size, i.e. ignoring reading the name being
- * looked up):
- * - First step normally requires 1 cache line load to pull in the
- * 64-byte htbucket_t with the 7 element slot table holding the
- * hash_msb32s.
- * - In the event (hopefully rare for a hash table with appropriate
- * number of buckets) that more than 7 elements hash to the same bucket,
- * lookup may well need to look not only at the static htbc_elmt_t but at
- * the chain of dynamically allocated htbc_elmt_t's linked to the static
- * htbc_elmt_t, where each of these holds slot entries for additional
- * elements.
- * - Before reaching that point, it is initially required to read in the
- * hash table record fields (ht_bucket_buf, htnode buf, etc) holding
- * pointers to the arrays, but these cache lines are common to all
- * lookups so will likely already be in the cache.
- * - second step is to match at the record level (htnode/htkb level) once a
- * slot-level match happens. Matching at this level implies the following
- * match
- * - the hash values (the full 64 bits vs. bucket+32 msb, above).
- * - the name which, on the hash table side, is stored as a list of htkb_t
- * (key buffers).
- *
- * Some hashtables (for which rare false positives are tolerable) store hash
- * values but no keys. (In ISM NDN forwarder, this was used for dcm_dpf: data
- * cache manager's dataplane filter, where speed was critical and very rare
- * false positives would be detected in the full dcm check.) - No key buffers
- * are used (or even allocated at hash table creation).
- */
-
-/* Handy abbreviations for success status, and for boolean values */
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#define HICN_HASH_INVALID_IDX ~0
-/*
- * for hicn_hashtb_next_node() iterator, this otherwise illegal context value
- * indicates first call of iteration. Note: must not be 0, which is a legal
- * context value.
- */
-#define HICN_HASH_WALK_CTX_INITIAL (~((u64) 0))
-
-/*
- * Key memory allocation scheme.
- *
- * The key is the bytestring that a hashtable entry is storing, e.g. a fib
- * prefix or packet name. The hash of the name is used not just to pick the
- * bucket, but also as a surrogate for the actual key value.
- *
- * Client calls pass key/name as contiguous memory for lookup/add/delete but
- * hashable stores its copy of the key/name as a list of one or more hash_key
- * structs. - key memory is managed as a list of keys (cache line
- * sized/aligned buffers). - If (keysize < 128) then use key struct's full
- * 128 bytes - If not, first key struct is head of a linked list of elements
- * where the first bytes are used for the key and the last 4 bytes are the
- * index of the next entry (or an end marker). - key memory is generally the
- * single largest use of memory in the hash table, especially for PIT, as
- * names are bigger than node structs (which is also per name/entry).
- *
- */
-
-/* Compute hash node index from node pointer */
-#define NODE_IDX_FROM_NODE(p, h) (u32) ((p) - ((h)->ht_nodes))
-
-#define HICN_HASH_KEY_BYTES 20
-
-typedef struct
-{
- struct
- {
- u8 key[HICN_HASH_KEY_BYTES];
- } ks; /* Entire key in one block */
-} hicn_hash_key_t;
-
-/*
- * Ratio of extra key blocks to allocate, in case the embedded ones aren't
- * sufficient. This is the fraction of the number of entries allocated.
- */
-#define HICN_HASHTB_KEY_RATIO 8
-
-/*
- * hash node, used to store a hash table entry; indexed by an entry in a
- * bucket. the node contains an embedded key; long keys are stored as chains
- * of keys.
- *
- * The memory block for a node includes space for storing outgoing faces for
- * interests, additional memory located off the end of the htnode data
- * structure.
- *
- */
-
-/* Size this so that we can offer 64B aligned on 64-bits for storing outgoing
- * faces information
- */
-#define HICN_HASH_NODE_APP_DATA_SIZE 64
-
-/* How to align in the right way */
-typedef struct __attribute__ ((packed)) hicn_hash_node_s
-{
- /* Bucket id containing the corresponding hash entry. */
- u32 bucket_id;
-
- /* Hash entry index in the bucket */
- u32 entry_idx;
-
- /* Total size of the key */
- u16 hn_keysize;
-
- /* 1 byte of flags for application use */
- u8 hn_flags;
-
- u8 _hn_reserved1; /* TBD, to align what follows back to
- * 32 */
-
- hicn_hash_key_t hn_key; /* Key value embedded in the node, may chain
- * to more key buffers if necessary */
-
- /* 32B + HICN_HASH_NODE_APP_DATA_SIZE */
- /* Followed by app-specific data (fib or pit or cs entry, e.g.) */
- u8 hn_data[HICN_HASH_NODE_APP_DATA_SIZE];
-
-} hicn_hash_node_t;
-
-#define HICN_HASH_NODE_FLAGS_DEFAULT 0x00
-#define HICN_HASH_NODE_CS_FLAGS 0x01
-#define HICN_HASH_NODE_OVERFLOW_BUCKET 0x02
-
-/*
- * hicn_hash_entry_t Structure holding all or part of a hash value, a node
- * index, and other key pieces of info.
- *
- * - 128 bytes/bucket with 19 bytes/entry gives 6 entries, or 5 entries plus
- * next bucket ptr if overflow Changes in this structure will affect
- * hicn_hash_bucket_t
- */
-typedef struct __attribute__ ((packed)) hicn_hash_entry_s
-{
-
- /* MSB of the hash value */
- u64 he_msb64;
-
- /* Index of node block */
- u32 he_node;
-
- /*
- * Lock to prevent hash_node deletion while there are still interest
- * or data referring to it
- */
- u32 locks;
-
- /* Index of dpo (4B) */
- index_t dpo_ctx_id;
-
- /* A few flags, including 'this points to a chain of buckets' */
- u8 he_flags;
-
- /*
- * Index of the virtual function table corresponding to the dpo_ctx
- * strategy
- */
- u8 vft_id;
-
-} hicn_hash_entry_t; // size 22B
-
-STATIC_ASSERT (sizeof (index_t) <= 4, "sizeof index_t is greater than 4B");
-
-#define HICN_HASH_ENTRY_FLAGS_DEFAULT 0x00
-
-/* If entry is PIT this flag is 0 */
-#define HICN_HASH_ENTRY_FLAG_CS_ENTRY 0x01
-
-/*
- * This entry heads a chain of overflow buckets (we expect to see this only
- * in the last entry in a bucket.) In this case, the index is to an overflow
- * bucket rather than to a single node block.
- */
-#define HICN_HASH_ENTRY_FLAG_OVERFLOW 0x04
-
-/* This entry has been marked for deletion */
-#define HICN_HASH_ENTRY_FLAG_DELETED 0x08
-
-/* Use fast he_timeout units for expiration, slow if not */
-#define HICN_HASH_ENTRY_FLAG_FAST_TIMEOUT 0x10
-
-/*
- * hash bucket: Contains an array of entries. Cache line sized/aligned, so no
- * room for extra fields unless bucket size is increased to 2 cache lines or
- * the entry struct shrinks.
- */
-
-/*
- * Overflow bucket ratio as a fraction of the fixed/configured count; a pool
- * of hash buckets used if a row in the fixed table overflows.
- */
-#define HICN_HASHTB_BUCKET_ENTRIES 5
-
-typedef struct __attribute__ ((packed))
-{
- hicn_hash_entry_t hb_entries[HICN_HASHTB_BUCKET_ENTRIES];
- u64 align1;
- u64 align2;
- u16 align3;
-} hicn_hash_bucket_t;
-
-/* Overall target fill-factor for the hashtable */
-#define HICN_HASHTB_FILL_FACTOR 4
-
-#define HICN_HASHTB_MIN_ENTRIES (1 << 4) // includes dummy node 0 entry
-#define HICN_HASHTB_MAX_ENTRIES (1 << 24)
-
-#define HICN_HASHTB_MIN_BUCKETS (1 << 10)
-
-/*
- * htab_t
- *
- * Hash table main structure.
- *
- * Contains - pointers to dynamically allocated arrays of cache-line
- * sized/aligned structures (buckets, nodes, keys). Put frequently accessed
- * fields in the first cache line.
- */
-typedef struct hicn_hashtb_s
-{
-
- /* 8B - main array of hash buckets */
- hicn_hash_bucket_t *ht_buckets;
-
- /* 8B - just-in-case block of overflow buckets */
- hicn_hash_bucket_t *ht_overflow_buckets;
-
- /* 8B - block of nodes associated with entries in buckets */
- hicn_hash_node_t *ht_nodes;
-
- /* Flags */
- u32 ht_flags;
-
- /* Count of buckets allocated in the main array */
- u32 ht_bucket_count;
-
- /* Count of overflow buckets allocated */
- u32 ht_overflow_bucket_count;
- u32 ht_overflow_buckets_used;
-
- /* Count of nodes allocated */
- u32 ht_node_count;
- u32 ht_nodes_used;
-
- /* Count of overflow key structs allocated */
- u32 ht_key_count;
- u32 ht_keys_used;
-
-} hicn_hashtb_t, *hicn_hashtb_h;
-
-/*
- * Offset to aligned start of additional data (PIT/CS, FIB) embedded in each
- * node.
- */
-extern u32 ht_node_data_offset_aligned;
-
-/* Flags for hashtable */
-
-#define HICN_HASHTB_FLAGS_DEFAULT 0x00
-
-/*
- * Don't use the last entry in each bucket - only use it for overflow. We use
- * this for the FIB, currently, so that we can support in-place FIB changes
- * that would be difficult if there were hash entry copies as part of
- * overflow handling.
- */
-#define HICN_HASHTB_FLAG_USE_SEVEN 0x04
-#define HICN_HASHTB_FLAG_KEY_FMT_PFX 0x08
-#define HICN_HASHTB_FLAG_KEY_FMT_NAME 0x10
-
-/*
- * Max prefix name components we'll support in our incremental hashing;
- * currently used only for LPM in the FIB.
- */
-#define HICN_HASHTB_MAX_NAME_COMPS HICN_PARAM_FIB_ENTRY_PFX_COMPS_MAX
-
-/*
- * APIs and inlines
- */
-
-/* Compute hash node index from node pointer */
-static inline u32
-hicn_hashtb_node_idx_from_node (hicn_hashtb_h h, hicn_hash_node_t *p)
-{
- return (p - h->ht_nodes);
-}
-
-/* Retrieve a hashtable node by node index */
-static inline hicn_hash_node_t *
-hicn_hashtb_node_from_idx (hicn_hashtb_h h, u32 idx)
-{
- return (pool_elt_at_index (h->ht_nodes, idx));
-}
-
-/* Allocate a brand-new hashtable */
-int hicn_hashtb_alloc (hicn_hashtb_h *ph, u32 max_elems, size_t app_data_size);
-
-/* Free a hashtable, including its embedded arrays */
-int hicn_hashtb_free (hicn_hashtb_h *ph);
-
-/* Hash a bytestring, currently using bihash */
-u64 hicn_hashtb_hash_bytestring (const u8 *key, u32 keylen);
-
-always_inline hicn_hash_entry_t *
-hicn_hashtb_get_entry (hicn_hashtb_h h, u32 entry_idx, u32 bucket_id,
- u8 bucket_overflow)
-{
- hicn_hash_bucket_t *bucket;
- if (bucket_overflow)
- bucket = pool_elt_at_index (h->ht_overflow_buckets, bucket_id);
- else
- bucket = (hicn_hash_bucket_t *) (h->ht_buckets + bucket_id);
-
- return &(bucket->hb_entries[entry_idx]);
-}
-
-/* Hash a name, currently using bihash */
-always_inline u64
-hicn_hashtb_hash_name (const u8 *key, u16 keylen)
-{
- if (key != NULL && keylen == HICN_V4_NAME_LEN)
- {
- clib_bihash_kv_8_8_t kv;
- kv.key = ((u64 *) key)[0];
- return clib_bihash_hash_8_8 (&kv);
- }
- else if (key != NULL && keylen == HICN_V6_NAME_LEN)
- {
- clib_bihash_kv_24_8_t kv;
- kv.key[0] = ((u64 *) key)[0];
- kv.key[1] = ((u64 *) key)[1];
- kv.key[2] = ((u32 *) key)[4];
- return clib_bihash_hash_24_8 (&kv);
- }
- else
- {
- return (-1LL);
- }
-}
-
-/*
- * Prepare a hashtable node for insertion, supplying the key and computed
- * hash info. This sets up the node->key relationship, possibly allocating
- * overflow key buffers.
- */
-void hicn_hashtb_init_node (hicn_hashtb_h h, hicn_hash_node_t *node,
- const u8 *key, u32 keylen);
-
-/*
- * Insert a node into the hashtable. We expect the caller has used the init
- * api to set the node key and hash info, and populated the extra data area
- * (if any) - or done the equivalent work itself.
- */
-int hicn_hashtb_insert (hicn_hashtb_h h, hicn_hash_node_t *node,
- hicn_hash_entry_t **hash_entry, u64 hash, 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);
-
-/*
- * Basic api to lookup a specific hash+key tuple. This does the entire lookup
- * operation, retrieving node structs and comparing keys, so it's not
- * optimized for prefetching or high performance.
- *
- * Returns zero and mails back a node on success, errno otherwise.
- */
-int hicn_hashtb_lookup_node (hicn_hashtb_h h, const u8 *key, u32 keylen,
- u64 hashval, u8 is_data, 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);
-
-/*
- * Extended api to lookup a specific hash+key tuple. The implementation
- * allows the caller to locate nodes that are marked for deletion; this is
- * part of some hashtable applications, such as the FIB.
- *
- * This does the entire lookup operation, retrieving node structs and comparing
- * keys, so it's not optimized for prefetching or high performance.
- *
- * Returns zero and mails back a node on success, errno otherwise.
- */
-int hicn_hashtb_lookup_node_ex (hicn_hashtb_h h, const u8 *key, u32 keylen,
- u64 hashval, u8 is_data, int include_deleted_p,
- 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);
-
-/**
- * @brief Compares the key in the node with the given key
- *
- * This function allows to split the hash verification from the comparison of
- * the entire key. Useful to exploit prefertching.
- * @result 1 if equals, 0 otherwise
- */
-int hicn_node_compare (const u8 *key, u32 keylen, hicn_hash_node_t *node);
-
-/*
- * Remove a node from a hashtable using the node itself. The internal data
- * structs are cleaned up, but the node struct itself is not: the caller must
- * free the node itself.
- */
-void hicn_hashtb_remove_node (hicn_hashtb_h h, hicn_hash_node_t *node,
- u64 hashval);
-
-/*
- * Delete a node from a hashtable using the node itself, and delete/free the
- * node. Caller's pointer is cleared on success.
- */
-void hicn_hashtb_delete (hicn_hashtb_h h, hicn_hash_node_t **pnode,
- u64 hashval);
-
-/*
- * Utility to init a new entry in a hashtable bucket/row. We use this to add
- * new a node+hash, and to clear out an entry during removal.
- */
-void hicn_hashtb_init_entry (hicn_hash_entry_t *entry, u32 nodeidx,
- u64 hashval, u32 locks);
-
-/*
- * Return data area embedded in a hash node struct. We maintain an 'offset'
- * value in case the common node body struct doesn't leave the data area
- * aligned properly.
- */
-static inline void *
-hicn_hashtb_node_data (hicn_hash_node_t *node)
-{
- return ((u8 *) (node) + ht_node_data_offset_aligned);
-}
-
-/*
- * Use some bits of the low half of the hash to locate a row/bucket in the
- * table
- */
-static inline u32
-hicn_hashtb_bucket_idx (hicn_hashtb_h h, u64 hashval)
-{
- return ((u32) (hashval & (h->ht_bucket_count - 1)));
-}
-
-/*
- * Return a hash node struct from the free list, or NULL. Note that the
- * returned struct is _not_ cleared/zeroed - init is up to the caller.
- */
-static inline hicn_hash_node_t *
-hicn_hashtb_alloc_node (hicn_hashtb_h h)
-{
- hicn_hash_node_t *p = NULL;
-
- if (h->ht_nodes_used < h->ht_node_count)
- {
- pool_get_aligned (h->ht_nodes, p, 8);
- h->ht_nodes_used++;
- }
- return (p);
-}
-
-/*
- * Release a hashtable node back to the free list when an entry is cleared
- */
-void hicn_hashtb_free_node (hicn_hashtb_h h, hicn_hash_node_t *node);
-
-/*
- * Walk a hashtable, iterating through the nodes, keeping context in 'ctx'
- * between calls.
- *
- * Set the context value to HICN_HASH_WALK_CTX_INITIAL to start an iteration.
- */
-int hicn_hashtb_next_node (hicn_hashtb_h h, hicn_hash_node_t **pnode,
- u64 *ctx);
-
-int hicn_hashtb_key_to_str (hicn_hashtb_h h, const hicn_hash_node_t *node,
- char *buf, int bufsize, int must_fit);
-
-/*
- * single hash full name can pass offset for two hashes calculation in case
- * we use CS and PIT in a two steps hashes (prefix + seqno)
- */
-always_inline int
-hicn_hashtb_fullhash (const u8 *name, u16 namelen, u64 *name_hash)
-{
- *name_hash = hicn_hashtb_hash_name (name, namelen);
- return (*name_hash != (-1LL) ? HICN_ERROR_NONE : HICN_ERROR_HASHTB_INVAL);
-}
-
-#endif /* // __HICN_HASHTB_H__ */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables: eval: (c-set-style "gnu") End:
- */
diff --git a/hicn-plugin/src/hicn.api b/hicn-plugin/src/hicn.api
index 44382c743..8c1c78eb0 100644
--- a/hicn-plugin/src/hicn.api
+++ b/hicn-plugin/src/hicn.api
@@ -463,6 +463,9 @@ define hicn_api_register_prod_app
/* CS memory reserved -- in number of packets */
u32 cs_reserved;
+
+ /* Port identifying producer application */
+ u16 port;
};
define hicn_api_register_prod_app_reply
@@ -505,6 +508,9 @@ define hicn_api_register_cons_app
/* swif */
u32 swif;
+
+ /* src port of consumer packet from this face */
+ u16 port;
};
define hicn_api_register_cons_app_reply
diff --git a/hicn-plugin/src/hicn.c b/hicn-plugin/src/hicn.c
index 1789f5407..d48ef4023 100644
--- a/hicn-plugin/src/hicn.c
+++ b/hicn-plugin/src/hicn.c
@@ -25,7 +25,6 @@
#include "mgmt.h"
#include "error.h"
#include "faces/app/address_mgr.h"
-#include "face_db.h"
#include "udp_tunnels/udp_tunnel.h"
#include "route.h"
#include "pg.h"
@@ -34,14 +33,7 @@ hicn_main_t hicn_main;
/* Module vars */
int hicn_infra_fwdr_initialized = 0;
-/*
- * Global time counters we're trying out for opportunistic hashtable
- * expiration.
- */
-uint16_t hicn_infra_fast_timer; /* Counts at 1 second intervals */
-uint16_t hicn_infra_slow_timer; /* Counts at 1 minute intervals */
-
-hicn_face_bucket_t *hicn_face_bucket_pool;
+// hicn_face_bucket_t *hicn_face_bucket_pool;
/*
* Init hicn forwarder with configurable PIT, CS sizes
@@ -49,29 +41,27 @@ hicn_face_bucket_t *hicn_face_bucket_pool;
static int
hicn_infra_fwdr_init (uint32_t shard_pit_size, uint32_t shard_cs_size)
{
- int ret = 0;
+ int ret = HICN_ERROR_NONE;
if (hicn_infra_fwdr_initialized)
{
ret = HICN_ERROR_FWD_ALREADY_ENABLED;
- goto done;
+ goto DONE;
}
+
/* Init per worker limits */
hicn_infra_pit_size = shard_pit_size;
hicn_infra_cs_size = shard_cs_size;
- /* Init the global time-compression counters */
- hicn_infra_fast_timer = 1;
- hicn_infra_slow_timer = 1;
+ hicn_pit_create (&hicn_main.pitcs, hicn_infra_pit_size, hicn_infra_cs_size);
- ret = hicn_pit_create (&hicn_main.pitcs, hicn_infra_pit_size);
- hicn_pit_set_lru_max (&hicn_main.pitcs, hicn_infra_cs_size);
-done:
+DONE:
if ((ret == HICN_ERROR_NONE) && !hicn_infra_fwdr_initialized)
{
hicn_infra_fwdr_initialized = 1;
}
- return (ret);
+
+ return ret;
}
/*
@@ -166,8 +156,6 @@ hicn_infra_plugin_enable_disable (int enable_disable, int pit_size_req,
ret = hicn_infra_fwdr_init (pit_size, cs_size);
- hicn_face_db_init (pit_size);
-
if (ret != HICN_ERROR_NONE)
{
goto done;
diff --git a/hicn-plugin/src/hicn.h b/hicn-plugin/src/hicn.h
index 22309e3e5..3b197d6b4 100644
--- a/hicn-plugin/src/hicn.h
+++ b/hicn-plugin/src/hicn.h
@@ -61,28 +61,24 @@ typedef u8 weight_t;
typedef struct
{
/**
- * Hash of the name (8)
+ * IDs to prefetch a PIT/CS entry (4)
*/
- u64 name_hash;
+ u32 pcs_entry_id;
/**
- * IDs to prefetch a PIT/CS entry (4+4+1+1)
+ * DPO/Stategy VFT ID. This is also the DPO type (4)
*/
- u32 node_id;
- u32 bucket_id;
- u8 hash_entry_id;
- u8 hash_bucket_flags;
+ dpo_type_t vft_id;
/**
- * hICN buffer flags (1)
+ * DPO context ID (4)
*/
- u8 flags;
+ u32 dpo_ctx_id;
/**
- * used for data path (1+1)
+ * hICN buffer flags (1)
*/
- u8 dpo_ctx_id;
- u8 vft_id;
+ u8 flags;
/**
* Ingress face (4)
@@ -95,6 +91,7 @@ typedef struct
hicn_type_t type;
hicn_name_t name;
u16 port;
+ hicn_lifetime_t lifetime;
} hicn_buffer_t;
STATIC_ASSERT (sizeof (hicn_buffer_t) <=
@@ -113,14 +110,10 @@ hicn_is_v6 (hicn_header_t *pkt_hdr)
return ((pkt_hdr->v4.ip.version_ihl >> 4) != 4);
}
-always_inline void
-hicn_buffer_get_name_and_namelen (vlib_buffer_t *b0, u8 **nameptr,
- u16 *namelen)
+always_inline hicn_name_t *
+hicn_buffer_get_name (vlib_buffer_t *b)
{
- *nameptr = (u8 *) (&hicn_get_buffer (b0)->name);
- *namelen = ip_address_is_v4 (&hicn_get_buffer (b0)->name.prefix) ?
- HICN_V4_NAME_LEN :
- HICN_V6_NAME_LEN;
+ return &hicn_get_buffer (b)->name;
}
always_inline u8
@@ -135,6 +128,13 @@ hicn_buffer_set_flags (vlib_buffer_t *b, u8 flags)
hicn_buffer_t *hb = hicn_get_buffer (b);
hb->flags |= flags;
}
+
+always_inline hicn_lifetime_t
+hicn_buffer_get_lifetime (vlib_buffer_t *b)
+{
+ return hicn_get_buffer (b)->lifetime;
+}
+
#endif /* __HICN_H__ */
/*
diff --git a/hicn-plugin/src/infra.h b/hicn-plugin/src/infra.h
index c942ad581..463617da0 100644
--- a/hicn-plugin/src/infra.h
+++ b/hicn-plugin/src/infra.h
@@ -46,7 +46,7 @@ typedef struct hicn_main_s
* Boundaries for the interest lifetime. If greater than
* pit_lifetime_max_ms, pit_lifetime_max_ms is used in the PIT
*/
- u64 pit_lifetime_max_ms;
+ u32 pit_lifetime_max_ms;
vnet_link_t link;
diff --git a/hicn-plugin/src/interest_hitcs_node.c b/hicn-plugin/src/interest_hitcs_node.c
index 1af21191c..651b2796a 100644
--- a/hicn-plugin/src/interest_hitcs_node.c
+++ b/hicn-plugin/src/interest_hitcs_node.c
@@ -36,13 +36,14 @@ static char *hicn_interest_hitcs_error_strings[] = {
vlib_node_registration_t hicn_interest_hitcs_node;
-always_inline void drop_packet (u32 *next0);
+// always_inline void drop_packet (u32 *next0);
-always_inline void
-clone_from_cs (vlib_main_t *vm, u32 *bi0_cs, vlib_buffer_t *dest, u8 isv6)
+always_inline u32
+clone_from_cs (vlib_main_t *vm, u32 bi0_cs, vlib_buffer_t *dest, u8 isv6)
{
/* Retrieve the buffer to clone */
- vlib_buffer_t *cs_buf = vlib_get_buffer (vm, *bi0_cs);
+ u32 ret = bi0_cs;
+ vlib_buffer_t *cs_buf = vlib_get_buffer (vm, bi0_cs);
hicn_buffer_t *hicnb = hicn_get_buffer (cs_buf);
word buffer_advance = CLIB_CACHE_LINE_BYTES * 2;
if (hicnb->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL)
@@ -63,7 +64,7 @@ clone_from_cs (vlib_main_t *vm, u32 *bi0_cs, vlib_buffer_t *dest, u8 isv6)
{
vlib_buffer_t *cs_buf2 = vlib_buffer_copy (vm, cs_buf);
vlib_buffer_advance (cs_buf, buffer_advance);
- *bi0_cs = vlib_get_buffer_index (vm, cs_buf2);
+ ret = vlib_get_buffer_index (vm, cs_buf2);
cs_buf->ref_count--;
cs_buf = cs_buf2;
}
@@ -79,6 +80,8 @@ clone_from_cs (vlib_main_t *vm, u32 *bi0_cs, vlib_buffer_t *dest, u8 isv6)
/* Set fag for packet coming from CS */
hicn_get_buffer (dest)->flags |= HICN_BUFFER_FLAGS_FROM_CS;
+
+ return ret;
}
static uword
@@ -89,6 +92,16 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hicn_interest_hitcs_next_t next_index;
hicn_interest_hitcs_runtime_t *rt;
vl_api_hicn_api_node_stats_get_reply_t stats = { 0 };
+ vlib_buffer_t *b0;
+ u8 isv6;
+ u32 bi0, bi_ret;
+ u32 next0 = HICN_INTEREST_HITCS_NEXT_ERROR_DROP;
+ hicn_buffer_t *hicnb0;
+ u32 pcs_entry_index;
+ hicn_pcs_entry_t *pcs_entry = NULL;
+ const hicn_strategy_vft_t *strategy_vft0;
+ const hicn_dpo_vft_t *dpo_vft0;
+ u8 dpo_ctx_id0;
f64 tnow;
rt = vlib_node_get_runtime_data (vm, hicn_interest_hitcs_node.index);
@@ -109,27 +122,12 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
while (n_left_from > 0 && n_left_to_next > 0)
{
- vlib_buffer_t *b0;
- u8 isv6;
- u8 *nameptr;
- u16 namelen;
- u32 bi0;
- u32 next0 = HICN_INTEREST_HITCS_NEXT_ERROR_DROP;
- hicn_buffer_t *hicnb0;
- hicn_hash_node_t *node0;
- hicn_pcs_entry_t *pitp;
- hicn_hash_entry_t *hash_entry0;
- const hicn_strategy_vft_t *strategy_vft0;
- const hicn_dpo_vft_t *dpo_vft0;
- u8 dpo_ctx_id0;
-
/* Prefetch for next iteration. */
if (n_left_from > 1)
{
vlib_buffer_t *b1;
b1 = vlib_get_buffer (vm, from[1]);
CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, STORE);
}
/* Dequeue a packet buffer */
@@ -144,62 +142,43 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
/* Get hicn buffer and state */
hicnb0 = hicn_get_buffer (b0);
- hicn_get_internal_state (hicnb0, rt->pitcs, &node0, &strategy_vft0,
- &dpo_vft0, &dpo_ctx_id0, &hash_entry0);
+ hicn_get_internal_state (hicnb0, &pcs_entry_index, &strategy_vft0,
+ &dpo_vft0, &dpo_ctx_id0);
+ pcs_entry =
+ hicn_pcs_entry_get_entry_from_index (rt->pitcs, pcs_entry_index);
- hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen);
isv6 = hicn_buffer_is_v6 (b0);
- pitp = hicn_pit_get_data (node0);
- dpo_id_t hicn_dpo_id0 = { .dpoi_type =
- dpo_vft0->hicn_dpo_get_type (),
- .dpoi_proto = 0,
- .dpoi_next_node = 0,
- .dpoi_index = dpo_ctx_id0 };
-
- if (PREDICT_FALSE (!hicn_node_compare (nameptr, namelen, node0)))
- {
- /* Remove lock from the entry */
- hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, hash_entry0,
- dpo_vft0, &hicn_dpo_id0);
- drop_packet (&next0);
- goto end_processing;
- }
- if ((tnow > pitp->shared.expire_time))
+ if (tnow > hicn_pcs_entry_get_expire_time (pcs_entry))
{
- /* Delete and clean up expired CS entry */
- hicn_pcs_delete (rt->pitcs, &pitp, &node0, vm, hash_entry0,
- dpo_vft0, &hicn_dpo_id0);
+ // Delete and clean up expired CS entry
+ hicn_pcs_entry_remove_lock (rt->pitcs, pcs_entry);
+
+ // Update stats
stats.cs_expired_count++;
- /* Forward interest to the strategy node */
+
+ // Forward interest to the strategy node
next0 = HICN_INTEREST_HITCS_NEXT_STRATEGY;
}
else
{
- if (PREDICT_TRUE (
- !(hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED)))
- hicn_pcs_cs_update (vm, rt->pitcs, pitp, pitp, node0);
-
- /*
- * Retrieve the incoming iface and forward
- * the data through it
- */
+ // Retrieve the incoming iface and forward
+ // the data through it
next0 = isv6 ? HICN_INTEREST_HITCS_NEXT_IFACE6_OUT :
HICN_INTEREST_HITCS_NEXT_IFACE4_OUT;
vnet_buffer (b0)->ip.adj_index[VLIB_TX] = hicnb0->face_id;
- clone_from_cs (vm, &pitp->u.cs.cs_pkt_buf, b0, isv6);
+ bi_ret = clone_from_cs (
+ vm, hicn_pcs_entry_cs_get_buffer (pcs_entry), b0, isv6);
+
+ hicn_pcs_entry_cs_set_buffer (pcs_entry, bi_ret);
+ // Update stats
stats.pkts_from_cache_count++;
stats.pkts_data_count++;
- /* Remove lock from the entry */
- hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, hash_entry0,
- dpo_vft0, &hicn_dpo_id0);
}
- end_processing:
-
- /* Maybe trace */
+ // Maybe trace
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
(b0->flags & VLIB_BUFFER_IS_TRACED)))
{
@@ -209,20 +188,18 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
t->next_index = next0;
}
- /* Incr packet counter */
+
+ // Increment packet counter
stats.pkts_processed += 1;
- /*
- * Verify speculative enqueue, maybe switch current
- * next frame
- */
+ // Verify speculative enqueue, maybe switch current next frame
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
n_left_to_next, bi0, next0);
}
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
- u32 pit_int_count = hicn_pit_get_int_count (rt->pitcs);
+ u32 pit_int_count = hicn_pcs_get_pit_count (rt->pitcs);
vlib_node_increment_counter (vm, hicn_interest_hitcs_node.index,
HICNFWD_ERROR_CACHED,
@@ -237,11 +214,13 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
return (frame->n_vectors);
}
+#if 0
always_inline void
drop_packet (u32 *next0)
{
*next0 = HICN_INTEREST_HITCS_NEXT_ERROR_DROP;
}
+#endif
/* packet trace format function */
static u8 *
diff --git a/hicn-plugin/src/interest_hitpit_node.c b/hicn-plugin/src/interest_hitpit_node.c
index c98baf7e9..9715fc549 100644
--- a/hicn-plugin/src/interest_hitpit_node.c
+++ b/hicn-plugin/src/interest_hitpit_node.c
@@ -25,7 +25,6 @@
#include "strategy_dpo_manager.h"
#include "state.h"
#include "error.h"
-#include "face_db.h"
/* packet trace format function */
static u8 *hicn_interest_hitpit_format_trace (u8 *s, va_list *args);
@@ -48,11 +47,27 @@ static uword
hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_frame_t *frame)
{
+ int ret;
u32 n_left_from, *from, *to_next;
hicn_interest_hitpit_next_t next_index;
hicn_interest_hitpit_runtime_t *rt;
vl_api_hicn_api_node_stats_get_reply_t stats = { 0 };
f64 tnow;
+ u32 n_left_to_next;
+ vlib_buffer_t *b0;
+ u8 isv6;
+ u32 bi0;
+ u32 next0 = HICN_INTEREST_HITPIT_NEXT_ERROR_DROP;
+ const hicn_strategy_vft_t *strategy_vft0;
+ const hicn_dpo_vft_t *dpo_vft0;
+ u8 dpo_ctx_id0;
+ u8 found = 0;
+ hicn_face_id_t outfaces[MAX_OUT_FACES];
+ u32 clones[MAX_OUT_FACES];
+ u16 outfaces_len;
+ u32 pit_entry_index;
+ hicn_pcs_entry_t *pcs_entry = NULL;
+ hicn_buffer_t *hicnb0;
rt = vlib_node_get_runtime_data (vm, hicn_interest_hitpit_node.index);
@@ -69,35 +84,15 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
while (n_left_from > 0)
{
- u32 n_left_to_next;
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
while (n_left_from > 0 && n_left_to_next > 0)
{
- vlib_buffer_t *b0;
- u8 isv6;
- u8 *nameptr;
- u16 namelen;
- u32 bi0;
- u32 next0 = HICN_INTEREST_HITPIT_NEXT_ERROR_DROP;
- hicn_hash_node_t *node0;
- const hicn_strategy_vft_t *strategy_vft0;
- const hicn_dpo_vft_t *dpo_vft0;
- hicn_pcs_entry_t *pitp;
- u8 dpo_ctx_id0;
- u8 found = 0;
- int nh_idx;
- hicn_face_id_t outfaces[MAX_OUT_FACES];
- u32 outfaces_len;
- hicn_hash_entry_t *hash_entry0;
- hicn_buffer_t *hicnb0;
-
/* Prefetch for next iteration. */
if (n_left_from > 1)
{
vlib_buffer_t *b1;
b1 = vlib_get_buffer (vm, from[1]);
CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, STORE);
}
/* Dequeue a packet buffer */
@@ -112,163 +107,142 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
/* Get hicn buffer and state */
hicnb0 = hicn_get_buffer (b0);
- hicn_get_internal_state (hicnb0, rt->pitcs, &node0, &strategy_vft0,
- &dpo_vft0, &dpo_ctx_id0, &hash_entry0);
+ hicn_get_internal_state (hicnb0, &pit_entry_index, &strategy_vft0,
+ &dpo_vft0, &dpo_ctx_id0);
- hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen);
- isv6 = hicn_buffer_is_v6 (b0);
+ // Retrieve PIT entry
+ pcs_entry =
+ hicn_pcs_entry_get_entry_from_index (rt->pitcs, pit_entry_index);
- pitp = hicn_pit_get_data (node0);
- dpo_id_t hicn_dpo_id0 = { .dpoi_type =
- dpo_vft0->hicn_dpo_get_type (),
- .dpoi_proto = 0,
- .dpoi_next_node = 0,
- .dpoi_index = dpo_ctx_id0 };
+ isv6 = hicn_buffer_is_v6 (b0);
- /*
- * Check if the hit is instead a collision in the
- * hash table. Unlikely to happen.
- */
- if (PREDICT_FALSE (!hicn_node_compare (nameptr, namelen, node0)))
- {
- stats.interests_hash_collision++;
- /* Remove lock from the entry */
- hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, hash_entry0,
- dpo_vft0, &hicn_dpo_id0);
- drop_packet (&next0);
+ // Increment packet counter
+ stats.pkts_processed += 1;
- goto end_processing;
- }
- /*
- * If the entry is expired, remove it no matter of
- * the possible cases.
- */
- if (tnow > pitp->shared.expire_time)
+ // If the entry is expired, remove it no matter of the possible
+ // cases.
+ if (tnow > hicn_pcs_entry_get_expire_time (pcs_entry))
{
+ // Notify strategy
strategy_vft0->hicn_on_interest_timeout (dpo_ctx_id0);
- hicn_pcs_delete (rt->pitcs, &pitp, &node0, vm, hash_entry0,
- dpo_vft0, &hicn_dpo_id0);
+
+ // Release lock on entry - this MUST delete the entry
+ hicn_pcs_entry_remove_lock (rt->pitcs, pcs_entry);
+
stats.pit_expired_count++;
+
+ // Forward to strategy node
+ // TODO this can be simplified by checking directly in the
+ // pcslookup node!
next0 = HICN_INTEREST_HITPIT_NEXT_STRATEGY;
}
else
{
- if ((hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY))
+ // A data packet may have arrived in the time between the pcs
+ // lookup and now. Check again to make sure the entry is CS or
+ // PIT
+ if (hicn_pcs_entry_is_cs (pcs_entry))
{
next0 = HICN_INTEREST_HITPIT_NEXT_INTEREST_HITCS;
}
else
{
- /*
- * Distinguish between aggregation or
- * retransmission
- */
-
+ // Distinguish between aggregation or retransmission
found =
- hicn_face_search (hicnb0->face_id, &(pitp->u.pit.faces));
+ hicn_pcs_entry_pit_search (pcs_entry, hicnb0->face_id);
if (found)
{
+ // Retransmission
strategy_vft0->hicn_select_next_hop (
- dpo_ctx_id0, &nh_idx, outfaces, &outfaces_len);
- /* Retransmission */
- /*
- * Prepare the packet for the
- * forwarding
- */
- if (outfaces_len == 1)
- {
- next0 = isv6 ?
- HICN_INTEREST_HITPIT_NEXT_FACE6_OUTPUT :
- HICN_INTEREST_HITPIT_NEXT_FACE4_OUTPUT;
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
- outfaces[0];
+ dpo_ctx_id0, outfaces, &outfaces_len);
- /*
- * Update the egress face in
- * the PIT
- */
- pitp->u.pit.pe_txnh = nh_idx;
- stats.interests_retx++;
+ // Prepare the packet for the forwarding
+ next0 = isv6 ? HICN_INTEREST_HITPIT_NEXT_FACE6_OUTPUT :
+ HICN_INTEREST_HITPIT_NEXT_FACE4_OUTPUT;
+
+ // Update stats
+ stats.interests_retx += outfaces_len;
+
+ // Clone interest if needed
+ if (outfaces_len > 1)
+ {
+ ret = vlib_buffer_clone (vm, bi0, clones,
+ (u16) outfaces_len,
+ CLIB_CACHE_LINE_BYTES * 2);
+ ASSERT (ret == outfaces_len);
}
else
{
- // restore pointers
- to_next -= 1;
- n_left_to_next += 1;
- u32 clones[outfaces_len];
- int ret =
- vlib_buffer_clone (vm, bi0, clones, outfaces_len,
- CLIB_CACHE_LINE_BYTES * 2);
- ASSERT (ret == outfaces_len);
- for (u32 nh = 0; nh < outfaces_len; nh++)
+ clones[0] = bi0;
+ }
+
+ // We need to clone the packet over multiple output
+ // faces
+
+ // Restore pointers
+ to_next -= 1;
+ n_left_to_next += 1;
+
+ for (u32 nh = 0; nh < outfaces_len; nh++)
+ {
+ vlib_buffer_t *local_b0 =
+ vlib_get_buffer (vm, clones[nh]);
+ to_next[0] = clones[nh];
+ to_next += 1;
+ n_left_to_next -= 1;
+
+ vnet_buffer (local_b0)->ip.adj_index[VLIB_TX] =
+ outfaces[nh];
+
+ /* Maybe trace */
+ if (PREDICT_FALSE (
+ (node->flags & VLIB_NODE_FLAG_TRACE) &&
+ (local_b0->flags & VLIB_BUFFER_IS_TRACED)))
{
- vlib_buffer_t *local_b0 =
- vlib_get_buffer (vm, clones[nh]);
- to_next[0] = clones[nh];
- to_next += 1;
- n_left_to_next -= 1;
-
- next0 =
- isv6 ? HICN_INTEREST_HITPIT_NEXT_FACE6_OUTPUT :
- HICN_INTEREST_HITPIT_NEXT_FACE4_OUTPUT;
- vnet_buffer (local_b0)->ip.adj_index[VLIB_TX] =
- outfaces[nh];
- stats.interests_retx++;
-
- /* Maybe trace */
- if (PREDICT_FALSE (
- (node->flags & VLIB_NODE_FLAG_TRACE) &&
- (local_b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- hicn_interest_hitpit_trace_t *t =
- vlib_add_trace (vm, node, local_b0,
- sizeof (*t));
- t->pkt_type = HICN_PACKET_TYPE_INTEREST;
- t->sw_if_index = vnet_buffer (local_b0)
- ->sw_if_index[VLIB_RX];
- t->next_index = next0;
- }
-
- /*
- * Verify speculative enqueue, maybe switch
- * current next frame
- */
- vlib_validate_buffer_enqueue_x1 (
- vm, node, next_index, to_next, n_left_to_next,
- clones[nh], next0);
+ hicn_interest_hitpit_trace_t *t =
+ vlib_add_trace (vm, node, local_b0,
+ sizeof (*t));
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST;
+ t->sw_if_index =
+ vnet_buffer (local_b0)->sw_if_index[VLIB_RX];
+ t->next_index = next0;
}
- continue;
+
+ /*
+ * Verify speculative enqueue, maybe switch
+ * current next frame
+ */
+ vlib_validate_buffer_enqueue_x1 (
+ vm, node, next_index, to_next, n_left_to_next,
+ clones[nh], next0);
}
+ continue;
}
else
{
- hicn_face_db_add_face (hicnb0->face_id,
- &pitp->u.pit.faces);
+ // Aggregation
+ hicn_pcs_entry_pit_add_face (pcs_entry, hicnb0->face_id);
/* Aggregation */
drop_packet (&next0);
stats.interests_aggregated++;
+
+ /* Maybe trace */
+ if (PREDICT_FALSE (
+ (node->flags & VLIB_NODE_FLAG_TRACE) &&
+ (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ hicn_interest_hitpit_trace_t *t =
+ vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST;
+ t->sw_if_index =
+ vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ t->next_index = next0;
+ }
}
- /* Remove lock from the entry */
- hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm,
- hash_entry0, dpo_vft0, &hicn_dpo_id0);
}
}
- end_processing:
-
- /* Maybe trace */
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
- (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- hicn_interest_hitpit_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = HICN_PACKET_TYPE_INTEREST;
- t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- t->next_index = next0;
- }
- /* Incr packet counter */
- stats.pkts_processed += 1;
/*
* Verify speculative enqueue, maybe switch current
@@ -279,7 +253,7 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
}
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
- u32 pit_int_count = hicn_pit_get_int_count (rt->pitcs);
+ u32 pit_int_count = hicn_pcs_get_pit_count (rt->pitcs);
vlib_node_increment_counter (vm, hicn_interest_hitpit_node.index,
HICNFWD_ERROR_PROCESSED, stats.pkts_processed);
diff --git a/hicn-plugin/src/interest_pcslookup_node.c b/hicn-plugin/src/interest_pcslookup_node.c
index e569573b7..a9ff9ba29 100644
--- a/hicn-plugin/src/interest_pcslookup_node.c
+++ b/hicn-plugin/src/interest_pcslookup_node.c
@@ -53,10 +53,15 @@ static uword
hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_frame_t *frame)
{
+ int ret;
u32 n_left_from, *from, *to_next;
hicn_interest_pcslookup_next_t next_index;
hicn_interest_pcslookup_runtime_t *rt;
vl_api_hicn_api_node_stats_get_reply_t stats = { 0 };
+ vlib_buffer_t *b0;
+ u32 bi0;
+ u32 next0 = HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP;
+ hicn_pcs_entry_t *pcs_entry = NULL;
rt = vlib_node_get_runtime_data (vm, hicn_interest_pcslookup_node.index);
@@ -74,29 +79,15 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
while (n_left_from > 0 && n_left_to_next > 0)
{
- vlib_buffer_t *b0;
- u8 *nameptr;
- u16 namelen;
- u32 bi0;
- u32 next0 = HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP;
- u64 name_hash = 0;
- u32 node_id0 = 0;
- index_t dpo_ctx_id0 = 0;
- u8 vft_id0 = 0;
- u8 is_cs0 = 0;
- u8 hash_entry_id = 0;
- u8 bucket_is_overflown = 0;
- u32 bucket_id = ~0;
-
/* Prefetch for next iteration. */
if (n_left_from > 1)
{
vlib_buffer_t *b1;
b1 = vlib_get_buffer (vm, from[1]);
CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, LOAD);
}
- /* Dequeue a packet buffer */
+
+ // Dequeue a packet buffer
bi0 = from[0];
from += 1;
n_left_from -= 1;
@@ -106,36 +97,34 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
b0 = vlib_get_buffer (vm, bi0);
- hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen);
-
+ // By default we send the interest to strategy node
next0 = HICN_INTEREST_PCSLOOKUP_NEXT_STRATEGY;
+
+ // Update stats
stats.pkts_processed++;
- if (PREDICT_FALSE (
- hicn_hashtb_fullhash (nameptr, namelen, &name_hash) !=
- HICN_ERROR_NONE))
- {
- next0 = HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP;
- }
- else
+ // Check if the interest is in the PCS already
+ ret = hicn_pcs_lookup_one (rt->pitcs, &hicn_get_buffer (b0)->name,
+ &pcs_entry);
+
+ if (ret == HICN_ERROR_NONE)
{
- if (hicn_hashtb_lookup_node (
- rt->pitcs->pcs_table, nameptr, namelen, name_hash,
- 0 /* is_data */, &node_id0, &dpo_ctx_id0, &vft_id0,
- &is_cs0, &hash_entry_id, &bucket_id,
- &bucket_is_overflown) == HICN_ERROR_NONE)
- {
- next0 =
- HICN_INTEREST_PCSLOOKUP_NEXT_INTEREST_HITPIT + is_cs0;
- }
- stats.pkts_interest_count++;
+ // We found an entry in the PCS. Next stage for this packet is
+ // one of hitpit/cs nodes
+ next0 = HICN_INTEREST_PCSLOOKUP_NEXT_INTEREST_HITPIT +
+ hicn_pcs_entry_is_cs (pcs_entry);
+
+ ret = hicn_store_internal_state (
+ b0, hicn_pcs_entry_get_index (rt->pitcs, pcs_entry),
+ vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
+
+ if (PREDICT_FALSE (ret != HICN_ERROR_NONE))
+ next0 = HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP;
}
- hicn_store_internal_state (b0, name_hash, node_id0, dpo_ctx_id0,
- vft_id0, hash_entry_id, bucket_id,
- bucket_is_overflown);
+ stats.pkts_interest_count++;
- /* Maybe trace */
+ // Maybe trace
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
(b0->flags & VLIB_BUFFER_IS_TRACED)))
{
@@ -154,9 +143,8 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
}
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
- u32 pit_int_count = hicn_pit_get_int_count (rt->pitcs);
- u32 pit_cs_count = hicn_pit_get_cs_count (rt->pitcs);
- u32 pcs_ntw_count = hicn_pcs_get_ntw_count (rt->pitcs);
+ u32 pit_int_count = hicn_pcs_get_pit_count (rt->pitcs);
+ u32 pit_cs_count = hicn_pcs_get_cs_count (rt->pitcs);
vlib_node_increment_counter (vm, hicn_interest_pcslookup_node.index,
HICNFWD_ERROR_PROCESSED, stats.pkts_processed);
@@ -171,9 +159,6 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
update_node_counter (vm, hicn_interest_pcslookup_node.index,
HICNFWD_ERROR_CS_COUNT, pit_cs_count);
- update_node_counter (vm, hicn_interest_pcslookup_node.index,
- HICNFWD_ERROR_CS_NTW_COUNT, pcs_ntw_count);
-
return (frame->n_vectors);
}
@@ -183,7 +168,7 @@ hicn_interest_pcslookup_format_trace (u8 *s, va_list *args)
{
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
- hicn_interest_pcslookup_trace_t *t =
+ const hicn_interest_pcslookup_trace_t *t =
va_arg (*args, hicn_interest_pcslookup_trace_t *);
s = format (s, "INTEREST_PCSLOOKUP: pkt: %d, sw_if_index %d, next index %d",
diff --git a/hicn-plugin/src/parser.h b/hicn-plugin/src/parser.h
index 29405ebec..3c21a33f8 100644
--- a/hicn-plugin/src/parser.h
+++ b/hicn-plugin/src/parser.h
@@ -20,11 +20,85 @@
#include "hicn.h"
#include "error.h"
+#include "infra.h"
/**
* @file parser.h
*/
+#define PARSE(PACKET_TYPE) \
+ do \
+ { \
+ if (pkt == NULL) \
+ return HICN_ERROR_PARSER_PKT_INVAL; \
+ \
+ int ret = HICN_LIB_ERROR_NONE; \
+ \
+ hicn_header_t *pkt_hdr; \
+ u8 *ip_pkt; \
+ u8 ip_proto; \
+ int isv6; \
+ u8 next_proto_offset; \
+ hicn_type_t type; \
+ hicn_name_t *name; \
+ u16 *port; \
+ hicn_lifetime_t *lifetime; \
+ \
+ /* start parsing first fields to get the protocols */ \
+ pkt_hdr = vlib_buffer_get_current (pkt); \
+ isv6 = hicn_is_v6 (pkt_hdr); \
+ \
+ ip_pkt = vlib_buffer_get_current (pkt); \
+ ip_proto = (1 - isv6) * IPPROTO_IP + (isv6) *IPPROTO_IPV6; \
+ \
+ /* in the ipv6 header the next header field is at byte 6 in the ipv4*/ \
+ /* header the protocol field is at byte 9*/ \
+ next_proto_offset = 6 + (1 - isv6) * 3; \
+ \
+ /* get type info*/ \
+ type.l4 = IPPROTO_NONE; \
+ type.l3 = ip_pkt[next_proto_offset] == IPPROTO_UDP ? IPPROTO_ENCAP : \
+ IPPROTO_NONE; \
+ type.l2 = ip_pkt[next_proto_offset]; \
+ type.l1 = ip_proto; \
+ \
+ /* cache hicn packet type in opaque2*/ \
+ hicn_get_buffer (pkt)->type = type; \
+ \
+ /* get name and name length*/ \
+ name = &hicn_get_buffer (pkt)->name; \
+ ret = hicn_ops_vft[type.l1]->get_##PACKET_TYPE##_name ( \
+ type, &pkt_hdr->protocol, name); \
+ if (PREDICT_FALSE (ret)) \
+ { \
+ if (type.l2 == IPPROTO_ICMPV4 || type.l2 == IPPROTO_ICMPV6) \
+ { \
+ return HICN_ERROR_PARSER_MAPME_PACKET; \
+ } \
+ return HICN_ERROR_PARSER_PKT_INVAL; \
+ } \
+ \
+ /* get source port*/ \
+ port = &hicn_get_buffer (pkt)->port; \
+ hicn_ops_vft[type.l1]->get_source_port (type, &pkt_hdr->protocol, \
+ port); \
+ if (PREDICT_FALSE (ret)) \
+ { \
+ return HICN_ERROR_PARSER_PKT_INVAL; \
+ } \
+ \
+ /* get lifetime*/ \
+ lifetime = &hicn_get_buffer (pkt)->lifetime; \
+ hicn_ops_vft[type.l1]->get_lifetime (type, &pkt_hdr->protocol, \
+ lifetime); \
+ \
+ if (*lifetime > hicn_main.pit_lifetime_max_ms) \
+ *lifetime = hicn_main.pit_lifetime_max_ms; \
+ \
+ return ret; \
+ } \
+ while (0)
+
/**
* @brief Parse a interest packet
*
@@ -39,63 +113,7 @@
always_inline int
hicn_interest_parse_pkt (vlib_buffer_t *pkt)
{
- if (pkt == NULL)
- return HICN_ERROR_PARSER_PKT_INVAL;
-
- int ret = HICN_LIB_ERROR_NONE;
-
- hicn_header_t *pkt_hdr;
- u8 *ip_pkt;
- u8 ip_proto;
- u8 next_proto_offset;
- hicn_type_t type;
- hicn_name_t *name;
- u16 *port;
- int isv6;
-
- // start parsing first fields to get the protocols
- pkt_hdr = vlib_buffer_get_current (pkt);
- isv6 = hicn_is_v6 (pkt_hdr);
-
- ip_pkt = vlib_buffer_get_current (pkt);
- ip_proto = (1 - isv6) * IPPROTO_IP + (isv6) *IPPROTO_IPV6;
-
- // in the ipv6 header the next header field is at byte 6 in the ipv4
- // header the protocol field is at byte 9
- next_proto_offset = 6 + (1 - isv6) * 3;
-
- // get type info
- type.l4 = IPPROTO_NONE;
- type.l3 =
- ip_pkt[next_proto_offset] == IPPROTO_UDP ? IPPROTO_ENCAP : IPPROTO_NONE;
- type.l2 = ip_pkt[next_proto_offset];
- type.l1 = ip_proto;
-
- // cache hicn packet type in opaque2
- hicn_get_buffer (pkt)->type = type;
-
- // get name and name length
- name = &hicn_get_buffer (pkt)->name;
- ret =
- hicn_ops_vft[type.l1]->get_interest_name (type, &pkt_hdr->protocol, name);
- if (PREDICT_FALSE (ret))
- {
- if (type.l2 == IPPROTO_ICMPV4 || type.l2 == IPPROTO_ICMPV6)
- {
- return HICN_ERROR_PARSER_MAPME_PACKET;
- }
- return HICN_ERROR_PARSER_PKT_INVAL;
- }
-
- // get source port
- port = &hicn_get_buffer (pkt)->port;
- hicn_ops_vft[type.l1]->get_source_port (type, &pkt_hdr->protocol, port);
- if (PREDICT_FALSE (ret))
- {
- return HICN_ERROR_PARSER_PKT_INVAL;
- }
-
- return ret;
+ PARSE (interest);
}
/**
@@ -112,65 +130,10 @@ hicn_interest_parse_pkt (vlib_buffer_t *pkt)
always_inline int
hicn_data_parse_pkt (vlib_buffer_t *pkt)
{
- if (pkt == NULL)
- return HICN_ERROR_PARSER_PKT_INVAL;
-
- int ret = HICN_LIB_ERROR_NONE;
-
- hicn_header_t *pkt_hdr;
- u8 *ip_pkt;
- u8 ip_proto;
- int isv6;
- u8 next_proto_offset;
- hicn_type_t type;
- hicn_name_t *name;
- u16 *port;
-
- // start parsing first fields to get the protocols
- pkt_hdr = vlib_buffer_get_current (pkt);
- isv6 = hicn_is_v6 (pkt_hdr);
-
- ip_pkt = vlib_buffer_get_current (pkt);
- ip_proto = (1 - isv6) * IPPROTO_IP + (isv6) *IPPROTO_IPV6;
-
- // in the ipv6 header the next header field is at byte 6 in the ipv4
- // header the protocol field is at byte 9
- next_proto_offset = 6 + (1 - isv6) * 3;
-
- // get type info
- type.l4 = IPPROTO_NONE;
- type.l3 =
- ip_pkt[next_proto_offset] == IPPROTO_UDP ? IPPROTO_ENCAP : IPPROTO_NONE;
- type.l2 = ip_pkt[next_proto_offset];
- type.l1 = ip_proto;
-
- // cache hicn packet type in opaque2
- hicn_get_buffer (pkt)->type = type;
-
- // get name and name length
- name = &hicn_get_buffer (pkt)->name;
- ret = hicn_ops_vft[type.l1]->get_data_name (type, &pkt_hdr->protocol, name);
- if (PREDICT_FALSE (ret))
- {
- if (type.l2 == IPPROTO_ICMPV4 || type.l2 == IPPROTO_ICMPV6)
- {
- return HICN_ERROR_PARSER_MAPME_PACKET;
- }
- return HICN_ERROR_PARSER_PKT_INVAL;
- }
-
- // get source port
- port = &hicn_get_buffer (pkt)->port;
- hicn_ops_vft[type.l1]->get_source_port (type, &pkt_hdr->protocol, port);
- if (PREDICT_FALSE (ret))
- {
- return HICN_ERROR_PARSER_PKT_INVAL;
- }
-
- return ret;
+ PARSE (data);
}
-#endif /* // __HICN_PARSER_H__ */
+#endif /* __HICN_PARSER_H__ */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/pcs.c b/hicn-plugin/src/pcs.c
index d6e4fd954..564a435a0 100644
--- a/hicn-plugin/src/pcs.c
+++ b/hicn-plugin/src/pcs.c
@@ -16,33 +16,39 @@
#include <stdlib.h>
#include <vlib/vlib.h>
-#include "hashtb.h"
#include "pcs.h"
#include "cache_policies/cs_lru.h"
-int
-hicn_pit_create (hicn_pit_cs_t *p, u32 num_elems)
+void
+hicn_pit_create (hicn_pit_cs_t *p, u32 max_pit_elt, u32 max_cs_elt)
{
- int ret =
- hicn_hashtb_alloc (&p->pcs_table, num_elems, sizeof (hicn_pcs_entry_t));
- p->pcs_table->ht_flags |= HICN_HASHTB_FLAG_KEY_FMT_NAME;
+ // Allocate PCS hash table. KEY=Name, VALUE=pool_idx
+ clib_bihash_24_8_t *pcs_table = &p->pcs_table;
+ u32 n_elements = max_pit_elt / BIHASH_KVP_PER_PAGE;
+ clib_bihash_init_24_8 (pcs_table, "hicn_pcs_table", n_elements, 512 << 20);
- p->pcs_pit_count = p->pcs_cs_count = 0;
+ // Allocate pool of PIT/CS entries
+ pool_alloc (p->pcs_entries_pool, max_pit_elt);
- p->policy_state.max =
- HICN_PARAM_CS_LRU_DEFAULT -
- (HICN_PARAM_CS_LRU_DEFAULT * HICN_PARAM_CS_RESERVED_APP / 100);
- p->policy_state.count = 0;
- p->policy_state.head = p->policy_state.tail = 0;
+ // Init counters
+ p->max_pit_size = max_pit_elt;
+ p->pcs_pit_count = p->pcs_cs_count = 0;
+ p->policy_state = hicn_cs_lru_create (max_cs_elt);
+ p->pcs_cs_count = 0;
+ p->pcs_pcs_alloc = 0;
+ p->pcs_pcs_dealloc = 0;
+ p->pcs_pit_count = 0;
+}
- p->policy_vft.hicn_cs_insert = hicn_cs_lru.hicn_cs_insert;
- p->policy_vft.hicn_cs_update = hicn_cs_lru.hicn_cs_update;
- p->policy_vft.hicn_cs_dequeue = hicn_cs_lru.hicn_cs_dequeue;
- p->policy_vft.hicn_cs_delete_get = hicn_cs_lru.hicn_cs_delete_get;
- p->policy_vft.hicn_cs_trim = hicn_cs_lru.hicn_cs_trim;
- p->policy_vft.hicn_cs_flush = hicn_cs_lru.hicn_cs_flush;
+void
+hicn_pit_destroy (hicn_pit_cs_t *p)
+{
+ // Deallocate PCS hash table.
+ clib_bihash_24_8_t *pcs_table = &p->pcs_table;
+ clib_bihash_free_24_8 (pcs_table);
- return (ret);
+ // Deallocate pool of PIT/CS entries
+ pool_free (p->pcs_entries_pool);
}
/*
diff --git a/hicn-plugin/src/pcs.h b/hicn-plugin/src/pcs.h
index b98b72a53..fa5a68b27 100644
--- a/hicn-plugin/src/pcs.h
+++ b/hicn-plugin/src/pcs.h
@@ -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,740 +58,756 @@
#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 - 32
+ 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 */
- /* 24B + 8B = 32B */
- 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 */
- /* 32B + (64 - 32)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);
-
-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);
+/************************************************************************
+ **************************** Create / Destroy **************************
+ ************************************************************************/
-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);
+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_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);
+/************************************************************************
+ **************************** Counters getters **************************
+ ************************************************************************/
-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);
-
-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);
-
-/* 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)
+{
+ kv->key[0] = name->prefix.ip6.as_u64[0];
+ kv->key[1] = name->prefix.ip6.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)
{
- p->policy_state.max = limit;
+ 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;
-
- ASSERT (pcs == hicn_hashtb_node_data (*node));
+ pitcs->pcs_pcs_dealloc++;
+ pool_put (pitcs->pcs_entries_pool, entry);
+}
- 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++;
+/*
+ * 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);
+}
- /* Flush faces */
- hicn_faces_flush (&(pcs->u.pit.faces));
- }
+/*
+ * 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);
+}
- hicn_hashtb_delete (pitcs->pcs_table, node, hash_entry->he_msb64);
- *pcs_entryp = NULL;
+/*
+ * Check if pcs entry is a content store entry
+ */
+always_inline int
+hicn_pcs_entry_is_cs (const hicn_pcs_entry_t *entry)
+{
+ ASSERT (entry);
+ return (entry->flags & HICN_PCS_ENTRY_CS_FLAG);
}
/*
- * 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.
+ * Add lock to PIT 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_pcs_entry_add_lock (hicn_pcs_entry_t *pcs_entry)
{
+ pcs_entry->locks++;
+}
- /*
- * 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 (&(pcs_entry->u.pit.faces));
+/*
+ * 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;
+}
- 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;
+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;
+}
- /* 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)
+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));
-
- 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);
+ 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);
- 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, kv.value);
+
+ // 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)
- {
- hicn_pcs_cs_delete (vm, pitcs, pcs_entryp, nodep, hash_entry, dpo_vft,
- hicn_dpo_id);
- }
- else
+ if (pcs_entry->flags & HICN_PCS_ENTRY_CS_FLAG)
{
- 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
diff --git a/hicn-plugin/src/pg_node.c b/hicn-plugin/src/pg_node.c
index 3672a6b72..1a99d3fa2 100644
--- a/hicn-plugin/src/pg_node.c
+++ b/hicn-plugin/src/pg_node.c
@@ -124,6 +124,12 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
u16 msg_type0 = 0, msg_type1 = 0;
hicnpg_main_t *hpgm = &hicnpg_main;
int iface = 0;
+ u32 next0 = HICNPG_INTEREST_NEXT_DROP;
+ u32 next1 = HICNPG_INTEREST_NEXT_DROP;
+ u32 sw_if_index0 = ~0, sw_if_index1 = ~0;
+ u8 isv6_0;
+ u8 isv6_1;
+ u32 n_left_to_next;
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
@@ -131,18 +137,10 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
while (n_left_from > 0)
{
- u32 n_left_to_next;
-
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
while (n_left_from >= 4 && n_left_to_next >= 2)
{
- u32 next0 = HICNPG_INTEREST_NEXT_DROP;
- u32 next1 = HICNPG_INTEREST_NEXT_DROP;
- u32 sw_if_index0 = ~0, sw_if_index1 = ~0;
- u8 isv6_0;
- u8 isv6_1;
-
/* Prefetch next iteration. */
{
vlib_buffer_t *p2, *p3;
@@ -278,10 +276,6 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
while (n_left_from > 0 && n_left_to_next > 0)
{
- u32 next0 = HICNPG_INTEREST_NEXT_DROP;
- u32 sw_if_index0;
- u8 isv6_0;
-
/* speculatively enqueue b0 to the current next frame */
bi0 = from[0];
to_next[0] = bi0;
@@ -576,6 +570,9 @@ hicnpg_client_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_buffer_t *b0, *b1;
u8 pkt_type0 = 0, pkt_type1 = 0;
u16 msg_type0 = 1, msg_type1 = 1;
+ u32 next0 = HICNPG_DATA_NEXT_DROP;
+ u32 next1 = HICNPG_DATA_NEXT_DROP;
+ u32 sw_if_index0, sw_if_index1;
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
@@ -588,10 +585,6 @@ hicnpg_client_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
while (n_left_from >= 4 && n_left_to_next >= 2)
{
- u32 next0 = HICNPG_DATA_NEXT_DROP;
- u32 next1 = HICNPG_DATA_NEXT_DROP;
- u32 sw_if_index0, sw_if_index1;
-
/* Prefetch next iteration. */
{
vlib_buffer_t *p2, *p3;
@@ -659,9 +652,6 @@ hicnpg_client_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
while (n_left_from > 0 && n_left_to_next > 0)
{
- u32 next0 = HICNPG_DATA_NEXT_DROP;
- u32 sw_if_index0;
-
/* speculatively enqueue b0 to the current next frame */
bi0 = from[0];
to_next[0] = bi0;
@@ -815,6 +805,12 @@ hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_buffer_t *b0, *b1;
u8 pkt_type0 = 0, pkt_type1 = 0;
u16 msg_type0 = 0, msg_type1 = 0;
+ u32 next0 = HICNPG_SERVER_NEXT_DROP;
+ u32 next1 = HICNPG_SERVER_NEXT_DROP;
+ u32 sw_if_index0, sw_if_index1;
+ u32 hpgi0, hpgi1;
+ hicnpg_server_t *hpg0, *hpg1;
+ u32 n_left_to_next;
from = vlib_frame_vector_args (frame);
@@ -823,18 +819,10 @@ hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
while (n_left_from > 0)
{
- u32 n_left_to_next;
-
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
while (n_left_from >= 4 && n_left_to_next >= 2)
{
- u32 next0 = HICNPG_SERVER_NEXT_DROP;
- u32 next1 = HICNPG_SERVER_NEXT_DROP;
- u32 sw_if_index0, sw_if_index1;
- u32 hpgi0, hpgi1;
- hicnpg_server_t *hpg0, *hpg1;
-
/* Prefetch next iteration. */
{
vlib_buffer_t *p2, *p3;
@@ -940,11 +928,6 @@ hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
while (n_left_from > 0 && n_left_to_next > 0)
{
- u32 next0 = HICNPG_SERVER_NEXT_DROP;
- u32 sw_if_index0 = ~0;
- u32 hpgi0;
- hicnpg_server_t *hpg0;
-
/* speculatively enqueue b0 to the current next frame */
bi0 = from[0];
to_next[0] = bi0;
@@ -1126,7 +1109,3 @@ VLIB_REGISTER_NODE(hicn_pg_server4_node) =
[HICNPG_SERVER_NEXT_DROP] = "error-drop",
},
};
-
-/*
- * End of packet-generator server node
- */ \ No newline at end of file
diff --git a/hicn-plugin/src/state.h b/hicn-plugin/src/state.h
index 39953722d..e80e81e29 100644
--- a/hicn-plugin/src/state.h
+++ b/hicn-plugin/src/state.h
@@ -21,7 +21,6 @@
#include "hicn.h"
#include "pcs.h"
-#include "hashtb.h"
#include "strategy.h"
#include "strategy_dpo_ctx.h"
#include "strategy_dpo_manager.h"
@@ -51,26 +50,14 @@
* @param hash_entry entry in the hash table referring to the buffer
*/
always_inline void
-hicn_get_internal_state (hicn_buffer_t *hicnb, hicn_pit_cs_t *pitcs,
- hicn_hash_node_t **node,
+hicn_get_internal_state (hicn_buffer_t *hicnb, u32 *pit_entry_index,
const hicn_strategy_vft_t **strategy_vft,
- const hicn_dpo_vft_t **dpo_vft, u8 *dpo_ctx_id,
- hicn_hash_entry_t **hash_entry)
+ const hicn_dpo_vft_t **dpo_vft, u8 *dpo_ctx_id)
{
- *node = pool_elt_at_index (pitcs->pcs_table->ht_nodes, hicnb->node_id);
+ *pit_entry_index = hicnb->pcs_entry_id;
*strategy_vft = hicn_dpo_get_strategy_vft (hicnb->vft_id);
*dpo_vft = hicn_dpo_get_vft (hicnb->vft_id);
*dpo_ctx_id = hicnb->dpo_ctx_id;
-
- hicn_hash_bucket_t *bucket;
- if (hicnb->hash_bucket_flags & HICN_HASH_NODE_OVERFLOW_BUCKET)
- bucket = pool_elt_at_index (pitcs->pcs_table->ht_overflow_buckets,
- hicnb->bucket_id);
- else
- bucket =
- (hicn_hash_bucket_t *) (pitcs->pcs_table->ht_buckets + hicnb->bucket_id);
-
- *hash_entry = &(bucket->hb_entries[hicnb->hash_entry_id]);
}
/*
@@ -83,30 +70,25 @@ hicn_get_internal_state (hicn_buffer_t *hicnb, hicn_pit_cs_t *pitcs,
* @brief Store the hicn state in the hicn buffer
*
* @param b vlib buffer holding the hICN packet
- * @param name_hash hash of the hICN name
- * @param node_id id of the node in the hash table referring to the buffer
- * @param dpo_ctx_id id of the dpo context id corresponding to the buffer
- * @param vft_id id of the strategy vft corresponding to the buffer
- * @param hash_entry_id id of the entry in the hash table referring to the
- * buffer
- * @param bucket_id id of the hasth table bucket that holds the hash entry
- * @param bucket_is_overflow 1 if the bucket is from the ht_overflow_buckets
- * pool 0 if the bucket is from the ht_buckets pool
+ * @param pcs_entry_index index of the PCS entry
*/
-always_inline void
-hicn_store_internal_state (vlib_buffer_t *b, u64 name_hash, u32 node_id,
- u8 dpo_ctx_id, u8 vft_id, u8 hash_entry_id,
- u32 bucket_id, u8 bucket_is_overflow)
+always_inline int
+hicn_store_internal_state (vlib_buffer_t *b, u32 pcs_entry_index,
+ u32 dpo_ctx_id)
{
hicn_buffer_t *hicnb = hicn_get_buffer (b);
- hicnb->name_hash = name_hash;
- hicnb->node_id = node_id;
+
hicnb->dpo_ctx_id = dpo_ctx_id;
- hicnb->vft_id = vft_id;
- hicnb->hash_entry_id = hash_entry_id;
- hicnb->bucket_id = bucket_id;
- hicnb->hash_bucket_flags =
- HICN_HASH_NODE_OVERFLOW_BUCKET * bucket_is_overflow;
+ const hicn_dpo_ctx_t *dpo_ctx =
+ hicn_strategy_dpo_ctx_get (hicnb->dpo_ctx_id);
+
+ if (PREDICT_FALSE (dpo_ctx == NULL))
+ return HICN_ERROR_DPO_CTX_NOT_FOUND;
+
+ hicnb->vft_id = dpo_ctx->dpo_type;
+ hicnb->pcs_entry_id = pcs_entry_index;
+
+ return HICN_ERROR_NONE;
}
#endif /* // __HICN_STATE__ */
diff --git a/hicn-plugin/src/strategies/strategy_mw.c b/hicn-plugin/src/strategies/strategy_mw.c
index 990e64a5d..81c757f70 100644
--- a/hicn-plugin/src/strategies/strategy_mw.c
+++ b/hicn-plugin/src/strategies/strategy_mw.c
@@ -16,16 +16,15 @@
#include "../strategy.h"
#include "../strategy_dpo_ctx.h"
#include "../faces/face.h"
-#include "../hashtb.h"
#include "../strategy_dpo_manager.h"
/* Simple strategy that chooses the next hop with the maximum weight */
/* It does not require to exend the hicn_dpo */
void hicn_receive_data_mw (index_t dpo_idx, int nh_idx);
-void hicn_add_interest_mw (index_t dpo_idx, hicn_hash_entry_t *pit_entry);
+void hicn_add_interest_mw (index_t dpo_idx);
void hicn_on_interest_timeout_mw (index_t dpo_idx);
-u32 hicn_select_next_hop_mw (index_t dpo_idx, int *nh_idx,
- hicn_face_id_t *outfaces, uint32_t *len);
+u32 hicn_select_next_hop_mw (index_t dpo_idx, hicn_face_id_t *outfaces,
+ u16 *len);
u32 get_strategy_node_index_mw (void);
u8 *hicn_strategy_format_trace_mw (u8 *s, hicn_strategy_trace_t *t);
u8 *hicn_strategy_format_mw (u8 *s, va_list *ap);
@@ -51,8 +50,7 @@ hicn_mw_strategy_get_vft (void)
/* DPO should be give in input as it containes all the information to calculate
* the next hops*/
u32
-hicn_select_next_hop_mw (index_t dpo_idx, int *nh_idx,
- hicn_face_id_t *outfaces, uint32_t *len)
+hicn_select_next_hop_mw (index_t dpo_idx, hicn_face_id_t *outfaces, u16 *len)
{
hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx);
@@ -82,14 +80,8 @@ hicn_select_next_hop_mw (index_t dpo_idx, int *nh_idx,
}
void
-hicn_add_interest_mw (index_t dpo_ctx_idx, hicn_hash_entry_t *hash_entry)
+hicn_add_interest_mw (index_t dpo_ctx_idx)
{
- hash_entry->dpo_ctx_id = dpo_ctx_idx;
- dpo_id_t hicn_dpo_id = { .dpoi_type = hicn_dpo_strategy_mw_get_type (),
- .dpoi_proto = 0,
- .dpoi_next_node = 0,
- .dpoi_index = dpo_ctx_idx };
- hash_entry->vft_id = hicn_dpo_get_vft_id (&hicn_dpo_id);
}
void
diff --git a/hicn-plugin/src/strategies/strategy_rp.c b/hicn-plugin/src/strategies/strategy_rp.c
index 748cd69b1..eb495ff91 100644
--- a/hicn-plugin/src/strategies/strategy_rp.c
+++ b/hicn-plugin/src/strategies/strategy_rp.c
@@ -17,16 +17,15 @@
#include "../strategy.h"
#include "../strategy_dpo_ctx.h"
#include "../faces/face.h"
-#include "../hashtb.h"
#include "../strategy_dpo_manager.h"
/* Simple strategy that forwards intertests to all next hops */
/* It does not require to exend the hicn_dpo */
void hicn_receive_data_rp (index_t dpo_idx, int nh_idx);
-void hicn_add_interest_rp (index_t dpo_idx, hicn_hash_entry_t *pit_entry);
+void hicn_add_interest_rp (index_t dpo_idx);
void hicn_on_interest_timeout_rp (index_t dpo_idx);
-u32 hicn_select_next_hop_rp (index_t dpo_idx, int *nh_idx,
- hicn_face_id_t *outfaces, uint32_t *len);
+u32 hicn_select_next_hop_rp (index_t dpo_idx, hicn_face_id_t *outfaces,
+ u16 *len);
u8 *hicn_strategy_format_trace_rp (u8 *s, hicn_strategy_trace_t *t);
u8 *hicn_strategy_format_rp (u8 *s, va_list *ap);
@@ -51,8 +50,7 @@ hicn_rp_strategy_get_vft (void)
/* DPO should be give in input as it containes all the information to calculate
* the next hops*/
u32
-hicn_select_next_hop_rp (index_t dpo_idx, int *nh_idx,
- hicn_face_id_t *outfaces, uint32_t *len)
+hicn_select_next_hop_rp (index_t dpo_idx, hicn_face_id_t *outfaces, u16 *len)
{
hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx);
@@ -74,7 +72,7 @@ hicn_select_next_hop_rp (index_t dpo_idx, int *nh_idx,
}
void
-hicn_add_interest_rp (index_t dpo_ctx_idx, hicn_hash_entry_t *hash_entry)
+hicn_add_interest_rp (index_t dpo_ctx_idx)
{
/* Nothing to do */
}
diff --git a/hicn-plugin/src/strategies/strategy_rr.c b/hicn-plugin/src/strategies/strategy_rr.c
index 192cf5fc3..ef5dc3fc1 100644
--- a/hicn-plugin/src/strategies/strategy_rr.c
+++ b/hicn-plugin/src/strategies/strategy_rr.c
@@ -17,16 +17,15 @@
#include "../strategy.h"
#include "../strategy_dpo_ctx.h"
#include "../faces/face.h"
-#include "../hashtb.h"
#include "../strategy_dpo_manager.h"
/* Simple strategy that chooses the next hop with the maximum weight */
/* It does not require to exend the hicn_dpo */
void hicn_receive_data_rr (index_t dpo_idx, int nh_idx);
-void hicn_add_interest_rr (index_t dpo_idx, hicn_hash_entry_t *pit_entry);
+void hicn_add_interest_rr (index_t dpo_idx);
void hicn_on_interest_timeout_rr (index_t dpo_idx);
-u32 hicn_select_next_hop_rr (index_t dpo_idx, int *nh_idx,
- hicn_face_id_t *outfaces, uint32_t *len);
+u32 hicn_select_next_hop_rr (index_t dpo_idx, hicn_face_id_t *outfaces,
+ u16 *len);
u8 *hicn_strategy_format_trace_rr (u8 *s, hicn_strategy_trace_t *t);
u8 *hicn_strategy_format_rr (u8 *s, va_list *ap);
@@ -51,8 +50,7 @@ hicn_rr_strategy_get_vft (void)
/* DPO should be give in input as it containes all the information to calculate
* the next hops*/
u32
-hicn_select_next_hop_rr (index_t dpo_idx, int *nh_idx,
- hicn_face_id_t *outfaces, uint32_t *len)
+hicn_select_next_hop_rr (index_t dpo_idx, hicn_face_id_t *outfaces, u16 *len)
{
hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx);
@@ -75,14 +73,8 @@ hicn_select_next_hop_rr (index_t dpo_idx, int *nh_idx,
}
void
-hicn_add_interest_rr (index_t dpo_ctx_idx, hicn_hash_entry_t *hash_entry)
+hicn_add_interest_rr (index_t dpo_ctx_idx)
{
- hash_entry->dpo_ctx_id = dpo_ctx_idx;
- dpo_id_t hicn_dpo_id = { .dpoi_type = hicn_dpo_strategy_rr_get_type (),
- .dpoi_proto = 0,
- .dpoi_next_node = 0,
- .dpoi_index = dpo_ctx_idx };
- hash_entry->vft_id = hicn_dpo_get_vft_id (&hicn_dpo_id);
}
void
diff --git a/hicn-plugin/src/strategy.h b/hicn-plugin/src/strategy.h
index efc6e464e..85fc1e12d 100644
--- a/hicn-plugin/src/strategy.h
+++ b/hicn-plugin/src/strategy.h
@@ -17,7 +17,6 @@
#define __HICN_STRATEGY__
#include "hicn.h"
-#include "hashtb.h"
#include "mgmt.h"
#include "faces/face.h"
@@ -51,9 +50,9 @@ typedef struct hicn_strategy_vft_s
{
void (*hicn_receive_data) (index_t dpo_idx, int nh_idx);
void (*hicn_on_interest_timeout) (index_t dpo_idx);
- void (*hicn_add_interest) (index_t dpo_idx, hicn_hash_entry_t *pit_entry);
- u32 (*hicn_select_next_hop) (index_t dpo_idx, int *nh_idx,
- hicn_face_id_t *outfaces, uint32_t *len);
+ void (*hicn_add_interest) (index_t dpo_idx);
+ u32 (*hicn_select_next_hop) (index_t dpo_idx, hicn_face_id_t *outfaces,
+ u16 *len);
u8 *(*hicn_format_strategy_trace) (u8 *, hicn_strategy_trace_t *);
u8 *(*hicn_format_strategy) (u8 *s, va_list *ap);
/**< Format an hICN dpo*/
diff --git a/hicn-plugin/src/strategy_node.c b/hicn-plugin/src/strategy_node.c
index 3ff2d0209..565f3e496 100644
--- a/hicn-plugin/src/strategy_node.c
+++ b/hicn-plugin/src/strategy_node.c
@@ -20,7 +20,6 @@
#include "parser.h"
#include "strategy.h"
#include "strategy_dpo_ctx.h"
-#include "face_db.h"
#include "infra.h"
#include "mgmt.h"
#include "pcs.h"
@@ -61,117 +60,18 @@ hicn_strategy_format_trace (u8 *s, va_list *args)
return vft->hicn_format_strategy_trace (s, t);
}
-always_inline int
-hicn_new_interest (hicn_strategy_runtime_t *rt, vlib_buffer_t *b0, u32 *next,
- f64 tnow, u8 *nameptr, u16 namelen, hicn_face_id_t outface,
- int nh_idx, index_t dpo_ctx_id0,
- const hicn_strategy_vft_t *strategy, dpo_type_t dpo_type,
- vl_api_hicn_api_node_stats_get_reply_t *stats,
- u8 is_replication)
+always_inline void
+drop_packet (vlib_main_t *vm, u32 bi0, u32 *n_left_to_next, u32 *next0,
+ u32 **to_next, u32 *next_index, vlib_node_runtime_t *node)
{
- int ret;
- hicn_hash_node_t *nodep;
- hicn_pcs_entry_t *pitp;
- hicn_header_t *hicn0;
- hicn_main_t *sm = &hicn_main;
- hicn_buffer_t *hicnb0 = hicn_get_buffer (b0);
- u32 node_id0 = 0;
- u8 vft_id0 = dpo_type;
- u8 is_cs0 = 0;
- u8 hash_entry_id = 0;
- u8 bucket_is_overflow = 0;
- u32 bucket_id = ~0;
- u8 isv6 = hicn_buffer_is_v6 (b0);
-
- if (is_replication)
- {
- // an entry for this message alredy exists in the PIT so just send it
- *next = isv6 ? HICN_STRATEGY_NEXT_INTEREST_FACE6 :
- HICN_STRATEGY_NEXT_INTEREST_FACE4;
-
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = outface;
- stats->pkts_interest_count++;
- return HICN_ERROR_NONE;
- }
-
- /* Create PIT node and init PIT entry */
- nodep = hicn_hashtb_alloc_node (rt->pitcs->pcs_table);
- if (PREDICT_FALSE (nodep == NULL))
- {
- /* Nothing we can do - no mem */
- *next = HICN_STRATEGY_NEXT_ERROR_DROP;
- return HICN_ERROR_HASHTB_NOMEM;
- }
- pitp = hicn_pit_get_data (nodep);
- hicn_pit_init_data (pitp);
- pitp->shared.create_time = tnow;
-
- hicn0 = vlib_buffer_get_current (b0);
- hicn_lifetime_t imsg_lifetime;
- hicn_type_t type = hicnb0->type;
- hicn_ops_vft[type.l1]->get_lifetime (type, &hicn0->protocol, &imsg_lifetime);
-
- if (imsg_lifetime > sm->pit_lifetime_max_ms)
- {
- imsg_lifetime = sm->pit_lifetime_max_ms;
- }
-
- pitp->shared.expire_time = hicn_pcs_get_exp_time (tnow, imsg_lifetime);
-
- /* Set up the hash node and insert it */
- hicn_hash_entry_t *hash_entry;
- hicn_hashtb_init_node (rt->pitcs->pcs_table, nodep, nameptr, namelen);
-
- ret = hicn_pcs_pit_insert (rt->pitcs, pitp, nodep, &hash_entry,
- hicnb0->name_hash, &node_id0, &dpo_ctx_id0,
- &vft_id0, &is_cs0, &hash_entry_id, &bucket_id,
- &bucket_is_overflow);
-
- if (ret == HICN_ERROR_NONE)
- {
- strategy->hicn_add_interest (vnet_buffer (b0)->ip.adj_index[VLIB_TX],
- hash_entry);
-
- /* Add face */
- hicn_face_db_add_face (hicnb0->face_id, &(pitp->u.pit.faces));
+ *next0 = HICN_STRATEGY_NEXT_ERROR_DROP;
- *next = isv6 ? HICN_STRATEGY_NEXT_INTEREST_FACE6 :
- HICN_STRATEGY_NEXT_INTEREST_FACE4;
-
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = outface;
- stats->pkts_interest_count++;
- pitp->u.pit.pe_txnh = nh_idx;
- }
- else
- {
- /* Interest aggregate in PIT */
- if (ret == HICN_ERROR_HASHTB_EXIST)
- {
- hicn_store_internal_state (b0, hicnb0->name_hash, node_id0,
- dpo_ctx_id0, vft_id0, hash_entry_id,
- bucket_id, bucket_is_overflow);
- // We need to take a lock as the lock is not taken on the hash
- // entry because it is a CS entry (hash_insert function).
- if (is_cs0)
- {
- hash_entry->locks++;
- *next = HICN_STRATEGY_NEXT_INTEREST_HITCS;
- }
- else
- {
- *next = HICN_STRATEGY_NEXT_INTEREST_HITPIT;
- }
- }
- else
- {
- /* Send the packet to the interest-hitpit node */
- *next = HICN_STRATEGY_NEXT_ERROR_DROP;
- }
- hicn_faces_flush (&(pitp->u.pit.faces));
- hicn_hashtb_free_node (rt->pitcs->pcs_table, nodep);
- }
+ (*to_next)[0] = bi0;
+ *to_next += 1;
+ *n_left_to_next -= 1;
- return (ret);
+ vlib_validate_buffer_enqueue_x1 (vm, node, *next_index, *to_next,
+ *n_left_to_next, bi0, *next0);
}
/*
@@ -183,11 +83,22 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_frame_t *frame)
{
+ int ret;
u32 n_left_from, *from, *to_next, n_left_to_next;
hicn_strategy_next_t next_index;
hicn_strategy_runtime_t *rt = NULL;
vl_api_hicn_api_node_stats_get_reply_t stats = { 0 };
f64 tnow;
+ vlib_buffer_t *b0;
+ u32 bi0;
+ hicn_face_id_t outfaces[MAX_OUT_FACES];
+ u32 clones[MAX_OUT_FACES];
+ u16 outfaces_len;
+ u32 next0;
+ const hicn_dpo_ctx_t *dpo_ctx;
+ const hicn_strategy_vft_t *strategy;
+ hicn_buffer_t *hicnb0;
+ hicn_pcs_entry_t *pcs_entry = NULL;
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
@@ -196,6 +107,7 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
rt->pitcs = &hicn_main.pitcs;
/* Capture time in vpp terms */
tnow = vlib_time_now (vm);
+ next0 = next_index;
while (n_left_from > 0)
{
@@ -203,71 +115,87 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
while (n_left_from > 0 && n_left_to_next > 0)
{
- u8 *nameptr;
- u16 namelen;
- vlib_buffer_t *b0;
- u32 bi0;
- hicn_face_id_t outfaces[MAX_OUT_FACES];
- u32 outfaces_len;
- int nh_idx;
- u32 next0 = next_index;
-
- /* Prefetch for next iteration. */
+ // Prefetch for next iteration
if (n_left_from > 1)
{
vlib_buffer_t *b1;
b1 = vlib_get_buffer (vm, from[1]);
CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, LOAD);
}
- /* Dequeue a packet buffer */
+
+ // Dequeue a packet buffer
bi0 = from[0];
from += 1;
n_left_from -= 1;
-
b0 = vlib_get_buffer (vm, bi0);
+
+ // Drop by default
next0 = HICN_STRATEGY_NEXT_ERROR_DROP;
- hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (
+ // Increment counters
+ stats.pkts_processed++;
+
+ hicnb0 = hicn_get_buffer (b0);
+
+ // Get the strategy VFT
+ hicnb0->dpo_ctx_id = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
+ dpo_ctx = hicn_strategy_dpo_ctx_get (hicnb0->dpo_ctx_id);
+ hicnb0->vft_id = dpo_ctx->dpo_type;
+ strategy = hicn_dpo_get_strategy_vft (hicnb0->vft_id);
+ strategy->hicn_add_interest (hicnb0->dpo_ctx_id);
+
+ // Check we have at least one next hop for the packet
+ ret = strategy->hicn_select_next_hop (hicnb0->dpo_ctx_id, outfaces,
+ &outfaces_len);
+
+ if (PREDICT_FALSE (ret != HICN_ERROR_NONE || outfaces_len == 0))
+ {
+ drop_packet (vm, bi0, &n_left_from, &next0, &to_next,
+ &next_index, node);
+ continue;
+ }
+
+ // Create a new PIT entry
+ pcs_entry = hicn_pcs_entry_pit_get (rt->pitcs, tnow,
+ hicn_buffer_get_lifetime (b0));
+
+ // Add entry to PIT table
+ ret = hicn_pcs_pit_insert (rt->pitcs, pcs_entry, &hicnb0->name);
+
+ if (PREDICT_FALSE (ret != HICN_ERROR_NONE))
+ {
+ drop_packet (vm, bi0, &n_left_from, &next0, &to_next,
+ &next_index, node);
+ continue;
+ }
+
+ // Store internal state
+ ret = hicn_store_internal_state (
+ b0, hicn_pcs_entry_get_index (rt->pitcs, pcs_entry),
vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
- if (PREDICT_FALSE (!dpo_ctx))
+ if (PREDICT_FALSE (ret != HICN_ERROR_NONE))
{
- to_next[0] = bi0;
- to_next += 1;
- n_left_to_next -= 1;
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
+ hicn_pcs_entry_remove_lock (rt->pitcs, pcs_entry);
+ drop_packet (vm, bi0, &n_left_from, &next0, &to_next,
+ &next_index, node);
continue;
}
- const hicn_strategy_vft_t *strategy =
- hicn_dpo_get_strategy_vft (dpo_ctx->dpo_type);
+ // Add face
+ hicn_pcs_entry_pit_add_face (pcs_entry, hicnb0->face_id);
- hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen);
+ // Set next node
+ next0 = hicn_buffer_is_v6 (b0) ? HICN_STRATEGY_NEXT_INTEREST_FACE6 :
+ HICN_STRATEGY_NEXT_INTEREST_FACE4;
- stats.pkts_processed++;
- /* Select next hop */
- /*
- * Double check that the interest has been through
- * the interest-pcslookup node due to misconfiguration in
- * the punting rules.
- */
- if (PREDICT_TRUE (HICN_IS_NAMEHASH_CACHED (b0) &&
- strategy->hicn_select_next_hop (
- vnet_buffer (b0)->ip.adj_index[VLIB_TX], &nh_idx,
- outfaces, &outfaces_len) == HICN_ERROR_NONE))
+ if (PREDICT_TRUE (ret == HICN_ERROR_NONE))
{
- /*
- * No need to check if parsing was successful
- * here. Already checked in the interest_pcslookup
- * node
- */
- u32 clones[outfaces_len];
+ // Clone interest if needed
if (outfaces_len > 1)
{
- int ret = vlib_buffer_clone (vm, bi0, clones, outfaces_len,
- CLIB_CACHE_LINE_BYTES * 2);
+ ret = vlib_buffer_clone (vm, bi0, clones, (u16) outfaces_len,
+ CLIB_CACHE_LINE_BYTES * 2);
ASSERT (ret == outfaces_len);
}
else
@@ -275,6 +203,7 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
clones[0] = bi0;
}
+ // Send interest to next hops
for (u32 nh = 0; nh < outfaces_len; nh++)
{
vlib_buffer_t *local_b0 = vlib_get_buffer (vm, clones[nh]);
@@ -283,26 +212,10 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
to_next += 1;
n_left_to_next -= 1;
- if (nh == 0)
- {
- // send first interest
- hicn_new_interest (
- rt, local_b0, &next0, tnow, nameptr, namelen,
- outfaces[nh], nh_idx,
- vnet_buffer (local_b0)->ip.adj_index[VLIB_TX],
- strategy, dpo_ctx->dpo_type, &stats, 0);
- }
- else
- {
- // send duplicated interests, avoid aggregation/drop
- hicn_new_interest (
- rt, local_b0, &next0, tnow, nameptr, namelen,
- outfaces[nh], nh_idx,
- vnet_buffer (local_b0)->ip.adj_index[VLIB_TX],
- strategy, dpo_ctx->dpo_type, &stats, 1);
- }
+ vnet_buffer (local_b0)->ip.adj_index[VLIB_TX] = outfaces[nh];
+ stats.pkts_interest_count++;
- /* Maybe trace */
+ // Maybe trace
if (PREDICT_FALSE (
(node->flags & VLIB_NODE_FLAG_TRACE) &&
(local_b0->flags & VLIB_BUFFER_IS_TRACED)))
@@ -313,14 +226,10 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
t->sw_if_index =
vnet_buffer (local_b0)->sw_if_index[VLIB_RX];
t->next_index = next0;
- t->dpo_type = dpo_ctx->dpo_type;
+ t->dpo_type = hicnb0->vft_id;
}
/*
- * Verify speculative enqueue, maybe switch current
- * next frame
- */
- /*
* Fix in case of a wrong speculation. Needed for
* cloning the data in the right frame
*/
@@ -329,6 +238,11 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
clones[nh], next0);
}
}
+ else
+ {
+ drop_packet (vm, bi0, &n_left_from, &next0, &to_next,
+ &next_index, node);
+ }
}
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
diff --git a/hicn-plugin/src/test/CMakeLists.txt b/hicn-plugin/src/test/CMakeLists.txt
new file mode 100644
index 000000000..89ad24fbb
--- /dev/null
+++ b/hicn-plugin/src/test/CMakeLists.txt
@@ -0,0 +1,67 @@
+# Copyright (c) 2022 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.
+
+#############################################################
+# Dependencies
+#############################################################
+
+# We need a pure C test framework for the hicn-plugin.
+include (UnityTestFrameworkImport)
+find_package(Threads REQUIRED)
+
+##############################################################
+# Test sources
+##############################################################
+list(APPEND TESTS_SRC
+ main.c
+ vpp.c
+ test_pcs.c
+)
+
+
+##############################################################
+# Link libraries
+##############################################################
+set(TEST_LIBRARIES
+ ${VPP_LIBRARIES}
+ ${UNITY_LIBRARIES}
+ ${LIBHICN_SHARED}
+ ${HICNPLUGIN_SHARED}
+ Threads::Threads
+)
+
+set (
+ LINK_FLAGS
+ "-Wl,-unresolved-symbols=ignore-all"
+)
+
+
+##############################################################
+# Build single unit test executable and add it to test list
+##############################################################
+build_executable(hicnplugin_tests
+ NO_INSTALL
+ SOURCES ${TESTS_SRC}
+ LINK_LIBRARIES
+ ${TEST_LIBRARIES}
+ INCLUDE_DIRS
+ $<TARGET_PROPERTY:${HICNPLUGIN_SHARED},INCLUDE_DIRECTORIES>
+ ${UNITY_INCLUDE_DIRS}
+ DEPENDS unity ${HICNPLUGIN_SHARED}
+ COMPONENT ${HICN_PLUGIN}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+ LINK_FLAGS ${LINK_FLAGS}
+)
+
+unity_add_test_internal(hicnplugin_tests)
diff --git a/hicn-plugin/src/test/main.c b/hicn-plugin/src/test/main.c
new file mode 100644
index 000000000..82caba18a
--- /dev/null
+++ b/hicn-plugin/src/test/main.c
@@ -0,0 +1,31 @@
+
+/*
+ * Copyright (c) 20022 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.
+ */
+
+#include <unity_fixture.h>
+#include "vpp.h"
+
+static void
+RunAllTests (void)
+{
+ RUN_TEST_GROUP (PCS);
+}
+
+int
+main (int argc, const char *argv[])
+{
+ vpp_init ();
+ return UnityMain (argc, argv, RunAllTests);
+} \ No newline at end of file
diff --git a/hicn-plugin/src/test/test_pcs.c b/hicn-plugin/src/test/test_pcs.c
new file mode 100644
index 000000000..8e7416b8b
--- /dev/null
+++ b/hicn-plugin/src/test/test_pcs.c
@@ -0,0 +1,622 @@
+/*
+ * Copyright (c) 20022 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.
+ */
+
+#define HICN_PCS_TESTING
+#include "vpp.h"
+#include <pcs.h>
+
+#include <unity.h>
+#include <unity_fixture.h>
+
+/*
+ * Global PCS instance common to each test
+ */
+static hicn_pit_cs_t global_pcs;
+
+TEST_GROUP (PCS);
+
+/**
+ * Default PIT elements
+ */
+#define MAX_PIT_ELEMENTS 1000000
+
+/**
+ * Default CS elements
+ */
+#define MAX_CS_ELEMENTS (MAX_PIT_ELEMENTS / 10)
+
+TEST_SETUP (PCS)
+{
+ hicn_pit_cs_t *pcs = &global_pcs;
+ hicn_pit_create (pcs, MAX_PIT_ELEMENTS, MAX_CS_ELEMENTS);
+}
+
+TEST_TEAR_DOWN (PCS)
+{
+ hicn_pit_cs_t *pcs = &global_pcs;
+ hicn_pit_destroy (pcs);
+}
+
+TEST (PCS, Create)
+{
+ hicn_pit_cs_t *pcs = &global_pcs;
+
+ // Check counters
+ TEST_ASSERT_EQUAL (0, pcs->pcs_pit_count);
+ TEST_ASSERT_EQUAL (0, pcs->pcs_cs_count);
+ TEST_ASSERT_EQUAL (0, pcs->pcs_pcs_alloc);
+ TEST_ASSERT_EQUAL (0, pcs->pcs_pcs_dealloc);
+ TEST_ASSERT_EQUAL (MAX_PIT_ELEMENTS, pcs->max_pit_size);
+ TEST_ASSERT_EQUAL (MAX_CS_ELEMENTS, pcs->policy_state.max);
+
+ printf ("PIT entry size: %lu", sizeof (hicn_pcs_entry_t));
+}
+
+TEST (PCS, Destroy)
+{
+ // Global PCS instance
+}
+
+TEST (PCS, LookupEmpty)
+{
+ hicn_pit_cs_t *pcs = &global_pcs;
+
+ hicn_name_t name;
+ int ret = hicn_name_create ("b001::abcd", 0, &name);
+ TEST_ASSERT_EQUAL (0, ret);
+
+ hicn_pcs_entry_t *pcs_entry;
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry);
+
+ TEST_ASSERT_EQUAL (HICN_ERROR_PCS_NOT_FOUND, ret);
+ TEST_ASSERT_EQUAL (NULL, pcs_entry);
+}
+
+TEST (PCS, InsertPITEntryAndLookup)
+{
+ hicn_pit_cs_t *pcs = &global_pcs;
+
+ // Add entry to the PCS
+ int ret = 0;
+
+ // Allocate name
+ hicn_name_t name;
+ hicn_name_create ("b001::1234", 0, &name);
+
+ // Create PCS entry
+ hicn_pcs_entry_t *pcs_entry;
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry);
+
+ // We will not find the entry
+ TEST_ASSERT_EQUAL (ret, HICN_ERROR_PCS_NOT_FOUND);
+ TEST_ASSERT_EQUAL (NULL, pcs_entry);
+
+ // Get a new PIT entry from the pool
+ // TODO Check if the hicn_pcs_entry_pit_get is needed here
+ pcs_entry = hicn_pcs_entry_pit_get (pcs, 0, 0);
+ TEST_ASSERT_NOT_NULL (pcs_entry);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pcs_alloc (pcs), 1);
+
+ // Insert PIT entry
+ ret = hicn_pcs_pit_insert (pcs, pcs_entry, &name);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pit_count (pcs), 1);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_cs_count (pcs), 0);
+
+ // Lookup PIT entry
+ hicn_pcs_entry_t *pcs_entry_ret = NULL;
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry_ret);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_NOT_NULL (pcs_entry_ret);
+ TEST_ASSERT_EQUAL (pcs_entry, pcs_entry_ret);
+
+ // Release PIT entry
+ hicn_pcs_entry_remove_lock (pcs, pcs_entry);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pcs_dealloc (pcs), 1);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pit_count (pcs), 0);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_cs_count (pcs), 0);
+
+ // Lookup PIT entry again, we should not find it
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry_ret);
+ TEST_ASSERT_EQUAL (HICN_ERROR_PCS_NOT_FOUND, ret);
+ TEST_ASSERT_EQUAL (NULL, pcs_entry_ret);
+}
+
+TEST (PCS, InsertCSEntryAndLookup)
+{
+ hicn_pit_cs_t *pcs = &global_pcs;
+
+ // Add entry to the PCS
+ int ret = 0;
+
+ // Allocate name
+ hicn_name_t name;
+ hicn_name_create ("b008::5555", 0, &name);
+
+ // Create PCS entry
+ hicn_pcs_entry_t *pcs_entry;
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry);
+
+ // We will not find the entry
+ TEST_ASSERT_EQUAL (ret, HICN_ERROR_PCS_NOT_FOUND);
+ TEST_ASSERT_EQUAL (NULL, pcs_entry);
+
+ // Get a buffer
+ u32 buffer_index = 198274;
+
+ // Get a new entry from the pool
+ pcs_entry = hicn_pcs_entry_cs_get (pcs, 0, buffer_index);
+ TEST_ASSERT_NOT_NULL (pcs_entry);
+ TEST_ASSERT_EQUAL (1, hicn_pcs_get_pcs_alloc (pcs));
+
+ // Insert CS entry
+ ret = hicn_pcs_cs_insert (pcs, pcs_entry, &name);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pit_count (pcs), 0);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_cs_count (pcs), 1);
+
+ // Lookup CS entry
+ hicn_pcs_entry_t *pcs_entry_ret = NULL;
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry_ret);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_TRUE (pcs_entry_ret->flags & HICN_PCS_ENTRY_CS_FLAG);
+ TEST_ASSERT_NOT_NULL (pcs_entry_ret);
+ TEST_ASSERT_EQUAL (pcs_entry, pcs_entry_ret);
+
+ // Release CS entry
+ hicn_pcs_entry_remove_lock (pcs, pcs_entry);
+ TEST_ASSERT_EQUAL (1, hicn_pcs_get_pcs_dealloc (pcs));
+ TEST_ASSERT_EQUAL (0, hicn_pcs_get_pit_count (pcs));
+ TEST_ASSERT_EQUAL (0, hicn_pcs_get_cs_count (pcs));
+
+ // Lookup CS entry again, we should not find it
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry_ret);
+ TEST_ASSERT_EQUAL (HICN_ERROR_PCS_NOT_FOUND, ret);
+ TEST_ASSERT_EQUAL (NULL, pcs_entry_ret);
+}
+
+TEST (PCS, PitToCS)
+{
+ hicn_pit_cs_t *pcs = &global_pcs;
+
+ // Add entry to the PCS
+ int ret = 0;
+
+ // Allocate name
+ hicn_name_t name;
+ hicn_name_create ("b001::1234", 0, &name);
+
+ // Create PCS entry
+ hicn_pcs_entry_t *pcs_entry;
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry);
+
+ // We will not find the entry
+ TEST_ASSERT_EQUAL (ret, HICN_ERROR_PCS_NOT_FOUND);
+ TEST_ASSERT_EQUAL (NULL, pcs_entry);
+
+ // Get a new entry from the pool
+ // TODO Check if the hicn_pcs_entry_pit_get is needed here
+ pcs_entry = hicn_pcs_entry_pit_get (pcs, 0, 0);
+ TEST_ASSERT_NOT_NULL (pcs_entry);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pcs_alloc (pcs), 1);
+
+ // Insert PIT entry
+ ret = hicn_pcs_pit_insert (pcs, pcs_entry, &name);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pit_count (pcs), 1);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_cs_count (pcs), 0);
+
+ // Lookup PIT entry
+ hicn_pcs_entry_t *pcs_entry_ret = NULL;
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry_ret);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_NOT_NULL (pcs_entry_ret);
+ TEST_ASSERT_EQUAL (pcs_entry, pcs_entry_ret);
+
+ // Found the PIT entry we inserted before.
+ // Double check is not a CS
+ TEST_ASSERT_FALSE (pcs_entry_ret->flags & HICN_PCS_ENTRY_CS_FLAG);
+
+ // Turn the PIT entry into a CS
+ hicn_pit_to_cs (pcs, pcs_entry, /* random buffer index */ 12345);
+
+ // Check counters
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pit_count (pcs), 0);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_cs_count (pcs), 1);
+
+ // Make sure entry is now a CS
+ TEST_ASSERT_TRUE (pcs_entry_ret->flags & HICN_PCS_ENTRY_CS_FLAG);
+}
+
+TEST (PCS, CheckCSLruConsistency)
+{
+ hicn_pit_cs_t *pcs = &global_pcs;
+
+ // Add entry to the PCS
+ int ret = 0;
+
+ // Allocate name
+ hicn_name_t name;
+ hicn_name_create ("b001::1234", 0, &name);
+
+ // Create CS entry
+ hicn_pcs_entry_t *pcs_entry;
+ // Get a new entry from the pool
+ // TODO Check if the hicn_pcs_entry_pit_get is needed here
+ pcs_entry = hicn_pcs_entry_cs_get (pcs, 0, 0);
+ TEST_ASSERT_NOT_NULL (pcs_entry);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pcs_alloc (pcs), 1);
+
+ // Insert CS entry
+ ret = hicn_pcs_cs_insert (pcs, pcs_entry, &name);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_cs_count (pcs), 1);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pit_count (pcs), 0);
+
+ // Get pcs_entry index
+ uint32_t pcs_entry_index = hicn_pcs_entry_get_index (pcs, pcs_entry);
+
+ // Check LRU
+ hicn_cs_policy_t *policy_state = hicn_pcs_get_policy_state (pcs);
+
+ // Make sure MAX corresponds to what we set
+ TEST_ASSERT_EQUAL (MAX_CS_ELEMENTS, hicn_cs_policy_get_max (policy_state));
+
+ TEST_ASSERT_EQUAL (pcs_entry_index, hicn_cs_policy_get_head (policy_state));
+ TEST_ASSERT_EQUAL (pcs_entry_index, hicn_cs_policy_get_tail (policy_state));
+ TEST_ASSERT_EQUAL (1, hicn_cs_policy_get_count (policy_state));
+
+ // Check pointers of the entry
+ TEST_ASSERT_EQUAL (HICN_CS_POLICY_END_OF_CHAIN,
+ hicn_pcs_entry_cs_get_next (pcs_entry));
+ TEST_ASSERT_EQUAL (HICN_CS_POLICY_END_OF_CHAIN,
+ hicn_pcs_entry_cs_get_prev (pcs_entry));
+
+ // Lookup the entry itself
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry);
+
+ // Check again the pointers of the entry
+ TEST_ASSERT_EQUAL (HICN_CS_POLICY_END_OF_CHAIN,
+ hicn_pcs_entry_cs_get_next (pcs_entry));
+ TEST_ASSERT_EQUAL (HICN_CS_POLICY_END_OF_CHAIN,
+ hicn_pcs_entry_cs_get_prev (pcs_entry));
+
+ // Remove CS entry
+ hicn_pcs_entry_remove_lock (pcs, pcs_entry);
+ TEST_ASSERT_EQUAL (1, hicn_pcs_get_pcs_dealloc (pcs));
+ TEST_ASSERT_EQUAL (0, hicn_pcs_get_pit_count (pcs));
+ TEST_ASSERT_EQUAL (0, hicn_pcs_get_cs_count (pcs));
+
+ // Check again LRU
+ TEST_ASSERT_EQUAL (HICN_CS_POLICY_END_OF_CHAIN,
+ hicn_cs_policy_get_head (policy_state));
+ TEST_ASSERT_EQUAL (HICN_CS_POLICY_END_OF_CHAIN,
+ hicn_cs_policy_get_tail (policy_state));
+ TEST_ASSERT_EQUAL (0, hicn_cs_policy_get_count (policy_state));
+
+ // Let's insert now 2 entries
+ hicn_pcs_entry_t *pcs_entry0;
+ hicn_pcs_entry_t *pcs_entry1;
+
+ pcs_entry0 = hicn_pcs_entry_cs_get (pcs, 0, 0);
+ TEST_ASSERT_NOT_NULL (pcs_entry0);
+ hicn_name_t name0;
+ hicn_name_create ("b001::abcd", 123, &name0);
+ u32 index0 = hicn_pcs_entry_get_index (pcs, pcs_entry0);
+
+ pcs_entry1 = hicn_pcs_entry_cs_get (pcs, 0, 0);
+ TEST_ASSERT_NOT_NULL (pcs_entry1);
+ hicn_name_t name1;
+ hicn_name_create ("b001::9999", 321, &name1);
+ u32 index1 = hicn_pcs_entry_get_index (pcs, pcs_entry1);
+
+ // Insert CS entry
+ ret = hicn_pcs_cs_insert (pcs, pcs_entry0, &name0);
+ ret = hicn_pcs_cs_insert (pcs, pcs_entry1, &name1);
+
+ // Check LRU. index1 was inserted last, so it should be at the head
+ TEST_ASSERT_EQUAL (index1, hicn_cs_policy_get_head (policy_state));
+ // index0 was inserted first, so it should be at the tail
+ TEST_ASSERT_EQUAL (index0, hicn_cs_policy_get_tail (policy_state));
+ // And count shoould be 2
+ TEST_ASSERT_EQUAL (2, hicn_cs_policy_get_count (policy_state));
+
+ // Check pointers of the entries
+
+ // pcs_entry0 should be at the tail
+ TEST_ASSERT_EQUAL (HICN_CS_POLICY_END_OF_CHAIN,
+ hicn_pcs_entry_cs_get_next (pcs_entry0));
+ TEST_ASSERT_EQUAL (index1, hicn_pcs_entry_cs_get_prev (pcs_entry0));
+
+ // pcs_entry1 should be at the head
+ TEST_ASSERT_EQUAL (index0, hicn_pcs_entry_cs_get_next (pcs_entry1));
+ TEST_ASSERT_EQUAL (HICN_CS_POLICY_END_OF_CHAIN,
+ hicn_pcs_entry_cs_get_prev (pcs_entry1));
+
+ // Let's lookup for entry 0 and check if the LRU is updated correctly
+ ret = hicn_pcs_lookup_one (pcs, &name0, &pcs_entry);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_EQUAL (index0, hicn_pcs_entry_get_index (pcs, pcs_entry));
+
+ // Check pointers of the entries
+
+ // pcs_entry1 should be at the tail
+ TEST_ASSERT_EQUAL (HICN_CS_POLICY_END_OF_CHAIN,
+ hicn_pcs_entry_cs_get_next (pcs_entry1));
+ TEST_ASSERT_EQUAL (index0, hicn_pcs_entry_cs_get_prev (pcs_entry1));
+
+ // pcs_entry0 should be at the head
+ TEST_ASSERT_EQUAL (index1, hicn_pcs_entry_cs_get_next (pcs_entry0));
+ TEST_ASSERT_EQUAL (HICN_CS_POLICY_END_OF_CHAIN,
+ hicn_pcs_entry_cs_get_prev (pcs_entry0));
+
+ // index0 should be now the head
+ TEST_ASSERT_EQUAL (index0, hicn_cs_policy_get_head (policy_state));
+ // index1 should be now the tail
+ TEST_ASSERT_EQUAL (index1, hicn_cs_policy_get_tail (policy_state));
+}
+
+TEST (PCS, CheckCSLruMax)
+{
+ hicn_pit_cs_t *pcs = &global_pcs;
+ int i, ret = 0;
+ ;
+ u32 pcs_entry_index = 0;
+ u32 pcs_entry_index0 = 0;
+ u32 pcs_entry_index1 = 0;
+ hicn_pcs_entry_t *pcs_entry = NULL;
+ hicn_name_t name;
+
+ const hicn_cs_policy_t *policy_state = hicn_pcs_get_policy_state (pcs);
+
+ for (i = 0; i < MAX_CS_ELEMENTS; i++)
+ {
+ // Allocate name
+ ret = hicn_name_create ("b004::aaaa", i, &name);
+ TEST_ASSERT_EQUAL (0, ret);
+
+ // Create CS entry
+ // Get a new entry from the pool
+ // TODO Check if the hicn_pcs_entry_pit_get is needed here
+ pcs_entry = hicn_pcs_entry_cs_get (pcs, 0, i);
+ TEST_ASSERT_NOT_NULL (pcs_entry);
+ TEST_ASSERT_EQUAL (i + 1, hicn_pcs_get_pcs_alloc (pcs));
+
+ pcs_entry_index = hicn_pcs_entry_get_index (pcs, pcs_entry);
+
+ if (i == 0)
+ {
+ pcs_entry_index0 = pcs_entry_index;
+ }
+
+ if (i == 1)
+ {
+ pcs_entry_index1 = pcs_entry_index;
+ }
+
+ // Insert CS entry
+ ret = hicn_pcs_cs_insert (pcs, pcs_entry, &name);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_cs_count (pcs), i + 1);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pit_count (pcs), 0);
+
+ // Check LRU
+ TEST_ASSERT_EQUAL (pcs_entry_index,
+ hicn_cs_policy_get_head (policy_state));
+ TEST_ASSERT_EQUAL (pcs_entry_index0,
+ hicn_cs_policy_get_tail (policy_state));
+ TEST_ASSERT_EQUAL (i + 1, hicn_cs_policy_get_count (policy_state));
+ }
+
+ // In this moment the CS should be full
+ TEST_ASSERT_EQUAL (hicn_cs_policy_get_max (policy_state),
+ hicn_cs_policy_get_count (policy_state));
+
+ // Next insertion should:
+ // - evict the tail
+ // - update the head
+ // - make a coffee because I am tired
+ ret = hicn_name_create ("b004::aaaa", i, &name);
+ TEST_ASSERT_EQUAL (0, ret);
+
+ pcs_entry = hicn_pcs_entry_cs_get (pcs, 0, i);
+ TEST_ASSERT_NOT_NULL (pcs_entry);
+ TEST_ASSERT_EQUAL (i + 1, hicn_pcs_get_pcs_alloc (pcs));
+
+ pcs_entry_index = hicn_pcs_entry_get_index (pcs, pcs_entry);
+
+ // Insert CS entry
+ ret = hicn_pcs_cs_insert (pcs, pcs_entry, &name);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_cs_count (pcs), i);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pit_count (pcs), 0);
+
+ // Check LRU
+ TEST_ASSERT_EQUAL (pcs_entry_index, hicn_cs_policy_get_head (policy_state));
+ // pcs_entry_index1 should be have eveicted, and pcs_entry_index1 should be
+ // the tail
+ TEST_ASSERT_EQUAL (pcs_entry_index1, hicn_cs_policy_get_tail (policy_state));
+
+ // Make pcs_entry_index0 was freed.
+ TEST_ASSERT_TRUE (
+ pool_is_free_index (pcs->pcs_entries_pool, pcs_entry_index0));
+}
+
+TEST (PCS, AddIngressFacesToPITEntry)
+{
+ hicn_pit_cs_t *pcs = &global_pcs;
+
+ // Add entry to the PCS
+ int ret = 0;
+
+ // Allocate name
+ hicn_name_t name;
+ hicn_name_create ("b001::9876", 0, &name);
+
+ // Create PCS entry
+ hicn_pcs_entry_t *pcs_entry;
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry);
+
+ // We will not find the entry
+ TEST_ASSERT_EQUAL (ret, HICN_ERROR_PCS_NOT_FOUND);
+ TEST_ASSERT_EQUAL (NULL, pcs_entry);
+
+ // Get a new entry from the pool
+ // TODO Check if the hicn_pcs_entry_pit_get is needed here
+ f64 tnow = 10.0;
+ pcs_entry = hicn_pcs_entry_pit_get (pcs, tnow, 0);
+ TEST_ASSERT_NOT_NULL (pcs_entry);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pcs_alloc (pcs), 1);
+
+ const u32 faceid = 20;
+
+ // The face should not be in the PIT entry
+ TEST_ASSERT_EQUAL (0, hicn_pcs_entry_pit_search (pcs_entry, faceid));
+
+ // Add ingress face to pit entry
+ hicn_pcs_entry_pit_add_face (pcs_entry, faceid);
+
+ // Insert PIT entry
+ ret = hicn_pcs_pit_insert (pcs, pcs_entry, &name);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pit_count (pcs), 1);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_cs_count (pcs), 0);
+
+ // Lookup PIT entry
+ hicn_pcs_entry_t *pcs_entry_ret = NULL;
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry_ret);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_NOT_NULL (pcs_entry_ret);
+ TEST_ASSERT_EQUAL (pcs_entry, pcs_entry_ret);
+
+ // Check everything is fine
+ ret = hicn_pcs_entry_pit_search (pcs_entry_ret, faceid);
+ // Face 20 should be in the entry
+ TEST_ASSERT_EQUAL (ret, 1);
+
+ // Get faces and make sure
+ // - there is only one face
+ // - the face is 20
+ TEST_ASSERT_EQUAL (1, hicn_pcs_entry_pit_get_n_faces (pcs_entry_ret));
+ TEST_ASSERT_EQUAL (20, hicn_pcs_entry_pit_get_dpo_face (pcs_entry_ret, 0));
+
+ // Release PIT entry
+ hicn_pcs_entry_remove_lock (pcs, pcs_entry_ret);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pcs_dealloc (pcs), 1);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pit_count (pcs), 0);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_cs_count (pcs), 0);
+
+ // Lookup PIT entry again, we should not find it
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry_ret);
+ TEST_ASSERT_EQUAL (HICN_ERROR_PCS_NOT_FOUND, ret);
+ TEST_ASSERT_EQUAL (NULL, pcs_entry_ret);
+}
+
+TEST (PCS, AddIngressFacesToPitEntryCornerCases)
+{
+ hicn_pit_cs_t *pcs = &global_pcs;
+
+ // Add entry to the PCS
+ int ret = 0;
+
+ // Allocate name
+ hicn_name_t name;
+ hicn_name_create ("b001::9876", 0, &name);
+
+ // Create PCS entry
+ hicn_pcs_entry_t *pcs_entry;
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry);
+
+ // We will not find the entry
+ TEST_ASSERT_EQUAL (ret, HICN_ERROR_PCS_NOT_FOUND);
+ TEST_ASSERT_EQUAL (NULL, pcs_entry);
+
+ // Get a new entry from the pool
+ // TODO Check if the hicn_pcs_entry_pit_get is needed here
+ f64 tnow = 10.0;
+ pcs_entry = hicn_pcs_entry_pit_get (pcs, tnow, 0);
+ TEST_ASSERT_NOT_NULL (pcs_entry);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pcs_alloc (pcs), 1);
+
+ // Let's initialize HICN_FACE_DB_INLINE_FACES + 1 face IDs
+ u32 faceids[HICN_FACE_DB_INLINE_FACES + 1];
+ for (u32 i = 0; i < HICN_FACE_DB_INLINE_FACES + 1; i++)
+ faceids[i] = rand () % HICN_PARAM_FACES_MAX;
+
+ // The faces should not be in the PIT entry
+ for (u32 i = 0; i < HICN_FACE_DB_INLINE_FACES + 1; i++)
+ TEST_ASSERT_EQUAL (0, hicn_pcs_entry_pit_search (pcs_entry, faceids[i]));
+
+ // Add ingress faces to pit entry
+ for (u32 i = 0; i < HICN_FACE_DB_INLINE_FACES + 1; i++)
+ hicn_pcs_entry_pit_add_face (pcs_entry, faceids[i]);
+
+ // Insert PIT entry
+ ret = hicn_pcs_pit_insert (pcs, pcs_entry, &name);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pit_count (pcs), 1);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_cs_count (pcs), 0);
+
+ // Lookup PIT entry
+ hicn_pcs_entry_t *pcs_entry_ret = NULL;
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry_ret);
+ TEST_ASSERT_EQUAL (HICN_ERROR_NONE, ret);
+ TEST_ASSERT_NOT_NULL (pcs_entry_ret);
+ TEST_ASSERT_EQUAL (pcs_entry, pcs_entry_ret);
+
+ // Check everything is fine
+ for (u32 i = 0; i < HICN_FACE_DB_INLINE_FACES + 1; i++)
+ {
+ ret = hicn_pcs_entry_pit_search (pcs_entry_ret, faceids[i]);
+ // Face 20 should be in the entry
+ TEST_ASSERT_EQUAL (1, ret);
+ }
+
+ // Get faces and make sure
+ // - there are HICN_FACE_DB_INLINE_FACES + 1 faces
+ // - the first HICN_FACE_DB_INLINE_FACES are stored in the PIT entry
+ // - the face HICN_FACE_DB_INLINE_FACES + 1 is stored in the array of
+ // additional faces, so outside PIT entry
+ TEST_ASSERT_EQUAL (HICN_FACE_DB_INLINE_FACES + 1,
+ hicn_pcs_entry_pit_get_n_faces (pcs_entry_ret));
+ for (u32 i = 0; i < HICN_FACE_DB_INLINE_FACES + 1; i++)
+ TEST_ASSERT_EQUAL (faceids[i],
+ hicn_pcs_entry_pit_get_dpo_face (pcs_entry_ret, i));
+
+ // Release PIT entry
+ hicn_pcs_entry_remove_lock (pcs, pcs_entry_ret);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pcs_dealloc (pcs), 1);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_pit_count (pcs), 0);
+ TEST_ASSERT_EQUAL (hicn_pcs_get_cs_count (pcs), 0);
+
+ // Lookup PIT entry again, we should not find it
+ ret = hicn_pcs_lookup_one (pcs, &name, &pcs_entry_ret);
+ TEST_ASSERT_EQUAL (HICN_ERROR_PCS_NOT_FOUND, ret);
+ TEST_ASSERT_EQUAL (NULL, pcs_entry_ret);
+}
+
+TEST_GROUP_RUNNER (PCS)
+{
+ RUN_TEST_CASE (PCS, Create)
+ RUN_TEST_CASE (PCS, Destroy)
+ RUN_TEST_CASE (PCS, LookupEmpty)
+ RUN_TEST_CASE (PCS, InsertPITEntryAndLookup)
+ RUN_TEST_CASE (PCS, InsertCSEntryAndLookup)
+ RUN_TEST_CASE (PCS, PitToCS)
+ RUN_TEST_CASE (PCS, CheckCSLruConsistency)
+ RUN_TEST_CASE (PCS, CheckCSLruMax)
+ RUN_TEST_CASE (PCS, AddIngressFacesToPITEntry)
+ RUN_TEST_CASE (PCS, AddIngressFacesToPitEntryCornerCases)
+}
diff --git a/hicn-plugin/src/test/vpp.c b/hicn-plugin/src/test/vpp.c
new file mode 100644
index 000000000..fc96e6e16
--- /dev/null
+++ b/hicn-plugin/src/test/vpp.c
@@ -0,0 +1,555 @@
+/*
+ * Copyright (c) 2022 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.
+ */
+
+#define _GNU_SOURCE
+#include <pthread.h>
+#include <sched.h>
+
+#include <vppinfra/cpu.h>
+#include <vlib/vlib.h>
+#include <vlib/unix/unix.h>
+#include <vlib/threads.h>
+#include <vnet/plugin/plugin.h>
+#include <vnet/ethernet/ethernet.h>
+#include <vpp/vnet/config.h>
+#include <vlibmemory/memclnt.api_enum.h> /* To get the last static message id */
+#include <limits.h>
+
+/*
+ * Load plugins from /usr/lib/vpp_plugins by default
+ */
+char *vlib_plugin_path = NULL;
+char *vat_plugin_path = NULL;
+
+static void
+vpp_find_plugin_path ()
+{
+ extern char *vat_plugin_path;
+ char *p, path[PATH_MAX];
+ int rv;
+ u8 *s;
+
+ /* find executable path */
+ if ((rv = readlink ("/proc/self/exe", path, PATH_MAX - 1)) == -1)
+ return;
+
+ /* readlink doesn't provide null termination */
+ path[rv] = 0;
+
+ /* strip filename */
+ if ((p = strrchr (path, '/')) == 0)
+ return;
+ *p = 0;
+
+ /* strip bin/ */
+ if ((p = strrchr (path, '/')) == 0)
+ return;
+ *p = 0;
+
+ s = format (0, "%s/" CLIB_LIB_DIR "/vpp_plugins", path, path);
+ vec_add1 (s, 0);
+ vlib_plugin_path = (char *) s;
+
+ s = format (0, "%s/" CLIB_LIB_DIR "/vpp_api_test_plugins", path, path);
+ vec_add1 (s, 0);
+ vat_plugin_path = (char *) s;
+}
+
+static void
+vpe_main_init (vlib_main_t *vm)
+{
+#if VPP_API_TEST_BUILTIN > 0
+ void vat_plugin_hash_create (void);
+#endif
+
+ if (CLIB_DEBUG > 0)
+ vlib_unix_cli_set_prompt ("DBGvpp# ");
+ else
+ vlib_unix_cli_set_prompt ("vpp# ");
+
+ /* Turn off network stack components which we don't want */
+ vlib_mark_init_function_complete (vm, srp_init);
+
+ /*
+ * Create the binary api plugin hashes before loading plugins
+ */
+#if VPP_API_TEST_BUILTIN > 0
+ vat_plugin_hash_create ();
+#endif
+
+ if (!vlib_plugin_path)
+ vpp_find_plugin_path ();
+}
+
+/*
+ * Default path for runtime data
+ */
+char *vlib_default_runtime_dir = "vpp";
+
+int
+vpp_init_internal (int argc, char *argv[])
+{
+ int i;
+ void vl_msg_api_set_first_available_msg_id (u16);
+ uword main_heap_size = (1ULL << 30);
+ u8 *sizep;
+ u32 size;
+ clib_mem_page_sz_t main_heap_log2_page_sz = CLIB_MEM_PAGE_SZ_DEFAULT;
+ clib_mem_page_sz_t default_log2_hugepage_sz = CLIB_MEM_PAGE_SZ_UNKNOWN;
+ unformat_input_t input, sub_input;
+ u8 *s = 0, *v = 0;
+ int main_core = 1;
+ cpu_set_t cpuset;
+ void *main_heap;
+
+#if __x86_64__
+ CLIB_UNUSED (const char *msg) =
+ "ERROR: This binary requires CPU with %s extensions.\n";
+#define _(a, b) \
+ if (!clib_cpu_supports_##a ()) \
+ { \
+ fprintf (stderr, msg, b); \
+ exit (1); \
+ }
+
+#if __AVX2__
+ _ (avx2, "AVX2")
+#endif
+#if __AVX__
+ _ (avx, "AVX")
+#endif
+#if __SSE4_2__
+ _ (sse42, "SSE4.2")
+#endif
+#if __SSE4_1__
+ _ (sse41, "SSE4.1")
+#endif
+#if __SSSE3__
+ _ (ssse3, "SSSE3")
+#endif
+#if __SSE3__
+ _ (sse3, "SSE3")
+#endif
+#undef _
+#endif
+ /*
+ * Load startup config from file.
+ * usage: vpp -c /etc/vpp/startup.conf
+ */
+ if ((argc == 3) && !strncmp (argv[1], "-c", 2))
+ {
+ FILE *fp;
+ char inbuf[4096];
+ int argc_ = 1;
+ char **argv_ = NULL;
+ char *arg = NULL;
+ char *p;
+
+ fp = fopen (argv[2], "r");
+ if (fp == NULL)
+ {
+ fprintf (stderr, "open configuration file '%s' failed\n", argv[2]);
+ return 1;
+ }
+ argv_ = calloc (1, sizeof (char *));
+ if (argv_ == NULL)
+ {
+ fclose (fp);
+ return 1;
+ }
+ arg = strndup (argv[0], 1024);
+ if (arg == NULL)
+ {
+ fclose (fp);
+ free (argv_);
+ return 1;
+ }
+ argv_[0] = arg;
+
+ while (1)
+ {
+ if (fgets (inbuf, 4096, fp) == 0)
+ break;
+ p = strtok (inbuf, " \t\n");
+ while (p != NULL)
+ {
+ if (*p == '#')
+ break;
+ argc_++;
+ char **tmp = realloc (argv_, argc_ * sizeof (char *));
+ if (tmp == NULL)
+ return 1;
+ argv_ = tmp;
+ arg = strndup (p, 1024);
+ if (arg == NULL)
+ return 1;
+ argv_[argc_ - 1] = arg;
+ p = strtok (NULL, " \t\n");
+ }
+ }
+
+ fclose (fp);
+
+ char **tmp = realloc (argv_, (argc_ + 1) * sizeof (char *));
+ if (tmp == NULL)
+ return 1;
+ argv_ = tmp;
+ argv_[argc_] = NULL;
+
+ argc = argc_;
+ argv = argv_;
+ }
+
+ /*
+ * Look for and parse the "heapsize" config parameter.
+ * Manual since none of the clib infra has been bootstrapped yet.
+ *
+ * Format: heapsize <nn>[mM][gG]
+ */
+
+ for (i = 1; i < (argc - 1); i++)
+ {
+ if (!strncmp (argv[i], "plugin_path", 11))
+ {
+ if (i < (argc - 1))
+ vlib_plugin_path = argv[++i];
+ }
+ if (!strncmp (argv[i], "test_plugin_path", 16))
+ {
+ if (i < (argc - 1))
+ vat_plugin_path = argv[++i];
+ }
+ else if (!strncmp (argv[i], "heapsize", 8))
+ {
+ sizep = (u8 *) argv[i + 1];
+ size = 0;
+ while (*sizep >= '0' && *sizep <= '9')
+ {
+ size *= 10;
+ size += *sizep++ - '0';
+ }
+ if (size == 0)
+ {
+ fprintf (
+ stderr,
+ "warning: heapsize parse error '%s', use default %lld\n",
+ argv[i], (long long int) main_heap_size);
+ goto defaulted;
+ }
+
+ main_heap_size = size;
+
+ if (*sizep == 'g' || *sizep == 'G')
+ main_heap_size <<= 30;
+ else if (*sizep == 'm' || *sizep == 'M')
+ main_heap_size <<= 20;
+ }
+ else if (!strncmp (argv[i], "main-core", 9))
+ {
+ if (i < (argc - 1))
+ {
+ errno = 0;
+ unsigned long x = strtol (argv[++i], 0, 0);
+ if (errno == 0)
+ main_core = x;
+ }
+ }
+ }
+defaulted:
+
+ /* temporary heap */
+ clib_mem_init (0, 1 << 20);
+ unformat_init_command_line (&input, (char **) argv);
+
+ while (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (&input, "memory %v", &v))
+ {
+ unformat_init_vector (&sub_input, v);
+ v = 0;
+ while (unformat_check_input (&sub_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (&sub_input, "main-heap-size %U",
+ unformat_memory_size, &main_heap_size))
+ ;
+ else if (unformat (&sub_input, "main-heap-page-size %U",
+ unformat_log2_page_size,
+ &main_heap_log2_page_sz))
+ ;
+ else if (unformat (&sub_input, "default-hugepage-size %U",
+ unformat_log2_page_size,
+ &default_log2_hugepage_sz))
+ ;
+ else
+ {
+ fformat (stderr, "unknown 'memory' config input '%U'\n",
+ format_unformat_error, &sub_input);
+ exit (1);
+ }
+ }
+ unformat_free (&sub_input);
+ }
+ else if (!unformat (&input, "%s %v", &s, &v))
+ break;
+
+ vec_reset_length (s);
+ vec_reset_length (v);
+ }
+ vec_free (s);
+ vec_free (v);
+
+ unformat_free (&input);
+
+ /* set process affinity for main thread */
+ CPU_ZERO (&cpuset);
+ CPU_SET (main_core, &cpuset);
+ pthread_setaffinity_np (pthread_self (), sizeof (cpu_set_t), &cpuset);
+
+ /* Set up the plugin message ID allocator right now... */
+ vl_msg_api_set_first_available_msg_id (VL_MSG_MEMCLNT_LAST + 1);
+
+ /* destroy temporary heap and create main one */
+ clib_mem_destroy ();
+
+ if ((main_heap = clib_mem_init_with_page_size (main_heap_size,
+ main_heap_log2_page_sz)))
+ {
+ /* Figure out which numa runs the main thread */
+ __os_numa_index = clib_get_current_numa_node ();
+
+ if (default_log2_hugepage_sz != CLIB_MEM_PAGE_SZ_UNKNOWN)
+ clib_mem_set_log2_default_hugepage_size (default_log2_hugepage_sz);
+
+ /* and use the main heap as that numa's numa heap */
+ clib_mem_set_per_numa_heap (main_heap);
+ vlib_main_init ();
+ vpe_main_init (vlib_get_first_main ());
+ return 0;
+ }
+ else
+ {
+ {
+ int rv __attribute__ ((unused)) =
+ write (2, "Main heap allocation failure!\r\n", 31);
+ }
+ return 1;
+ }
+}
+
+static clib_error_t *
+memory_config (vlib_main_t *vm, unformat_input_t *input)
+{
+ return 0;
+}
+
+VLIB_CONFIG_FUNCTION (memory_config, "memory");
+
+static clib_error_t *
+heapsize_config (vlib_main_t *vm, unformat_input_t *input)
+{
+ return 0;
+}
+
+VLIB_CONFIG_FUNCTION (heapsize_config, "heapsize");
+
+static clib_error_t *
+placeholder_path_config (vlib_main_t *vm, unformat_input_t *input)
+{
+ u8 *junk;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "%s", &junk))
+ {
+ vec_free (junk);
+ return 0;
+ }
+ else
+ return clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, input);
+ }
+ return 0;
+}
+
+static clib_error_t *
+plugin_path_config (vlib_main_t *vm, unformat_input_t *input)
+{
+ return placeholder_path_config (vm, input);
+}
+
+VLIB_CONFIG_FUNCTION (plugin_path_config, "plugin_path");
+
+static clib_error_t *
+test_plugin_path_config (vlib_main_t *vm, unformat_input_t *input)
+{
+ return placeholder_path_config (vm, input);
+}
+
+VLIB_CONFIG_FUNCTION (test_plugin_path_config, "test_plugin_path");
+
+void vl_msg_api_post_mortem_dump (void);
+void vlib_post_mortem_dump (void);
+
+void
+os_panic (void)
+{
+ vl_msg_api_post_mortem_dump ();
+ vlib_post_mortem_dump ();
+ abort ();
+}
+
+void vhost_user_unmap_all (void) __attribute__ ((weak));
+void
+vhost_user_unmap_all (void)
+{
+}
+
+void
+os_exit (int code)
+{
+ static int recursion_block;
+
+ if (code)
+ {
+ if (recursion_block)
+ abort ();
+
+ recursion_block = 1;
+
+ vl_msg_api_post_mortem_dump ();
+ vlib_post_mortem_dump ();
+ vhost_user_unmap_all ();
+ abort ();
+ }
+ exit (code);
+}
+
+#ifdef BARRIER_TRACING
+void
+vl_msg_api_barrier_trace_context (const char *context)
+{
+ vlib_worker_threads[0].barrier_context = context;
+}
+#endif
+
+void
+vl_msg_api_barrier_sync (void)
+{
+ vlib_worker_thread_barrier_sync (vlib_get_main ());
+}
+
+void
+vl_msg_api_barrier_release (void)
+{
+ vlib_worker_thread_barrier_release (vlib_get_main ());
+}
+
+/* This application needs 1 thread stack for the stats pthread */
+u32
+vlib_app_num_thread_stacks_needed (void)
+{
+ return 1;
+}
+
+/*
+ * Depending on the configuration selected above,
+ * it may be necessary to generate stub graph nodes.
+ * It is never OK to ignore "node 'x' refers to unknown node 'y'
+ * messages!
+ */
+
+#include <vppinfra/bihash_8_8.h>
+
+static clib_error_t *
+show_bihash_command_fn (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
+{
+ int i;
+ clib_bihash_8_8_t *h;
+ int verbose = 0;
+
+ if (unformat (input, "verbose"))
+ verbose = 1;
+
+ for (i = 0; i < vec_len (clib_all_bihashes); i++)
+ {
+ h = (clib_bihash_8_8_t *) clib_all_bihashes[i];
+ vlib_cli_output (vm, "\n%U", h->fmt_fn, h, verbose);
+ }
+
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (show_bihash_command, static) = {
+ .path = "show bihash",
+ .short_help = "show bihash",
+ .function = show_bihash_command_fn,
+};
+/* *INDENT-ON* */
+
+#ifdef CLIB_SANITIZE_ADDR
+/* default options for Address Sanitizer */
+const char *
+__asan_default_options (void)
+{
+ return VPP_SANITIZE_ADDR_OPTIONS;
+}
+#endif /* CLIB_SANITIZE_ADDR */
+
+/***********************************
+ * Missing Symbol in vpp libraries
+ ***********************************/
+
+typedef struct stat_segment_directory_entry_s stat_segment_directory_entry_t;
+typedef void (*stat_segment_update_fn) (stat_segment_directory_entry_t *e,
+ u32 i);
+clib_error_t *
+stat_segment_register_gauge (u8 *name, stat_segment_update_fn update_fn,
+ u32 caller_index)
+{
+ return NULL;
+}
+
+u8 *
+format_vl_api_address_union (u8 *s, va_list *args)
+{
+ return NULL;
+}
+
+int
+vpp_init ()
+{
+#define N_ARGS 3
+#define BUFFER_LEN 1024
+ // Get executable path
+ char buffer[BUFFER_LEN];
+ int ret = readlink ("/proc/self/exe", buffer, BUFFER_LEN);
+
+ ASSERT (ret < BUFFER_LEN);
+
+ buffer[ret] = '\0';
+
+ char *argv[N_ARGS] = { buffer, "unix { nodaemon }", NULL };
+ return vpp_init_internal (N_ARGS - 1, argv);
+}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/hicn-plugin/src/test/vpp.h b/hicn-plugin/src/test/vpp.h
new file mode 100644
index 000000000..fe680f6b6
--- /dev/null
+++ b/hicn-plugin/src/test/vpp.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022 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.
+ */
+
+#ifndef __VPP__
+#define __VPP__
+
+int vpp_init ();
+
+#endif \ No newline at end of file