aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--.cz.toml2
m---------cmake0
-rw-r--r--hicn-plugin/includes/vpp_plugins/hicn/error.h7
-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
41 files changed, 2914 insertions, 3554 deletions
diff --git a/.cz.toml b/.cz.toml
index a131c41ac..880cd6b33 100644
--- a/.cz.toml
+++ b/.cz.toml
@@ -1,5 +1,5 @@
[tool]
[tool.commitizen]
name = "cz_conventional_commits"
-version = "3.13.0"
+version = "22.02"
tag_format = "v$version"
diff --git a/cmake b/cmake
-Subproject 64155d4e52b4f8763667230ce489c675b0e47bf
+Subproject 5a6b4d42706c079f596576a9235974ba806f469
diff --git a/hicn-plugin/includes/vpp_plugins/hicn/error.h b/hicn-plugin/includes/vpp_plugins/hicn/error.h
index af9f5da46..be4e53c27 100644
--- a/hicn-plugin/includes/vpp_plugins/hicn/error.h
+++ b/hicn-plugin/includes/vpp_plugins/hicn/error.h
@@ -87,7 +87,12 @@
_ (UDP_TUNNEL_SRC_DST_TYPE, -17001, \
"Src and dst addresses have different type (ipv4 and ipv6)") \
_ (MAPME_NEXT_HOP_ADDED, -18000, "Next hop added to mapme") \
- _ (MAPME_NEXT_HOP_NOT_ADDED, -18001, "Next hop added to mapme")
+ _ (MAPME_NEXT_HOP_NOT_ADDED, -18001, "Next hop added to mapme") \
+ _ (PCS_NOT_FOUND, -19000, "Hash not found in hash table") \
+ _ (PCS_HASH_INVAL, -19001, "Error while calculating the hash") \
+ _ (PCS_INVAL, -19002, "Invalid argument") \
+ _ (PCS_KEY_INVAL, -19003, "Invalid hashtb key") \
+ _ (PCS_EXIST, -19004, "Hash already in hashtable")
typedef enum
{
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