aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordan Augé <jordan.auge+fdio@cisco.com>2020-09-23 17:50:52 +0200
committerJordan Augé <jordan.auge+fdio@cisco.com>2020-09-28 18:25:30 +0200
commit32dccec98e4c7d7e4ce902e19ba8d1b29b823758 (patch)
tree95c5dec2083a3774c13bd5f896743cd6c5c42a7a
parent7356408ca1554468c9d7b9840aaaee28b4341c8d (diff)
[HICN-570] Message buffer (incl. CS and PIT changes)
Change-Id: I4c508e4b04dee3acbfc3da1d26e1770cb826f22b Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com>
-rw-r--r--hicn-light/CMakeLists.txt2
-rw-r--r--hicn-light/cmake/Modules/Packaging.cmake4
-rw-r--r--hicn-light/src/hicn/base/bitmap.h126
-rw-r--r--hicn-light/src/hicn/base/common.h4
-rw-r--r--hicn-light/src/hicn/base/pool.c89
-rw-r--r--hicn-light/src/hicn/base/pool.h19
-rw-r--r--hicn-light/src/hicn/base/test/test-bitmap.cc122
-rw-r--r--hicn-light/src/hicn/base/test/test-pool.cc140
-rw-r--r--hicn-light/src/hicn/base/test/test-vector.cc96
-rw-r--r--hicn-light/src/hicn/base/vector.c43
-rw-r--r--hicn-light/src/hicn/base/vector.h52
-rw-r--r--hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c9
-rw-r--r--hicn-light/src/hicn/config/configuration.c145
-rw-r--r--hicn-light/src/hicn/config/configuration.h10
-rw-r--r--hicn-light/src/hicn/content_store/lru.c149
-rw-r--r--hicn-light/src/hicn/content_store/lru.h20
-rw-r--r--hicn-light/src/hicn/core/CMakeLists.txt3
-rw-r--r--hicn-light/src/hicn/core/address.h6
-rw-r--r--hicn-light/src/hicn/core/address_pair.h8
-rw-r--r--hicn-light/src/hicn/core/connection.c33
-rw-r--r--hicn-light/src/hicn/core/connection.h13
-rw-r--r--hicn-light/src/hicn/core/connection_table.c2
-rw-r--r--hicn-light/src/hicn/core/connection_vft.h3
-rw-r--r--hicn-light/src/hicn/core/content_store.c183
-rw-r--r--hicn-light/src/hicn/core/content_store.h134
-rw-r--r--hicn-light/src/hicn/core/forwarder.c572
-rw-r--r--hicn-light/src/hicn/core/forwarder.h119
-rw-r--r--hicn-light/src/hicn/core/listener.c149
-rw-r--r--hicn-light/src/hicn/core/listener.h25
-rw-r--r--hicn-light/src/hicn/core/listener_table.c2
-rw-r--r--hicn-light/src/hicn/core/listener_vft.h7
-rw-r--r--hicn-light/src/hicn/core/mapme.c12
-rw-r--r--hicn-light/src/hicn/core/mapme.h14
-rw-r--r--hicn-light/src/hicn/core/messageHandler.h7
-rw-r--r--hicn-light/src/hicn/core/msgbuf.h100
-rw-r--r--hicn-light/src/hicn/core/msgbuf_pool.c84
-rw-r--r--hicn-light/src/hicn/core/msgbuf_pool.h65
-rw-r--r--hicn-light/src/hicn/core/name.c57
-rw-r--r--hicn-light/src/hicn/core/name.h10
-rw-r--r--hicn-light/src/hicn/core/nexthops.h7
-rw-r--r--hicn-light/src/hicn/core/pit.c132
-rw-r--r--hicn-light/src/hicn/core/pit.h71
-rw-r--r--hicn-light/src/hicn/core/strategy.h15
-rw-r--r--hicn-light/src/hicn/core/strategy_vft.h11
-rw-r--r--hicn-light/src/hicn/core/wldr.c9
-rw-r--r--hicn-light/src/hicn/core/wldr.h7
-rw-r--r--hicn-light/src/hicn/io/CMakeLists.txt1
-rw-r--r--hicn-light/src/hicn/io/base.c128
-rw-r--r--hicn-light/src/hicn/io/base.h (renamed from hicn-light/src/hicn/core/messagePacketType.h)35
-rw-r--r--hicn-light/src/hicn/io/hicn.c95
-rw-r--r--hicn-light/src/hicn/io/tcp.c42
-rw-r--r--hicn-light/src/hicn/io/udp.c113
-rw-r--r--hicn-light/src/hicn/strategies/low_latency.h4
53 files changed, 2090 insertions, 1218 deletions
diff --git a/hicn-light/CMakeLists.txt b/hicn-light/CMakeLists.txt
index 5d0d59b43..42e7d0a01 100644
--- a/hicn-light/CMakeLists.txt
+++ b/hicn-light/CMakeLists.txt
@@ -45,7 +45,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ANDROID_C_FLAGS}")
endif()
-set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DLIBRTA_DISABLE_VALIDATION -DPARCLibrary_DISABLE_VALIDATION")
+set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DLIBRTA_DISABLE_VALIDATION ")
include(IosMacros)
include(WindowsMacros)
diff --git a/hicn-light/cmake/Modules/Packaging.cmake b/hicn-light/cmake/Modules/Packaging.cmake
index 2b9f4a7b9..936ea6dd4 100644
--- a/hicn-light/cmake/Modules/Packaging.cmake
+++ b/hicn-light/cmake/Modules/Packaging.cmake
@@ -21,7 +21,7 @@ set(${HICN_LIGHT}_DESCRIPTION
)
set(${HICN_LIGHT}_DEB_DEPENDENCIES
- "lib${LIBHICN} (>= stable_version), libparc (>= 1.0)"
+ "lib${LIBHICN} (>= stable_version), libapr1, libaprutil1"
CACHE STRING "Dependencies for deb/rpm package."
)
@@ -31,7 +31,7 @@ set(${HICN_LIGHT}_DEB_PACKAGE_CONTROL_EXTRA
)
set(${HICN_LIGHT}_RPM_DEPENDENCIES
- "lib${LIBHICN} >= stable_version, libparc >= 1.0"
+ "lib${LIBHICN} >= stable_version, libapr1, libaprutil1"
CACHE STRING "Dependencies for deb/rpm package."
)
diff --git a/hicn-light/src/hicn/base/bitmap.h b/hicn-light/src/hicn/base/bitmap.h
index 8fd9fcd70..4a78af567 100644
--- a/hicn-light/src/hicn/base/bitmap.h
+++ b/hicn-light/src/hicn/base/bitmap.h
@@ -23,7 +23,12 @@
#ifndef UTIL_BITMAP_H
#define UTIL_BITMAP_H
+#include <assert.h>
#include <string.h>
+#include <sys/param.h> // MIN, MAX
+
+#include <hicn/util/log.h>
+
#include "common.h"
#include "vector.h"
@@ -37,8 +42,9 @@ typedef uint_fast32_t bitmap_t;
* @param[in,out] bitmap Bitmap to allocate and initialize
* @param[in] max_size Bitmap max_size
*/
-#define bitmap_init(bitmap, max_size) \
- vector_init(bitmap, next_pow2(max_size / BITMAP_WIDTH(bitmap)))
+#define bitmap_init(bitmap, init_size, max_size) \
+ vector_init(bitmap, next_pow2(init_size / BITMAP_WIDTH(bitmap)), \
+ max_size == 0 ? 0 : next_pow2(max_size / BITMAP_WIDTH(bitmap)))
/*
* @brief Ensures a bitmap is sufficiently large to hold an element at the
@@ -51,7 +57,13 @@ typedef uint_fast32_t bitmap_t;
* - This function should always be called before writing to a bitmap element
* to eventually make room for it (the bitmap will eventually be resized).
*/
-#define bitmap_ensure_pos(bitmap, pos) vector_ensure_pos(bitmap, pos / BITMAP_WIDTH(bitmap))
+static inline
+int
+bitmap_ensure_pos(bitmap_t * bitmap, off_t pos)
+{
+ size_t offset = pos / BITMAP_WIDTH(bitmap);
+ return vector_ensure_pos(bitmap, offset);
+}
/**
* @brief Retrieve the state of the i-th bit in the bitmap.
@@ -59,7 +71,15 @@ typedef uint_fast32_t bitmap_t;
* @param[in] bitmap The bitmap to access.
* @param[in] i The bit position.
*/
-#define bitmap_get(bitmap, i) (((bitmap)[(i) / BITMAP_WIDTH(bitmap)] & (1 << ((i) % BITMAP_WIDTH(bitmap)))) >> ((i) % BITMAP_WIDTH(bitmap)))
+static inline
+int
+bitmap_get(const bitmap_t * bitmap, off_t i)
+{
+ size_t offset = i / BITMAP_WIDTH(bitmap);
+ size_t pos = i % BITMAP_WIDTH(bitmap);
+ size_t shift = BITMAP_WIDTH(bitmap) - pos - 1;
+ return (bitmap[offset] >> shift) & 1;
+}
/*
* @brief Returns whether the i-th bit is set (equal to 1) in a bitmap.
@@ -70,6 +90,7 @@ typedef uint_fast32_t bitmap_t;
* @return bool
*/
#define bitmap_is_set(bitmap, i) (bitmap_get((bitmap), (i)) == 1)
+#define bitmap_is_unset(bitmap, i) (bitmap_get((bitmap), (i)) == 0)
/*
* @brief Returns whether the i-th bit is unset (equal to 0) in a bitmap.
@@ -79,19 +100,94 @@ typedef uint_fast32_t bitmap_t;
*
* @return bool
*/
-#define bitmap_is_unset(bitmap, i) (bitmap_get((bitmap), (i)) == 0)
+static inline
+int
+bitmap_set(bitmap_t * bitmap, off_t i)
+{
+ if (bitmap_ensure_pos(bitmap, i) < 0)
+ return -1;
+ size_t offset = i / BITMAP_WIDTH(bitmap);
+ size_t pos = i % BITMAP_WIDTH(bitmap);
+ size_t shift = BITMAP_WIDTH(bitmap) - pos - 1;
+ bitmap[offset] |= 1ul << shift;
+ return 0;
+}
+
+static inline
+int
+bitmap_unset(bitmap_t * bitmap, off_t i)
+{
+ if (bitmap_ensure_pos(bitmap, i) < 0)
+ return -1;
+ size_t offset = i / BITMAP_WIDTH(bitmap);
+ size_t pos = i % BITMAP_WIDTH(bitmap);
+ size_t shift = BITMAP_WIDTH(bitmap) - pos - 1;
+ bitmap[offset] &= ~ (1ul << shift);
+ return 0;
+}
+
+
+static inline
+int
+bitmap_set_range(bitmap_t * bitmap, off_t from, off_t to)
+{
+ assert(from <= to);
+ ssize_t offset_from = from / BITMAP_WIDTH(bitmap);
+ ssize_t offset_to = to / BITMAP_WIDTH(bitmap);
+ size_t pos_from = from % BITMAP_WIDTH(bitmap);
+ size_t pos_to = to % BITMAP_WIDTH(bitmap);
+
+
+ /*
+ * First block initialization is needed if <from> is not aligned with the
+ * bitmap element size or if to is within the same one.
+ */
+ if ((pos_from != 0) || ((offset_to == offset_from) && (pos_to != BITMAP_WIDTH(bitmap) - 1))) {
+ size_t from_end = MIN(to, (offset_from + 1) * BITMAP_WIDTH(bitmap));
+ for (size_t k = from; k < from_end; k++) {
+ if (bitmap_set(bitmap, k) < 0)
+ goto END;
+ }
+ }
+
+ /*
+ * Second block is needed if <to> is not aligned with the bitmap element
+ * size
+ */
+ if ((pos_to != BITMAP_WIDTH(bitmap) - 1) && (offset_to != offset_from)) {
+ size_t to_start = MAX(from, offset_to * BITMAP_WIDTH(bitmap));
+ for (size_t k = to_start; k < to; k++) {
+ if (bitmap_set(bitmap, k) < 0)
+ goto END;
+ }
+ }
+
+ if (pos_from != 0)
+ offset_from += 1;
+ if (pos_to != BITMAP_WIDTH(bitmap) - 1)
+ offset_to -= 1;
+
+ /*
+ * We need to cover both elements at position offset_from and offset_to
+ * provided that offset_from is not bigger
+ */
+ if (offset_to >= offset_from) {
+ memset(&bitmap[offset_from], 0xFF, (offset_to - offset_from + 1) * sizeof(bitmap[0]));
+ }
+
+ return 0;
+
+END:
+ ERROR("Error setting bitmap range\n");
+ return -1;
+}
-#define bitmap_set(bitmap, i) bitmap[(i) / BITMAP_WIDTH(bitmap)] |= 1 << ((i) % BITMAP_WIDTH(bitmap))
+#define bitmap_set_to(bitmap, to) bitmap_set_range((bitmap), 0, (to))
-#define bitmap_unset(bitmap, i) bitmap[(i) / BITMAP_WIDTH(bitmap)] &= ~ (1 << ((i) % BITMAP_WIDTH(bitmap)))
+#define bitmap_free(bitmap) vector_free(bitmap)
-#define bitmap_set_to(bitmap, pos) \
-do { \
- size_t offset = (pos / BITMAP_WIDTH(bitmap) + 1); \
- memset(bitmap, 0xFF, pos * sizeof(bitmap[0])); \
- size_t set_bits = offset * BITMAP_WIDTH(bitmap); \
- for (unsigned i = pos; i < set_bits; i++) \
- bitmap_unset(bitmap, i); \
-} while(0);
+#ifdef WITH_TESTS
+#define bitmap_get_alloc_size(bitmap) vector_get_alloc_size(bitmap)
+#endif /* WITH_TESTS */
#endif /* UTIL_BITMAP_H */
diff --git a/hicn-light/src/hicn/base/common.h b/hicn-light/src/hicn/base/common.h
index 996050308..9ba426bb8 100644
--- a/hicn-light/src/hicn/base/common.h
+++ b/hicn-light/src/hicn/base/common.h
@@ -46,7 +46,7 @@ uint32_t __inline __builtin_clz(uint32_t value) {
return 32;
}
-uint32_t __inline __builtin_clzll(uint64_t value) {
+uint32_t __inline __builtin_clzl2(uint64_t value) {
uint32_t leading_zero = 0;
if (_BitScanReverse64(&leading_zero, value))
return 63 - leading_zero;
@@ -57,6 +57,6 @@ uint32_t __inline __builtin_clzll(uint64_t value) {
#define __builtin_clzl __builtin_clzll
#endif
-#define next_pow2(x) (x == 1 ? 1 : 1<<(64-__builtin_clzl(x-1)))
+#define next_pow2(x) (x <= 1 ? 1 : 1ul <<(64-__builtin_clzl(x-1)))
#endif /* UTIL_COMMON_H */
diff --git a/hicn-light/src/hicn/base/pool.c b/hicn-light/src/hicn/base/pool.c
index 0f5f728e3..31abb13f1 100644
--- a/hicn-light/src/hicn/base/pool.c
+++ b/hicn-light/src/hicn/base/pool.c
@@ -30,36 +30,52 @@
#include "common.h"
#include "pool.h"
+#include <stdio.h> // XXX
+
void
-_pool_init(void ** pool_ptr, size_t elt_size, size_t max_size)
+_pool_init(void ** pool_ptr, size_t elt_size, size_t init_size, size_t max_size)
{
assert(pool_ptr);
assert(elt_size);
- pool_hdr_t * ph = calloc(POOL_HDRLEN + elt_size * max_size, 1);
- if (!ph) {
- *pool_ptr = NULL;
- return;
- }
+ init_size = next_pow2(init_size);
+
+ if (max_size && init_size > max_size)
+ goto ERR_MAX_SIZE;
+
+ /* The initial pool size is rounded to the next power of two */
+ size_t alloc_size = next_pow2(init_size);
+
+ pool_hdr_t * ph = calloc(POOL_HDRLEN + alloc_size * elt_size, 1);
+ if (!ph)
+ goto ERR_MALLOC;
ph->elt_size = elt_size;
+ ph->alloc_size = alloc_size;
ph->max_size = max_size;
/* Free indices */
off_t * free_indices;
- vector_init(free_indices, max_size);
- for(unsigned i = 0; i < max_size; i++)
- free_indices[i] = (max_size - 1) - i;
- vector_len(free_indices) = max_size;
+ vector_init(free_indices, init_size, max_size);
+ for(unsigned i = 0; i < init_size; i++)
+ free_indices[i] = (init_size - 1) - i;
+ vector_len(free_indices) = init_size;
ph->free_indices = free_indices;
/* Free bitmap */
uint_fast32_t * fb = ph->free_bitmap;
- bitmap_init(fb, max_size);
- bitmap_set_to(fb, max_size);
+ bitmap_init(fb, init_size, max_size);
+ bitmap_set_to(fb, init_size);
ph->free_bitmap = fb;
*pool_ptr = (uint8_t*)ph + POOL_HDRLEN;
+
+ return;
+
+ERR_MALLOC:
+ERR_MAX_SIZE:
+ *pool_ptr = NULL;
+ return;
}
void
@@ -73,42 +89,59 @@ void
_pool_resize(void ** pool_ptr, size_t elt_size)
{
pool_hdr_t * ph = pool_hdr(*pool_ptr);
- size_t old_elts = ph->max_size;
- size_t new_elts = old_elts * 2;
+ size_t old_size = ph->alloc_size;
+ size_t new_size = old_size * 2;
+
+ if (ph->max_size && new_size > ph->max_size)
+ goto ERR_MAX_SIZE;
/* Double pool storage */
- ph = realloc(ph, POOL_HDRLEN + new_elts * elt_size);
- if (!ph) {
- *pool_ptr = NULL;
- return;
- }
+ ph = realloc(ph, POOL_HDRLEN + new_size * elt_size);
+ if (!ph)
+ goto ERR_REALLOC;
ph->elt_size = elt_size;
- ph->max_size = new_elts;
+ ph->alloc_size = new_size;
/*
- * After resize, the pool will have old_elts free indices, ranging from
- * old_elts to (new_elts - 1)
+ * After resize, the pool will have new free indices, ranging from
+ * old_size to (new_size - 1)
*/
- off_t * free_indices = ph->free_indices;
- vector_ensure_pos(free_indices, old_elts);
- for (unsigned i = 0; i < old_elts; i++)
- free_indices[i] = new_elts - 1 - i;
+ vector_ensure_pos(ph->free_indices, old_size);
+ for (unsigned i = 0; i < old_size; i++)
+ ph->free_indices[i] = new_size - 1 - i;
+ vector_len(ph->free_indices) = old_size;
+
+ /* We also need to update the bitmap */
+ bitmap_ensure_pos(ph->free_bitmap, new_size - 1);
+ bitmap_set_range(ph->free_bitmap, old_size, new_size - 1);
/* Reassign pool pointer */
*pool_ptr = (uint8_t*)ph + POOL_HDRLEN;
+
+ return;
+
+ERR_REALLOC:
+ERR_MAX_SIZE:
+ *pool_ptr = NULL;
+ return;
}
-void
+off_t
_pool_get(void ** pool_ptr, void ** elt, size_t elt_size)
{
pool_hdr_t * ph = pool_hdr(*pool_ptr);
uint64_t l = vector_len(ph->free_indices);
- if (l == 0)
+ if (l == 0) {
_pool_resize(pool_ptr, elt_size);
+ ph = pool_hdr(*pool_ptr);
+ l = vector_len(ph->free_indices);
+ }
off_t free_id = ph->free_indices[l - 1];
vector_len(ph->free_indices)--;
+ bitmap_unset(ph->free_bitmap, free_id);
*elt = *pool_ptr + free_id;
memset(*elt, 0, sizeof(elt));
+ return free_id;
}
void
diff --git a/hicn-light/src/hicn/base/pool.h b/hicn-light/src/hicn/base/pool.h
index 8335c9bc5..57172192b 100644
--- a/hicn-light/src/hicn/base/pool.h
+++ b/hicn-light/src/hicn/base/pool.h
@@ -51,6 +51,7 @@
typedef struct {
size_t elt_size;
+ size_t alloc_size;
size_t max_size;
uint_fast32_t * free_bitmap; /* bitmap of free indices */
off_t * free_indices; /* vector of free indices */
@@ -76,7 +77,7 @@ typedef struct {
*
* NOTE: that an empty pool might be equal to NULL.
*/
-void _pool_init(void ** pool_ptr, size_t elt_size, size_t max_size);
+void _pool_init(void ** pool_ptr, size_t elt_size, size_t init_size, size_t max_size);
/**
* @brief Free a pool data structure (helper).
@@ -105,7 +106,7 @@ void _pool_resize(void ** pool_ptr, size_t elt_size);
* NOTES:
* - The memory chunk is cleared upon attribution
*/
-void _pool_get(void ** pool, void ** elt, size_t elt_size);
+off_t _pool_get(void ** pool, void ** elt, size_t elt_size);
/**
* @brief Put an element back into the pool data structure (helper).
@@ -127,8 +128,8 @@ void _pool_put(void ** pool, void ** elt, size_t elt_size);
*
* NOTE: that an empty pool might be equal to NULL.
*/
-#define pool_init(pool, max_size) \
- _pool_init((void**)&pool, sizeof(pool[0]), max_size);
+#define pool_init(pool, init_size, max_size) \
+ _pool_init((void**)&pool, sizeof(pool[0]), init_size, max_size);
/**
* @brief Free a pool data structure.
@@ -168,6 +169,8 @@ void _pool_put(void ** pool, void ** elt, size_t elt_size);
#define pool_validate_id(pool, id) \
bitmap_is_unset((pool_hdr(pool))->free_bitmap, (id))
+#define pool_get_free_indices_size(pool) vector_len(pool_hdr(pool)->free_indices)
+
/**
* @brief Returns the current length of the pool.
*
@@ -180,7 +183,7 @@ void _pool_put(void ** pool, void ** elt, size_t elt_size);
* size of the pool.
*/
#define pool_len(pool) \
- (pool_hdr(pool)->max_size - vector_len((pool_hdr(pool)->free_indices)))
+ (pool_hdr(pool)->alloc_size - pool_get_free_indices_size(pool))
/**
* @brief Enumerate elements from a pool.
@@ -226,4 +229,10 @@ do { \
pool_enumerate((pool), _pool_var(i), (eltp), BODY); \
} while(0)
+#ifdef WITH_TESTS
+#define pool_get_alloc_size(bitmap) pool_hdr(pool)->alloc_size
+#define pool_get_free_indices(pool) pool_hdr(pool)->free_indices
+#define pool_get_free_bitmap(pool) pool_hdr(pool)->free_bitmap
+#endif /* WITH_TESTS */
+
#endif /* UTIL_POOL_H */
diff --git a/hicn-light/src/hicn/base/test/test-bitmap.cc b/hicn-light/src/hicn/base/test/test-bitmap.cc
index d6ab94f3e..1a62edba3 100644
--- a/hicn-light/src/hicn/base/test/test-bitmap.cc
+++ b/hicn-light/src/hicn/base/test/test-bitmap.cc
@@ -24,60 +24,114 @@
#include <netinet/in.h>
extern "C" {
-#include <hicn/base/vector.h>
+#define WITH_TESTS
#include <hicn/base/bitmap.h>
}
+#define DEFAULT_SIZE 10
+
class BitmapTest : public ::testing::Test {
- protected:
- BitmapTest() {
- }
+protected:
+ BitmapTest() { }
- virtual ~BitmapTest() {
+ virtual ~BitmapTest() { }
- // You can do clean-up work that doesn't throw exceptions here.
- }
+ bitmap_t * bitmap;
+};
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
+/*
+ * TEST: bitmap allocation
+ */
+TEST_F(BitmapTest, BitmapAllocation)
+{
+ int rc;
- virtual void SetUp() {
- bitmap_init(bitmap, 1024);
- }
+ /*
+ * We take a value < 32 on purpose to avoid confusion on the choice of a 32
+ * or 64 bit integer for storage
+ */
+ size_t size_not_pow2 = DEFAULT_SIZE;
+ bitmap_init(bitmap, size_not_pow2, 0);
- virtual void TearDown() {
- free(bitmap);
- }
- uint32_t *bitmap;
-};
+ /*
+ * Bitmap should have been allocated with a size rounded to the next power
+ * of 2
+ */
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+
+ /* By default, no element should be set */
+ EXPECT_FALSE(bitmap_is_set(bitmap, 0));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 0));
+
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+
+ EXPECT_FALSE(bitmap_is_set(bitmap, size_not_pow2 - 1));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, size_not_pow2 - 1));
+
+ /* Bitmap should not have been reallocated */
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+
+ /* After setting a bit after the end, bitmap should have been reallocated */
+ bitmap_set(bitmap, sizeof(bitmap[0]) * 8 - 1);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+
+ /* After setting a bit after the end, bitmap should have been reallocated */
+ rc = bitmap_set(bitmap, sizeof(bitmap[0]) * 8);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2);
+
+ rc = bitmap_set(bitmap, sizeof(bitmap[0]) * 8 + 1);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2);
+
+ bitmap_free(bitmap);
+
+ size_t size_pow2 = 16;
+
+ /* Limiting test for allocation size */
+ bitmap_init(bitmap, size_pow2, 0);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+
+ bitmap_free(bitmap);
+}
TEST_F(BitmapTest, BitmapSet)
{
- bitmap_set(bitmap, 20);
- EXPECT_TRUE(bitmap_is_set(bitmap, 20));
- EXPECT_FALSE(bitmap_is_unset(bitmap, 20));
- EXPECT_FALSE(bitmap_is_set(bitmap, 19));
- EXPECT_TRUE(bitmap_is_unset(bitmap, 19));
+ bitmap_init(bitmap, DEFAULT_SIZE, 0);
+
+ bitmap_set(bitmap, 20);
+ EXPECT_TRUE(bitmap_is_set(bitmap, 20));
+ EXPECT_FALSE(bitmap_is_unset(bitmap, 20));
+ EXPECT_FALSE(bitmap_is_set(bitmap, 19));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 19));
+ bitmap_free(bitmap);
}
TEST_F(BitmapTest, BitmapUnSet) {
- bitmap_set(bitmap, 20);
- bitmap_set(bitmap, 19);
- bitmap_unset(bitmap, 20);
- EXPECT_FALSE(bitmap_is_set(bitmap, 20));
- EXPECT_TRUE(bitmap_is_unset(bitmap, 20));
- EXPECT_TRUE(bitmap_is_set(bitmap, 19));
- EXPECT_FALSE(bitmap_is_unset(bitmap, 19));
+ bitmap_init(bitmap, DEFAULT_SIZE, 0);
+
+ bitmap_set(bitmap, 20);
+ bitmap_set(bitmap, 19);
+ bitmap_unset(bitmap, 20);
+ EXPECT_FALSE(bitmap_is_set(bitmap, 20));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 20));
+ EXPECT_TRUE(bitmap_is_set(bitmap, 19));
+ EXPECT_FALSE(bitmap_is_unset(bitmap, 19));
+ bitmap_free(bitmap);
}
TEST_F(BitmapTest, BitmapSetTo) {
- bitmap_set_to(bitmap, 40);
- EXPECT_TRUE(bitmap_is_set(bitmap, 20));
- EXPECT_TRUE(bitmap_is_set(bitmap, 21));
- EXPECT_TRUE(bitmap_is_unset(bitmap, 41));
- EXPECT_TRUE(bitmap_is_unset(bitmap, 42));
+ bitmap_init(bitmap, DEFAULT_SIZE, 0);
+
+ bitmap_set_to(bitmap, 40);
+ EXPECT_TRUE(bitmap_is_set(bitmap, 20));
+ EXPECT_TRUE(bitmap_is_set(bitmap, 21));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 41));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 42));
+
+ bitmap_free(bitmap);
}
int main(int argc, char **argv)
diff --git a/hicn-light/src/hicn/base/test/test-pool.cc b/hicn-light/src/hicn/base/test/test-pool.cc
index 86c1c1270..1146ef2b7 100644
--- a/hicn-light/src/hicn/base/test/test-pool.cc
+++ b/hicn-light/src/hicn/base/test/test-pool.cc
@@ -24,45 +24,135 @@
#include <netinet/in.h>
extern "C" {
+#define WITH_TESTS
#include <hicn/base/pool.h>
}
+/*
+ * TODO
+ * - test max_size
+ */
+
+#define DEFAULT_SIZE 10
+
class PoolTest : public ::testing::Test {
- protected:
- PoolTest() {
- }
+protected:
+ PoolTest() { }
+ virtual ~PoolTest() { }
- virtual ~PoolTest() {
- // You can do clean-up work that doesn't throw exceptions here.
- }
+ int *pool;
+};
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
+TEST_F(PoolTest, PoolAllocation)
+{
+ int rc;
- virtual void SetUp() {
-
- }
+ pool_init(pool, DEFAULT_SIZE, 0);
- virtual void TearDown() {
- pool_free(pool);
- }
+ size_t pool_size = next_pow2(DEFAULT_SIZE);
- int *pool;
-};
+ EXPECT_EQ(pool_get_alloc_size(pool), pool_size);
+
+ /* Check that free indices and bitmaps are correctly initialize */
+ off_t * fi = pool_get_free_indices(pool);
+ EXPECT_EQ(vector_len(fi), pool_size);
+ EXPECT_EQ(fi[0], pool_size - 1);
+ EXPECT_EQ(fi[pool_size - 1], 0);
+
+ /* The allocated size of the underlying vector should be the next power of two */
+ EXPECT_EQ(vector_get_alloc_size(fi), pool_size);
+
+ bitmap_t * fb = pool_get_free_bitmap(pool);
+ EXPECT_TRUE(bitmap_is_set(fb, 0));
+ EXPECT_TRUE(bitmap_is_set(fb, pool_size - 2));
+ EXPECT_TRUE(bitmap_is_set(fb, pool_size - 1));
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size));
+
+ /* Getting elements from the pool should correctly update the free indices
+ * and bitmap */
+ int * elt;
+
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(vector_len(fi), pool_size - 1);
+ EXPECT_TRUE(bitmap_is_unset(fb, 0));
+
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(vector_len(fi), pool_size - 2);
+ EXPECT_TRUE(bitmap_is_unset(fb, 1));
+
+ for (unsigned i = 0; i < pool_size - 4; i++) {
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ }
+
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(vector_len(fi), 1);
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 2));
+
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(vector_len(fi), 0);
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 1));
+ /*
+ * Getting elements within the allocated range should not have triggered a
+ * resize
+ */
+ EXPECT_EQ(pool_len(pool), pool_size);
+
+ /*
+ * Getting elements once the allocated range has been exceeded should
+ * trigger a resize
+ */
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+
+ EXPECT_EQ(pool_get_alloc_size(pool), pool_size * 2);
+
+ EXPECT_EQ(pool_len(pool), pool_size + 1);
+
+ /*
+ * Doubling the size, we should have again pool_size elements free, minus 1
+ */
+ EXPECT_EQ(pool_get_free_indices_size(pool), pool_size - 1);
+
+ /*
+ * NOTE: this is wrong as there has been a realloc and the old fi
+ * pointer is now invalid
+ */
+ //EXPECT_EQ(vector_len(fi), pool_size - 1);
+
+ /* And the bitmap should also be correctly modified */
+ fb = pool_get_free_bitmap(pool);
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size));
+
+ /* Check that surrounding values are also correct */
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 1));
+ EXPECT_TRUE(bitmap_is_set(fb, pool_size + 1));
+
+ /* Setting elements after should through */
+
+ /* Check that free indices and bitmaps are correctly updated */
+
+ pool_free(pool);
+}
+
+// XXX todo : check state after several get and put
TEST_F(PoolTest, PoolPut)
{
- pool_init(pool, 1024);
- int* elt;
- pool_get(pool, elt);
- *elt = 10;
+ pool_init(pool, DEFAULT_SIZE, 0);
+
+ int* elt;
+ pool_get(pool, elt);
+ *elt = 10;
printf("2\n");
- pool_put(pool, elt);
+ pool_put(pool, elt);
printf("3\n");
-
- //pool_get(pool)
- //loop_ = loop_create();
- //EXPECT_TRUE(loop_ != NULL);
+
+ pool_free(pool);
}
diff --git a/hicn-light/src/hicn/base/test/test-vector.cc b/hicn-light/src/hicn/base/test/test-vector.cc
index e5eeff910..59571b053 100644
--- a/hicn-light/src/hicn/base/test/test-vector.cc
+++ b/hicn-light/src/hicn/base/test/test-vector.cc
@@ -24,64 +24,90 @@
#include <netinet/in.h>
extern "C" {
+#define WITH_TESTS
#include <hicn/base/vector.h>
}
+/*
+ * TODO
+ * - test max_size
+ */
+
+#define DEFAULT_SIZE 10
+
class VectorTest : public ::testing::Test {
- protected:
- VectorTest() {
- }
+protected:
+ VectorTest() { }
+ virtual ~VectorTest() { }
- virtual ~VectorTest() {
- // You can do clean-up work that doesn't throw exceptions here.
- }
+ int *vector = NULL;
+};
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
+/* TEST: Vector allocation and initialization */
+TEST_F(VectorTest, VectorAllocate)
+{
+ vector_init(vector, DEFAULT_SIZE, 0);
- virtual void SetUp() {;
- vector_init(vector, 1024);
- }
+ /* Allocated size should be the next power of two */
+ EXPECT_EQ(vector_get_alloc_size(vector), 16);
- virtual void TearDown() {
- vector_free(vector);
- }
+ /* Setting elements within the allocated size should not trigger a resize */
+ vector_ensure_pos(vector, 15);
+ EXPECT_EQ(vector_get_alloc_size(vector), 16);
- int *vector = NULL;
+ /* Setting elements after should through */
+ vector_ensure_pos(vector, 16);
+ EXPECT_EQ(vector_get_alloc_size(vector), 32);
-};
+ /* Check that free indices and bitmaps are correctly updated */
+
+ vector_free(vector);
+}
TEST_F(VectorTest, VectorSize)
{
- vector_push(vector, 109);
- vector_push(vector, 109);
- int size = vector_len(vector);
- EXPECT_EQ(size, 2);
- vector_push(vector, 109);
- size = vector_len(vector);
- EXPECT_EQ(size, 3);
+ vector_init(vector, DEFAULT_SIZE, 0);
+
+ vector_push(vector, 109);
+ int size = vector_len(vector);
+ EXPECT_EQ(size, 1);
+ vector_push(vector, 109);
+ size = vector_len(vector);
+ EXPECT_EQ(size, 2);
+ vector_push(vector, 109);
+ size = vector_len(vector);
+ EXPECT_EQ(size, 3);
+ vector_free(vector);
}
TEST_F(VectorTest, VectorCheckValue)
{
- vector_push(vector, 109);
- vector_push(vector, 200);
- EXPECT_EQ(vector[0], 109);
- EXPECT_EQ(vector[1], 200);
+ vector_init(vector, DEFAULT_SIZE, 0);
+
+ vector_push(vector, 109);
+ vector_push(vector, 200);
+ EXPECT_EQ(vector[0], 109);
+ EXPECT_EQ(vector[1], 200);
+
+ vector_free(vector);
}
TEST_F(VectorTest, VectorEnsurePos)
{
- printf (" %p\n", vector);
- vector_ensure_pos(vector, 1025);
- for (int i = 0; i <1025; i++) {
- printf("i %d\n", i);
+ vector_init(vector, DEFAULT_SIZE, 0);
+
printf (" %p\n", vector);
- vector_push(vector, i);
- }
- int size = vector_len(vector);
- EXPECT_EQ(size, 1025);
+ vector_ensure_pos(vector, 1025);
+ for (int i = 0; i <1025; i++) {
+ //printf("i %d\n", i);
+ //printf (" %p\n", vector);
+ vector_push(vector, i);
+ }
+ int size = vector_len(vector);
+ EXPECT_EQ(size, 1025);
+
+ vector_free(vector);
}
int main(int argc, char **argv)
diff --git a/hicn-light/src/hicn/base/vector.c b/hicn-light/src/hicn/base/vector.c
index b994a4465..43110414a 100644
--- a/hicn-light/src/hicn/base/vector.c
+++ b/hicn-light/src/hicn/base/vector.c
@@ -28,9 +28,10 @@
#define DEFAULT_VECTOR_SIZE 64
void
-_vector_init(void ** vector_ptr, size_t elt_size, size_t init_size)
+_vector_init(void ** vector_ptr, size_t elt_size, size_t init_size, size_t max_size)
{
assert(vector_ptr);
+ assert(max_size == 0 || init_size < max_size);
if (init_size == 0)
init_size = DEFAULT_VECTOR_SIZE;
@@ -40,6 +41,7 @@ _vector_init(void ** vector_ptr, size_t elt_size, size_t init_size)
vector_hdr_t * vh = vector_hdr(*vector_ptr);
vh->cur_size = 0;
+ vh->max_size = max_size;
}
void
@@ -49,23 +51,42 @@ _vector_free(void ** vector_ptr)
*vector_ptr = NULL;
}
-bool
+int
_vector_resize(void ** vector_ptr, size_t elt_size, off_t pos)
{
- vector_hdr_t * vh = *vector_ptr ? vector_hdr(*vector_ptr) : NULL;
+ vector_hdr_t * vh;
- /*
- * Round the allocated size to the next power of 2 of the requested position
- */
- size_t new_elts = (pos > 0) ? next_pow2(pos) : vh->max_size * 2;
+ size_t old_size;
- vh = realloc(vh, VECTOR_HDRLEN + new_elts * elt_size);
+ if (*vector_ptr) {
+ vh = vector_hdr(*vector_ptr);
+ old_size = vh->alloc_size;
+ } else {
+ vh = NULL;
+ old_size = 0;
+ }
+
+ /* Round the allocated size to the next power of 2 of the requested position */
+ size_t new_size = next_pow2(pos);
+
+ /* Don't grow the vector back */
+ if (new_size < old_size)
+ return 0;
+
+ /* Don't exceed maximum size (for init, check is done beforehand) */
+ if (vh && vh->max_size && new_size > vh->max_size)
+ return -1;
+
+ vh = realloc(vh, VECTOR_HDRLEN + new_size * elt_size);
if (!vh)
- return false;
- vh->max_size = new_elts;
+ return -1;
+ vh->alloc_size = new_size;
+
+ /* Zero out the newly allocated memory (except headers) */
+ memset((uint8_t*)vh + VECTOR_HDRLEN + old_size * elt_size, 0, (new_size - old_size) * elt_size);
/* Reassign vector pointer */
*vector_ptr = (uint8_t*)vh + VECTOR_HDRLEN;
- return true;
+ return 0;
}
diff --git a/hicn-light/src/hicn/base/vector.h b/hicn-light/src/hicn/base/vector.h
index 06ffa4428..ff12e6ee6 100644
--- a/hicn-light/src/hicn/base/vector.h
+++ b/hicn-light/src/hicn/base/vector.h
@@ -45,7 +45,7 @@
#ifndef UTIL_VECTOR_H
#define UTIL_VECTOR_H
-#include <stdbool.h>
+#include <stdint.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
@@ -58,7 +58,8 @@
typedef struct {
size_t cur_size; /** Vector current size (corresponding to the highest used element). */
- size_t max_size; /** The currently allocated size. */
+ size_t alloc_size; /** The currently allocated size. */
+ size_t max_size; /** The maximum allowed size (0 = no limit) */
} vector_hdr_t;
/* Make sure elements following the header are aligned */
@@ -80,7 +81,7 @@ typedef struct {
* @param[in] elt_size Size of a vector element.
* @param[in] max_size Maximum vector size (O = unlimited).
*/
-void _vector_init(void ** vector_ptr, size_t elt_size, size_t max_size);
+void _vector_init(void ** vector_ptr, size_t elt_size, size_t init_size, size_t max_size);
/**
* @brief Free a vector data structure.
@@ -97,7 +98,7 @@ void _vector_free(void ** vector_ptr);
* @param[in] pos The position at which the vector should be able to hold an
* element.
*
- * @return bool Flag indicating whether the vector has been correctly resized.
+ * @return int Flag indicating whether the vector has been correctly resized.
*
* NOTE:
* - The resize operation does not specify the final size of the vector but
@@ -105,7 +106,7 @@ void _vector_free(void ** vector_ptr);
* position. This allows the caller not to care about doing successive calls to
* this API while the vector is growing in size.
*/
-bool _vector_resize(void ** vector_ptr, size_t elt_size, off_t pos);
+int _vector_resize(void ** vector_ptr, size_t elt_size, off_t pos);
/**
* @brief Ensures a vector is sufficiently large to hold an element at the
@@ -115,7 +116,7 @@ bool _vector_resize(void ** vector_ptr, size_t elt_size, off_t pos);
* @param[in] elt_size The size of a vector element.
* @param[in] pos The position to validate.
*
- * @return bool Flag indicating whether the vector is available.
+ * @return int Flag indicating whether the vector is available.
*
* NOTE:
* - This function should always be called before writing to a vector element
@@ -124,13 +125,13 @@ bool _vector_resize(void ** vector_ptr, size_t elt_size, off_t pos);
* be resized.
*/
static inline
-bool
+int
_vector_ensure_pos(void ** vector_ptr, size_t elt_size, off_t pos)
{
vector_hdr_t * vh = vector_hdr(*vector_ptr);
- if (pos >= vh->max_size)
- return _vector_resize(vector_ptr, elt_size, pos);
- return true;
+ if (pos >= vh->alloc_size)
+ return _vector_resize(vector_ptr, elt_size, pos + 1);
+ return 0;
}
/**
@@ -146,15 +147,17 @@ _vector_ensure_pos(void ** vector_ptr, size_t elt_size, off_t pos)
* maximum size).
*/
static inline
-bool
+int
_vector_push(void ** vector_ptr, size_t elt_size, void * elt)
{
vector_hdr_t * vh = vector_hdr(*vector_ptr);
- if (!_vector_ensure_pos(vector_ptr, elt_size, vh->cur_size))
- return false;
- /*(*vector_ptr)[vh->cur_size++] = elt; */
- memcpy((uint8_t*)vector_ptr + vh->cur_size++ * elt_size, elt, elt_size);
- return true;
+ if (_vector_ensure_pos(vector_ptr, elt_size, vh->cur_size) < 0)
+ return -1;
+ /* Always get header after a potential resize */
+ memcpy((uint8_t*)*vector_ptr + vh->cur_size * elt_size, elt, elt_size);
+ vh = vector_hdr(*vector_ptr);
+ vh->cur_size++;
+ return 0;
}
/******************************************************************************/
@@ -165,9 +168,13 @@ _vector_push(void ** vector_ptr, size_t elt_size, void * elt)
*
* @param[in,out] vector Vector to allocate and initialize.
* @param[in] max_size Maximum vector size (nonzero).
+ *
+ * NOTE:
+ * - Allocated memory is set to 0 (used by bitmap)
*/
-#define vector_init(vector, max_size) \
- _vector_init((void**)&vector, sizeof(vector[0]), max_size)
+
+#define vector_init(vector, init_size, max_size) \
+ _vector_init((void**)&vector, sizeof(vector[0]), init_size, max_size)
/**
* @brief Free a vector data structure.
@@ -184,7 +191,7 @@ _vector_push(void ** vector_ptr, size_t elt_size, void * elt)
* @param[in] pos The position at which the vector should be able to hold an
* element.
*
- * @return bool Flag indicating whether the vector has been correctly resized.
+ * @return int Flag indicating whether the vector has been correctly resized.
*
* NOTE:
* - The resize operation does not specify the final size of the vector but
@@ -193,6 +200,7 @@ _vector_push(void ** vector_ptr, size_t elt_size, void * elt)
* this API while the vector is growing in size.
* - If the new size is smaller than the current size, the content of the
* vector will be truncated.
+ * - Newly allocated memory is set to 0 (used by bitmap)
*/
#define vector_resize(vector) _vector_resize((void**)&(vector), sizeof((vector)[0]), 0)
@@ -241,6 +249,10 @@ do { \
* - A user should always call vector_ensure_pos to ensure the vector is
* sufficiently large to hold an element at the specified position.
*/
-#define vector_len(vector) vector_hdr((vector))->cur_size
+#define vector_len(vector) vector_hdr(vector)->cur_size
+
+#ifdef WITH_TESTS
+#define vector_get_alloc_size(vector) vector_hdr(vector)->alloc_size
+#endif /* WITH_TESTS */
#endif /* UTIL_VECTOR_H */
diff --git a/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c b/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c
index f3fbf84dd..c743de743 100644
--- a/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c
+++ b/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c
@@ -369,6 +369,12 @@ int main(int argc, const char *argv[]) {
}
#endif
+ /*
+ * The loop should be created before the forwarder instance as it is needed
+ * for timers
+ */
+ MAIN_LOOP = loop_create();
+
forwarder_t * forwarder = forwarder_create();
if (!forwarder) {
ERROR("Forwarder initialization failed. Are you running it with sudo privileges?");
@@ -377,7 +383,7 @@ int main(int argc, const char *argv[]) {
configuration_t * configuration = forwarder_get_configuration(forwarder);
if (capacity > -1) {
- configuration_content_store_set_size(configuration, capacity);
+ configuration_cs_set_size(configuration, capacity);
}
forwarder_setup_local_listeners(forwarder, port);
@@ -389,7 +395,6 @@ int main(int argc, const char *argv[]) {
configurationPort);
/* Main loop */
- MAIN_LOOP = loop_create();
if (loop_dispatch(MAIN_LOOP) < 0) {
ERROR("Failed to run main loop");
return EXIT_FAILURE;
diff --git a/hicn-light/src/hicn/config/configuration.c b/hicn-light/src/hicn/config/configuration.c
index a6f78f9c2..fed9d95ed 100644
--- a/hicn-light/src/hicn/config/configuration.c
+++ b/hicn-light/src/hicn/config/configuration.c
@@ -51,8 +51,8 @@
#define DEFAULT_COST 1
#define DEFAULT_PORT 1234
-#define make_ack(msg) msg->header.messageType = ACK_LIGHT
-#define make_nack(msg) msg->header.messageType = NACK_LIGHT
+#define make_ack(msg) ((msg_header_t *)msg)->header.messageType = ACK_LIGHT
+#define make_nack(msg) ((msg_header_t *)msg)->header.messageType = NACK_LIGHT
#define msg_malloc_list(msg, N) \
do { \
@@ -224,7 +224,7 @@ configuration_on_listener_add(configuration_t * config, uint8_t * packet,
return (uint8_t*)msg;
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -291,7 +291,7 @@ configuration_on_listener_remove(configuration_t * config, uint8_t * packet,
return (uint8_t*)msg;
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -348,7 +348,7 @@ configuration_on_listener_list(configuration_t * config, uint8_t * packet,
msg_listener_list_reply_t * msg;
msg_malloc_list(msg, n)
if (!msg)
- return NULL;
+ goto NACK;
cmd_listener_list_item_t * payload = &msg->payload;
listener_t * listener;
@@ -358,6 +358,10 @@ configuration_on_listener_list(configuration_t * config, uint8_t * packet,
});
return (uint8_t*)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t*)msg;
}
/* Connection */
@@ -435,7 +439,7 @@ configuration_on_connection_add(configuration_t * config, uint8_t * packet,
return (uint8_t*)msg;
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -488,7 +492,7 @@ configuration_on_connection_remove(configuration_t * config, uint8_t * packet,
return (uint8_t*)msg;
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -578,7 +582,7 @@ configuration_on_connection_list(configuration_t * config, uint8_t * packet,
msg_connection_list_reply_t * msg;
msg_malloc_list(msg, n)
if (!msg)
- return NULL;
+ goto NACK;
cmd_connection_list_item_t * payload = &msg->payload;
connection_t * connection;
@@ -588,6 +592,10 @@ configuration_on_connection_list(configuration_t * config, uint8_t * packet,
});
return (uint8_t*)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t*)msg;
}
uint8_t *
@@ -622,7 +630,7 @@ configuration_on_connection_set_admin_state(configuration_t * config,
return (uint8_t*)msg;
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -652,7 +660,7 @@ configuration_on_connection_update(configuration_t * config, uint8_t * packet,
NACK:
#endif /* WITH_POLICY */
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -684,7 +692,7 @@ configuration_on_connection_set_priority(configuration_t * config,
NACK:
#endif /* WITH_POLICY */
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -716,7 +724,7 @@ configuration_on_connection_set_tags(configuration_t * config, uint8_t * packet,
NACK:
#endif /* WITH_POLICY */
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -751,7 +759,7 @@ configuration_on_route_add(configuration_t * config, uint8_t * packet,
return (uint8_t*)msg;
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -782,7 +790,7 @@ configuration_on_route_remove(configuration_t * config, uint8_t * packet,
return (uint8_t*)msg;
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -811,7 +819,7 @@ configuration_on_route_list(configuration_t * config, uint8_t * packet,
msg_route_list_reply_t * msg;
msg_malloc_list(msg, n);
if (!msg)
- return NULL;
+ goto NACK;
cmd_route_list_item_t * payload = &msg->payload;
fib_foreach_entry(fib, entry, {
@@ -850,6 +858,10 @@ configuration_on_route_list(configuration_t * config, uint8_t * packet,
});
return (uint8_t*)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t*)msg;
}
@@ -869,16 +881,16 @@ configuration_on_cache_set_store(configuration_t * config, uint8_t * packet,
goto NACK;
bool value = (bool)control->activate;
- forwarder_content_store_set_store(config->forwarder, value);
+ forwarder_cs_set_store(config->forwarder, value);
/* XXX Why do we need to check ? */
- if (forwarder_content_store_get_store(config->forwarder) != value)
+ if (forwarder_cs_get_store(config->forwarder) != value)
goto NACK;
make_ack(msg);
return (uint8_t*)msg;
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -896,16 +908,16 @@ configuration_on_cache_set_serve(configuration_t * config, uint8_t * packet,
goto NACK;
bool value = (bool)control->activate;
- forwarder_content_store_set_serve(config->forwarder, value);
+ forwarder_cs_set_serve(config->forwarder, value);
/* XXX Why do we need to check ? */
- if (forwarder_content_store_get_serve(config->forwarder) != value)
+ if (forwarder_cs_get_serve(config->forwarder) != value)
goto NACK;
make_ack(msg);
return (uint8_t*)msg;
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -918,7 +930,7 @@ configuration_on_cache_clear(configuration_t * config, uint8_t * packet,
msg_cache_clear_t * msg = (msg_cache_clear_t *)packet;
- forwarder_content_store_clear(config->forwarder);
+ forwarder_cs_clear(config->forwarder);
make_ack(msg);
return (uint8_t*)msg;
@@ -1039,7 +1051,7 @@ configuration_on_wldr_set(configuration_t * config, uint8_t * packet,
return (uint8_t*)msg;
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -1098,7 +1110,7 @@ configuration_on_punting_add(configuration_t * config, uint8_t * packet,
NACK:
#endif
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -1124,7 +1136,7 @@ configuration_on_mapme_enable(configuration_t * config, uint8_t * packet,
return (uint8_t*)msg;
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -1148,7 +1160,7 @@ configuration_on_mapme_set_discovery(configuration_t * config, uint8_t * packet,
return (uint8_t*)msg;
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -1221,7 +1233,7 @@ configuration_on_mapme_send_update(configuration_t * config, uint8_t * packet,
});
NACK:
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -1252,7 +1264,7 @@ configuration_on_policy_add(configuration_t * config, uint8_t * packet,
NACK:
#endif /* WITH_POLICY */
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -1282,7 +1294,7 @@ configuration_on_policy_remove(configuration_t * config, uint8_t * packet,
NACK:
#endif /* WITH_POLICY */
- make_ack(msg);
+ make_nack(msg);
return (uint8_t*)msg;
}
@@ -1298,10 +1310,10 @@ configuration_on_policy_list(configuration_t * config, uint8_t * packet,
size_t n = fib_get_size(fib);
#ifdef WITH_POLICY
- msg_policy_list_reply_t * msg;
+ msg_policy_list_reply_t * msg = (msg_policy_list_reply_t *)packet;
msg_malloc_list(msg, n);
if (!msg)
- return NULL;
+ goto NACK;
cmd_policy_list_item_t * payload = &msg->payload;
@@ -1333,23 +1345,25 @@ configuration_on_policy_list(configuration_t * config, uint8_t * packet,
});
return (uint8_t*)msg;
-#else
- return NULL;
#endif /* WITH_POLICY */
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
}
size_t
-configuration_content_store_get_size(configuration_t * config)
+configuration_cs_get_size(configuration_t * config)
{
return config->maximumContentObjectStoreSize;
}
void
-configuration_content_store_set_size(configuration_t * config, size_t size)
+configuration_cs_set_size(configuration_t * config, size_t size)
{
config->maximumContentObjectStoreSize = size;
- forwarder_content_store_set_size(config->forwarder,
+ forwarder_cs_set_size(config->forwarder,
config->maximumContentObjectStoreSize);
}
@@ -1359,58 +1373,59 @@ configuration_get_forwarder(const configuration_t * config) {
}
-// ===========================
-// Main functions that deal with receiving commands, executing them, and sending
-// ACK/NACK
-
-uint8_t *
-configuration_dispatch_command(configuration_t * config, command_type_t command_type,
- uint8_t * packet, unsigned ingress_id)
+ssize_t
+configuration_receive_command(configuration_t * config, msgbuf_t * msgbuf)
{
+ assert(config);
+ assert(msgbuf);
+
+ uint8_t * packet = msgbuf_get_packet(msgbuf);
+ unsigned ingress_id = msgbuf_get_connection_id(msgbuf);
+
+ uint8_t * reply = NULL;
+
+ /*
+ * For most commands, the packet will simply be transformed into an ack.
+ * For list commands, a new message will be allocated, and the return value
+ * might eventually be NULL in case of an error. That is why the free the
+ * reply at the end in these circumstances.
+ *
+ * XXX rework this part.
+ */
+ command_type_t command_type = msgbuf_get_command_type(msgbuf);
switch (command_type) {
#define _(l, u) \
case COMMAND_TYPE_ ## u: \
- return configuration_on_ ## l(config, packet, ingress_id);
+ reply = configuration_on_ ## l(config, packet, ingress_id); \
+ assert(reply); \
+ break;
foreach_command_type
#undef _
case COMMAND_TYPE_UNDEFINED:
case COMMAND_TYPE_N:
ERROR("Unexpected command type");
+ reply = packet;
+ make_nack(reply);
break;
}
- return NULL;
-}
-
-void configuration_receive_command(configuration_t * config,
- command_type_t command_type, uint8_t * packet, unsigned ingress_id)
-{
- assert(config);
- assert(command_type_is_valid(command_type));
- assert(packet);
-
- bool nack = false;
-
- uint8_t * reply = configuration_dispatch_command(config, command_type, packet, ingress_id);
- if (!reply) {
- reply = packet;
- msg_header_t * hdr = (msg_header_t *)reply;
- make_nack(hdr);
- nack = true;
- }
connection_table_t * table = forwarder_get_connection_table(config->forwarder);
const connection_t *connection = connection_table_at(table, ingress_id);
connection_send_packet(connection, reply, false);
- switch (command_type) {
+ switch (msgbuf->command.type) {
case COMMAND_TYPE_LISTENER_LIST:
case COMMAND_TYPE_CONNECTION_LIST:
case COMMAND_TYPE_ROUTE_LIST:
case COMMAND_TYPE_POLICY_LIST:
- if (!nack)
+ /* Free replies that have been allocated (not NACK's) */
+ if (((msg_header_t *)reply)->header.messageType != NACK_LIGHT)
free(reply);
break;
default:
break;
}
+
+ // XXX only if we consumed the whole packet.
+ return (ssize_t)msgbuf_get_len(msgbuf);
}
diff --git a/hicn-light/src/hicn/config/configuration.h b/hicn-light/src/hicn/config/configuration.h
index 86efa5236..fa1b0410c 100644
--- a/hicn-light/src/hicn/config/configuration.h
+++ b/hicn-light/src/hicn/config/configuration.h
@@ -26,7 +26,8 @@
#ifndef configuration_h
#define configuration_h
-#include <hicn/utils/commands.h>
+#include "../core/msgbuf.h"
+#include "../utils/commands.h"
typedef struct configuration_s configuration_t;
@@ -67,8 +68,7 @@ void configuration_free(configuration_t * config);
void configuration_setup_all_listeners(configuration_t *config, uint16_t port,
const char *localPath);
-void configuration_receive_command(configuration_t *config, command_type_t command,
- uint8_t * packet, unsigned ingress_id);
+ssize_t configuration_receive_command(configuration_t *config, msgbuf_t * msgbuf);
/**
* Returns the configured size of the content store
@@ -84,7 +84,7 @@ void configuration_receive_command(configuration_t *config, command_type_t comma
* <#example#>
* @endcode
*/
-size_t configuration_content_store_get_size(configuration_t *config);
+size_t configuration_cs_get_size(configuration_t *config);
/**
* Sets the size of the content store (in objects, not bytes)
@@ -98,7 +98,7 @@ size_t configuration_content_store_get_size(configuration_t *config);
* <#example#>
* @endcode
*/
-void configuration_content_store_set_size(configuration_t *config, size_t size);
+void configuration_cs_set_size(configuration_t *config, size_t size);
strategy_type_t configuration_get_strategy(configuration_t *config, const char *prefix);
diff --git a/hicn-light/src/hicn/content_store/lru.c b/hicn-light/src/hicn/content_store/lru.c
index 30f972ce9..72d3e4302 100644
--- a/hicn-light/src/hicn/content_store/lru.c
+++ b/hicn-light/src/hicn/content_store/lru.c
@@ -29,9 +29,9 @@
// XXX TODO
#if 0
-static void _content_store_lru_Log(ContentStoreInterface *storeImpl) {
- content_store_lru_data_t *store =
- (content_store_lru_data_t *)contentStoreInterface_GetPrivateData(storeImpl);
+static void _cs_lru_Log(ContentStoreInterface *storeImpl) {
+ cs_lru_data_t *store =
+ (cs_lru_data_t *)contentStoreInterface_GetPrivateData(storeImpl);
logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_All,
__func__,
@@ -47,40 +47,40 @@ static void _content_store_lru_Log(ContentStoreInterface *storeImpl) {
static
bool
-_content_store_lru_remove_least_used(content_store_t * cs)
+_cs_lru_remove_least_used(cs_t * cs)
{
- if (content_store_size(cs) == 0)
+ if (cs_size(cs) == 0)
return false;
#if 0
ListLruEntry *lruEntry = listLRU_PopTail(store->lru);
- content_store_entry_t *storeEntry =
- (content_store_entry_t *)listLRU_EntryGetData(lruEntry);
+ cs_entry_t *storeEntry =
+ (cs_entry_t *)listLRU_EntryGetData(lruEntry);
#else
- content_store_entry_t * entry = NULL;
+ cs_entry_t * entry = NULL;
#endif
DEBUG("CS %p LRU evict msgbuf %p (#evictions %" PRIu64 ")",
- cs, content_store_entry_message(entry),
+ cs, cs_entry_message(entry),
cs->stats.lru.countLruEvictions);
- content_store_purge_entry(cs, entry);
+ cs_purge_entry(cs, entry);
return true;
}
static
void
-_evictByStorePolicy(content_store_t * cs, uint64_t currentTimeInTicks)
+_evictByStorePolicy(cs_t * cs, uint64_t currentTimeInTicks)
{
// We need to make room. Here's the plan:
// 1) Check to see if anything has expired. If so, remove it and we're done.
// If not, 2) Remove the least recently used item.
- content_store_entry_t *entry =
+ cs_entry_t *entry =
listTimeOrdered_GetOldest(store->indexByExpirationTime);
- if (entry && content_store_entry_has_expiry_time(entry) &&
- (currentTimeInTicks > content_store_entry_get_expiry_time(entry))) {
+ if (entry && cs_entry_has_expiry_time(entry) &&
+ (currentTimeInTicks > cs_entry_get_expiry_time(entry))) {
// Found an expired entry. Remove it, and we're done.
store->stats.countExpiryEvictions++;
@@ -88,103 +88,92 @@ _evictByStorePolicy(content_store_t * cs, uint64_t currentTimeInTicks)
(void *)store, (void *)contentStoreEntry_GetMessage(entry),
store->stats.countExpiryEvictions);
- _content_store_lru_purge_entry(store, entry);
+ _cs_lru_purge_entry(store, entry);
} else {
store->stats.countLruEvictions++;
- _content_store_lru_remove_least_used(store);
+ _cs_lru_remove_least_used(store);
}
}
#endif
void
-content_store_lru_initialize(content_store_t * cs)
+cs_lru_initialize(cs_t * cs)
{
- content_store_lru_data_t * data = cs->data;
-
- data->lru = NULL;
- if (!data->lru) {
- ERROR("Could not create LRU index");
- goto ERR_INDEX;
- }
-
-ERR_INDEX:
- return;
+ /* We start with an empty double-linked list */
+ cs->lru.head = 0;
+ cs->lru.tail = 0;
}
void
-content_store_lru_finalize(content_store_t * cs)
+cs_lru_finalize(cs_t * cs)
{
- content_store_lru_data_t * data = cs->data;
-
- if (data->lru != NULL)
- ; // XXX TODO listLRU_Destroy(&(store->lru));
+ /* Nothing to do */
}
-bool
-content_store_lru_add_entry(content_store_t * cs, content_store_entry_t * entry)
+/**
+ * @brief LRU processing related to the insertion of a new entry in the content
+ * store.
+ * @param[in] cs Content store.
+ * @param[in] entry_id Identifier of the entry in the content store entry pool.
+ *
+ * @return int Error code : 0 if succesful, a negative value otherwise.
+ *
+ * NOTE:
+ * - We insert the new element at the head of the double-linked list.
+ */
+static
+int
+cs_lru_add_entry(cs_t * cs, off_t entry_id)
{
assert(cs);
- assert(entry);
-
- if (content_store_size(cs) == 0)
- return false;
-#if 0
- content_store_lru_data_t * data = cs->data;
-
- content_store_entry_t *dataEntry = parcHashCodeTable_Get(data->storageByName, content);
- if(dataEntry)
- _content_store_lru_purge_entry(data, dataEntry);
- uint64_t expiryTimeTicks = contentStoreEntry_MaxExpiryTime;
- if (message_HasContentExpiryTime(content))
- expiryTimeTicks = message_GetContentExpiryTimeTicks(content);
+ cs_entry_t * entry = &cs->entries[entry_id];
+ assert(entry);
- // Don't add anything that's already expired or has exceeded RCT.
- if (now >= expiryTimeTicks)
- return false;
+ if (cs->lru.head != INVALID_ENTRY_ID) {
+ cs_entry_t * head_entry = cs_entry_at(cs, cs->lru.head);
+ assert(head_entry->lru.prev == INVALID_ENTRY_ID);
+ head_entry->lru.prev = entry_id;
- if (data->objectCount >= data->objectCapacity)
- // Store is full. Need to make room.
- _evictByStorePolicy(data, now);
+ entry->lru.next = cs->lru.head;
+ entry->lru.prev = INVALID_ENTRY_ID;
- // And now add a new entry to the head of the LRU.
- content_store_entry_t *entry = contentStoreEntry_Create(content, data->lru);
- if (!entry)
- return false;
+ cs->lru.head = entry_id;
+ } else {
+ /* The list is empty */
+ assert(cs->lru.tail == INVALID_ENTRY_ID);
- if (!parcHashCodeTable_Add(data->storageByName, content, entry)) {
- // Free what we just created, but did not add. 'entry' has ownership of
- // 'copy', and so will call _Release() on it
- contentStoreEntry_Release(&entry);
- WARN("ContentStoreLRU %p failed to add message %p to hash table",
- (void *)data, (void *)content);
- return false;
+ entry->lru.next = INVALID_ENTRY_ID;
+ entry->lru.prev = INVALID_ENTRY_ID;
+ cs->lru.head = cs->lru.tail = entry_id;
}
- if (content_store_entry_has_expiry_time(entry))
- listTimeOrdered_Add(data->indexByExpirationTime, entry);
-
- data->objectCount++;
- data->stats.countAdds++;
-
- DEBUG("ContentStoreLRU %p saved message %p (object count %" PRIu64 ")",
- data, msgbuf, content_store_size(cs));
-#endif
- return true;
+ return 0;
}
/**
- * Remove a content_store_entry_t from all tables and indices.
+ * Remove a cs_entry_t from all tables and indices.
*/
static
-void
-content_store_lru_remove_entry(content_store_t * cs, content_store_entry_t * entry)
+int
+cs_lru_remove_entry(cs_t * cs, cs_entry_t * entry)
{
assert(cs);
assert(entry);
- //
- // XXX REMOVE ENTRY FROM LRU
+
+ off_t entry_id = cs_get_entry_id(cs, entry);
+
+ if (entry->lru.prev == INVALID_ENTRY_ID) {
+ /* Not already on the head of the LRU */
+ cs_entry_t * prev_entry = cs_entry_at(cs, entry->lru.prev);
+ assert(prev_entry);
+ prev_entry->lru.next = entry_id;
+ } else {
+ assert(cs->lru.head == entry_id);
+ }
+
+ return 0;
}
-DECLARE_CONTENT_STORE(lru);
+DECLARE_CS(lru);
diff --git a/hicn-light/src/hicn/content_store/lru.h b/hicn-light/src/hicn/content_store/lru.h
index 61341921f..574f9da7d 100644
--- a/hicn-light/src/hicn/content_store/lru.h
+++ b/hicn-light/src/hicn/content_store/lru.h
@@ -13,14 +13,18 @@
* limitations under the License.
*/
-#ifndef HICNLIGHT_CONTENT_STORE_LRU_H
-#define HICNLIGHT_CONTENT_STORE_LRU_H
+#ifndef HICNLIGHT_CS_LRU_H
+#define HICNLIGHT_CS_LRU_H
typedef struct {
- // This LRU is just for keeping track of insertion and access order.
- //ListLru *lru;
- void * lru;
-} content_store_lru_data_t;
+ off_t prev;
+ off_t next;
+} cs_entry_lru_state_t;
+
+typedef struct {
+ off_t head;
+ off_t tail;
+} cs_lru_state_t;
typedef struct {
uint64_t countExpiryEvictions;
@@ -29,6 +33,6 @@ typedef struct {
uint64_t countAdds;
uint64_t countHits;
uint64_t countMisses;
-} content_store_lru_stats_t;
+} cs_lru_stats_t;
-#endif /* HICNLIGHT_CONTENT_STORE_LRU_H */
+#endif /* HICNLIGHT_CS_LRU_H */
diff --git a/hicn-light/src/hicn/core/CMakeLists.txt b/hicn-light/src/hicn/core/CMakeLists.txt
index b1f952a43..f877717aa 100644
--- a/hicn-light/src/hicn/core/CMakeLists.txt
+++ b/hicn-light/src/hicn/core/CMakeLists.txt
@@ -26,8 +26,8 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/listener.h
${CMAKE_CURRENT_SOURCE_DIR}/listener_table.h
${CMAKE_CURRENT_SOURCE_DIR}/listener_vft.h
- ${CMAKE_CURRENT_SOURCE_DIR}/messagePacketType.h
${CMAKE_CURRENT_SOURCE_DIR}/msgbuf.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/msgbuf_pool.h
${CMAKE_CURRENT_SOURCE_DIR}/packet_cache.h
${CMAKE_CURRENT_SOURCE_DIR}/pit.h
${CMAKE_CURRENT_SOURCE_DIR}/prefix_stats.h
@@ -57,6 +57,7 @@ list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/listener_vft.c
${CMAKE_CURRENT_SOURCE_DIR}/mapme.c
${CMAKE_CURRENT_SOURCE_DIR}/msgbuf.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/msgbuf_pool.c
${CMAKE_CURRENT_SOURCE_DIR}/nameBitvector.c
${CMAKE_CURRENT_SOURCE_DIR}/name.c
${CMAKE_CURRENT_SOURCE_DIR}/packet_cache.c
diff --git a/hicn-light/src/hicn/core/address.h b/hicn-light/src/hicn/core/address.h
index d13fc99ed..35d0f63ea 100644
--- a/hicn-light/src/hicn/core/address.h
+++ b/hicn-light/src/hicn/core/address.h
@@ -18,8 +18,8 @@
* \brief Address
*/
-#ifndef HICN_ADDRESS_H
-#define HICN_ADDRESS_H
+#ifndef HICNLIGHT_ADDRESS_H
+#define HICNLIGHT_ADDRESS_H
#include <netinet/in.h>
@@ -84,5 +84,5 @@ extern const char * _address_family_str[];
#define address6_empty(address) (memcmp(address6_ip(address).s6_addr, &in6addr_any, sizeof(struct in6_addr)) == 0)
#define address_empty(address) (address_family(address) == AF_INET ? address4_empty(address) : address6_empty(address))
-#endif /* HICN_ADDRESS_H */
+#endif /* HICNLIGHT_ADDRESS_H */
diff --git a/hicn-light/src/hicn/core/address_pair.h b/hicn-light/src/hicn/core/address_pair.h
index 7a08426a4..4dfdfd9de 100644
--- a/hicn-light/src/hicn/core/address_pair.h
+++ b/hicn-light/src/hicn/core/address_pair.h
@@ -18,8 +18,8 @@
* \brief Address pair
*/
-#ifndef HICN_ADDRESS_PAIR_H
-#define HICN_ADDRESS_PAIR_H
+#ifndef HICNLIGHT_ADDRESS_PAIR_H
+#define HICNLIGHT_ADDRESS_PAIR_H
#include <hicn/core/address.h>
#include <hicn/util/ip_address.h>
@@ -40,9 +40,9 @@ int address_pair_from_ip_port(address_pair_t * pair, int family,
(address_family(address_pair_get_local(pair)))
#define address_pair_get_remote_family(pair) \
(address_family(address_pair_get_remote(pair)))
-#define address_pair_get_family(pair) address_pair_local_family(pair)
+#define address_pair_get_family(pair) address_pair_get_local_family(pair)
#define address_pair_is_valid(pair) \
(address_pair_get_local_family(pair) == address_pair_get_remote_family(pair))
-#endif /* HICN_ADDRESS_PAIR_H */
+#endif /* HICNLIGHT_ADDRESS_PAIR_H */
diff --git a/hicn-light/src/hicn/core/connection.c b/hicn-light/src/hicn/core/connection.c
index ba56ce459..680e82b9b 100644
--- a/hicn-light/src/hicn/core/connection.c
+++ b/hicn-light/src/hicn/core/connection.c
@@ -399,9 +399,9 @@ connection_process_buffer(connection_t * connection, const uint8_t * buffer, siz
msgbuf_t msgbuf;
MessagePacketType packet_type;
if (messageHandler_IsInterest(message->messageHead)) {
- packet_type = MESSAGE_TYPE_INTEREST;
+ packet_type = MSGBUF_TYPE_INTEREST;
} else if (messageHandler_IsData(message->messageHead)) {
- packet_type = MESSAGE_TYPE_DATA;
+ packet_type = MSGBUF_TYPE_DATA;
} else {
ERROR("Dropped packet that is not interest nor data");
return -1;
@@ -457,18 +457,27 @@ _connection_send(const connection_t * connection, msgbuf_t * msgbuf, bool queue)
}
bool
-connection_send(const connection_t * connection, msgbuf_t * msgbuf, bool queue)
+connection_flush(const connection_t * connection)
{
- assert(connection);
+ // XXX Replace this with a proper flush function to avoid implementing the
+ // same thing everywhere
+ return _connection_send(connection, NULL, false);
+}
- /* NULL message means flush */
- if (!msgbuf)
- return _connection_send(connection, NULL, false);
+bool
+connection_send(const connection_t * connection, off_t msgbuf_id, bool queue)
+{
+ assert(connection);
+ assert(msgbuf_id_is_valid(msgbuf_id)); // XXX we now have a flush() function
if (!connection_is_up(connection))
return false;
- if (msgbuf_get_type(msgbuf) == MESSAGE_TYPE_DATA) {
+ const forwarder_t * forwarder = connection_get_forwarder(connection);
+ const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
+ if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA) {
uint8_t conn_id = (uint8_t)connection_get_id(connection);
msgbuf_update_pathlabel(msgbuf, conn_id);
}
@@ -504,7 +513,7 @@ connection_resend(const connection_t * connection, msgbuf_t * msgbuf, bool
if (!connection_is_up(connection))
return ret;
- if (msgbuf_get_type(msgbuf) == MESSAGE_TYPE_DATA) {
+ if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA) {
uint8_t conn_id = (uint8_t)connection_get_id(connection);
uint32_t old_path_label = msgbuf_get_pathlabel(msgbuf);
msgbuf_update_pathlabel(msgbuf, conn_id);
@@ -551,7 +560,7 @@ connection_wldr_allow_autostart(connection_t * connection, bool value)
}
bool
-connection_wldr_autostart_is_allowed(connection_t * connection)
+connection_wldr_autostart_is_allowed(const connection_t * connection)
{
return connection->wldr_autostart;
}
@@ -579,7 +588,7 @@ connection_has_wldr(const connection_t * connection)
}
void
-connection_wldr_detect_losses(const connection_t * connection, msgbuf_t * msgbuf)
+connection_wldr_detect_losses(const connection_t * connection, const msgbuf_t * msgbuf)
{
if (!connection->wldr)
return;
@@ -587,7 +596,7 @@ connection_wldr_detect_losses(const connection_t * connection, msgbuf_t * msgbuf
}
void
-connection_wldr_handle_notification(const connection_t * connection, msgbuf_t * msgbuf)
+connection_wldr_handle_notification(const connection_t * connection, const msgbuf_t * msgbuf)
{
if (!connection->wldr)
return;
diff --git a/hicn-light/src/hicn/core/connection.h b/hicn-light/src/hicn/core/connection.h
index 6297e193c..d9ef817d2 100644
--- a/hicn-light/src/hicn/core/connection.h
+++ b/hicn-light/src/hicn/core/connection.h
@@ -87,6 +87,7 @@ typedef struct {
#define connection_get_name(C) ((C)->name)
#define connection_get_type(C) ((C)->type)
#define connection_has_valid_id(C) (connection_id_is_valid(connection_get_id(C)))
+#define connection_has_valid_type(C) (face_type_is_valid(connection_get_type(C)))
#define connection_get_pair(C) (&(C)->pair)
#define connection_get_local(C) (address_pair_local(connection_get_pair(C)))
#define connection_get_remote(C) (address_pair_remote(connection_get_pair(C)))
@@ -191,7 +192,9 @@ int connection_finalize(connection_t * connection);
int connection_send_packet(const connection_t * connection,
const uint8_t * packet, size_t size);
-bool connection_send(const connection_t * connection, msgbuf_t * msgbuf,
+bool connection_flush(const connection_t * connection);
+
+bool connection_send(const connection_t * connection, off_t msgbuf_id,
bool queue);
size_t connection_process_buffer(connection_t * connection, const uint8_t * buffer, size_t size);
@@ -200,14 +203,16 @@ size_t connection_process_buffer(connection_t * connection, const uint8_t * buff
void connection_wldr_allow_autostart(connection_t * connection, bool value);
-bool connection_wldr_autostart_is_allowed(connection_t * connection);
+bool connection_wldr_autostart_is_allowed(const connection_t * connection);
void connection_wldr_enable(connection_t * connection, bool value);
bool connection_has_wldr(const connection_t * connection);
-void connection_wldr_detect_losses(const connection_t * connection, msgbuf_t * msgbuf);
+void connection_wldr_detect_losses(const connection_t * connection, const msgbuf_t * msgbuf);
+
+void connection_wldr_handle_notification(const connection_t * connection, const msgbuf_t * msgbuf);
-void connection_wldr_handle_notification(const connection_t * connection, msgbuf_t * msgbuf);
+#define connection_get_forwarder(connection) (connection->forwarder)
#endif /* HICNLIGHT_CONNECTION_H */
diff --git a/hicn-light/src/hicn/core/connection_table.c b/hicn-light/src/hicn/core/connection_table.c
index 0b7df0384..c4010fe40 100644
--- a/hicn-light/src/hicn/core/connection_table.c
+++ b/hicn-light/src/hicn/core/connection_table.c
@@ -46,7 +46,7 @@ _connection_table_create(size_t init_size, size_t max_size)
* We start by allocating a reasonably-sized pool, as this will eventually
* be resized if needed.
*/
- pool_init(table->connections, init_size);
+ pool_init(table->connections, init_size, 0);
return table;
}
diff --git a/hicn-light/src/hicn/core/connection_vft.h b/hicn-light/src/hicn/core/connection_vft.h
index 589f39536..1ff4d7702 100644
--- a/hicn-light/src/hicn/core/connection_vft.h
+++ b/hicn-light/src/hicn/core/connection_vft.h
@@ -42,10 +42,11 @@ const connection_ops_t connection_ ## NAME = { \
.get_socket = listener_ ## NAME ## _get_socket, \
.send = connection_ ## NAME ## _send, \
.send_packet = connection_ ## NAME ## _send_packet, \
- .read_callback = connection_ ## NAME ## _read_callback, \
.data_size = sizeof(connection_ ## NAME ## _data_t), \
};
+// .read_callback = connection_ ## NAME ## _read_callback,
+
extern const connection_ops_t * connection_vft[];
#endif /* HICNLIGHT_CONNECTION_VFT_H */
diff --git a/hicn-light/src/hicn/core/content_store.c b/hicn-light/src/hicn/core/content_store.c
index 77d40ace5..74b675224 100644
--- a/hicn-light/src/hicn/core/content_store.c
+++ b/hicn-light/src/hicn/core/content_store.c
@@ -26,10 +26,10 @@
#include "content_store.h"
-extern const content_store_ops_t content_store_lru;
+extern const cs_ops_t cs_lru;
-const content_store_ops_t * const content_store_vft[] = {
- [CONTENT_STORE_TYPE_LRU] = &content_store_lru,
+const cs_ops_t * const cs_vft[] = {
+ [CS_TYPE_LRU] = &cs_lru,
};
// XXX TODO replace by a single packet cache
@@ -37,26 +37,35 @@ const content_store_ops_t * const content_store_vft[] = {
// XXX TODO getting rid of logger and the need to acquire
// XXX TODO separate cs from vft, same with strategy
-#define content_store_entry_from_msgbuf(entry, msgbuf) \
+#define cs_entry_from_msgbuf(entry, msgbuf) \
do { \
(entry)->hasExpiryTimeTicks = msgbuf_HasContentExpiryTime(msgbuf); \
if ((entry)->hasExpiryTimeTicks) \
(entry)->expiryTimeTicks = msgbuf_GetContentExpiryTimeTicks(msgbuf); \
} while(0)
+/* This is only used as a hint for first allocation, as the table is resizeable */
+#define DEFAULT_CS_SIZE 64
-content_store_t *
-_content_store_create(content_store_type_t type, size_t init_size, size_t max_size)
+cs_t *
+_cs_create(cs_type_t type, size_t init_size, size_t max_size)
{
- content_store_t * cs = malloc(sizeof(content_store_t));
+ if (!CS_TYPE_VALID(type)) {
+ ERROR("[cs_create] Invalid content store type");
+ return NULL;
+ }
+
+ if (init_size == 0)
+ init_size = DEFAULT_CS_SIZE;
+
+ cs_t * cs = malloc(sizeof(cs_t));
if (!cs)
- goto ERR_MALLOC;
- if (!CONTENT_STORE_TYPE_VALID(type))
- goto ERR_TYPE;
+ return NULL;
+
cs->type = type;
// XXX TODO an entry = data + metadata specific to each policy
- pool_init(cs->entries, init_size);
+ pool_init(cs->entries, init_size, max_size);
// data
// options
@@ -66,59 +75,65 @@ _content_store_create(content_store_type_t type, size_t init_size, size_t max_si
// index by name
cs->index_by_name = kh_init(cs_name);
+#if 0
cs->index_by_expiry_time = NULL;
if (!cs->index_by_expiry_time) {
ERROR("Could not create index (expiry time)");
goto ERR_INDEX_EXPIRY;
}
+#endif
+ cs_vft[type]->initialize(cs);
- // XXX indices specific to each policy => vft
- // index by expiration time
- // lru ?
-
- content_store_vft[type]->initialize(cs);
-
+ return cs;
+#if 0
ERR_INDEX_EXPIRY:
- // XXX TODO
-ERR_TYPE:
-ERR_MALLOC:
+ free(cs);
+ // XXX
+
return NULL;
+#endif
}
void
-content_store_free(content_store_t * cs)
+cs_free(cs_t * cs)
{
- content_store_vft[cs->type]->finalize(cs);
+ cs_vft[cs->type]->finalize(cs);
+#if 0
if (cs->index_by_expiry_time)
; //listTimeOrdered_Release(&(store->indexByExpirationTime));
+#endif
}
-void content_store_clear(content_store_t * cs)
+void cs_clear(cs_t * cs)
{
// XXX TODO
}
-msgbuf_t *
-content_store_match(content_store_t * cs, msgbuf_t * msgbuf, uint64_t now)
+off_t
+cs_match(cs_t * cs, off_t msgbuf_id, uint64_t now)
{
assert(cs);
+
+ const msgbuf_pool_t * msgbuf_pool = cs_get_msgbuf_pool(cs);
+ const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
assert(msgbuf);
- assert(msgbuf_get_type(msgbuf) == MESSAGE_TYPE_INTEREST);
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
/* Lookup entry by name */
khiter_t k = kh_get_cs_name(cs->index_by_name, msgbuf_get_name(msgbuf));
if (k == kh_end(cs->index_by_name))
- return NULL;
- content_store_entry_t * entry = cs->entries + kh_val(cs->index_by_name, k);
+ return INVALID_MSGBUF_ID;
+ cs_entry_t * entry = cs->entries + kh_val(cs->index_by_name, k);
assert(entry);
/* Remove any expired entry */
- if (content_store_entry_has_expiry_time(entry) &&
- content_store_entry_expiry_time(entry) < now) {
+ if (cs_entry_has_expiry_time(entry) &&
+ cs_entry_get_expiry_time(entry) < now) {
// the entry is expired, we can remove it
- content_store_remove_entry(cs, entry);
+ cs_remove_entry(cs, entry);
goto NOT_FOUND;
}
@@ -130,69 +145,139 @@ content_store_match(content_store_t * cs, msgbuf_t * msgbuf, uint64_t now)
DEBUG("CS %p LRU match %p (hits %" PRIu64 ", misses %" PRIu64 ")",
cs, msgbuf, cs->stats.lru.countHits, cs->stats.lru.countMisses);
- return content_store_entry_message(entry);
+ return cs_entry_get_msgbuf_id(entry);
NOT_FOUND:
cs->stats.lru.countMisses++;
DEBUG("ContentStoreLRU %p missed msgbuf %p (hits %" PRIu64 ", misses %" PRIu64 ")",
cs, msgbuf, cs->stats.lru.countHits, cs->stats.lru.countMisses);
- return NULL;
+ return INVALID_MSGBUF_ID;
}
-void
-content_store_add(content_store_t * cs, msgbuf_t * msgbuf, uint64_t now)
+// XXX temp
+// XXX pool member pointer might change, not the ID.
+#define msgbuf_acquire(x) (x)
+
+cs_entry_t *
+cs_add(cs_t * cs, off_t msgbuf_id, uint64_t now)
{
assert(cs);
- assert(msgbuf);
- assert(msgbuf_get_type(msgbuf) == MESSAGE_TYPE_DATA);
+ assert(msgbuf_id_is_valid(msgbuf_id));
+
+#if DEBUG
+ forwarder_t * forwarder = cs_get_forwarder(cs);
+ msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA);
+#endif
- content_store_entry_t * entry = NULL;
+#if 0
+ // entry exists ?
+ cs_entry_t *dataEntry = parcHashCodeTable_Get(data->storageByName, content);
+ if(dataEntry)
+ _cs_lru_purge_entry(data, dataEntry);
+#endif
+
+#if 0
+ // check expiration
+ uint64_t expiryTimeTicks = contentStoreEntry_MaxExpiryTime;
+ if (message_HasContentExpiryTime(content))
+ expiryTimeTicks = message_GetContentExpiryTimeTicks(content);
+
+ // Don't add anything that's already expired or has exceeded RCT.
+ if (now >= expiryTimeTicks)
+ return false;
+#endif
+
+#if 0
+ // evict
+ if (data->objectCount >= data->objectCapacity)
+ // Store is full. Need to make room.
+ _evictByStorePolicy(data, now);
+#endif
+
+ cs_entry_t * entry = NULL;
+ off_t entry_id = pool_get(cs->entries, entry);
+ if (!entry)
+ goto ERR_ENTRY;
+
+ *entry = (cs_entry_t) {
+ .msgbuf_id = msgbuf_id,
+ .hasExpiryTimeTicks = false, // XXX
+ .expiryTimeTicks = 0, // XXX
+ };
+
+ // update indices
+
+ // update policy index
+ /* eg. LRU: add new the entry at the head of the LRU */
+ if (!cs_vft[cs->type]->add_entry(cs, entry_id))
+ goto ERR_VFT;
- /* borrow from content_store_lru_add_entry */
+#if 0
+ // update expiry time index
+ if (cs_entry_has_expiry_time(entry)) {
+ }
+#endif
+
+#if 0
+ // stats
+ data->objectCount++;
+ data->stats.countAdds++;
+#endif
+
+ return entry;
- content_store_vft[cs->type]->add_entry(cs, entry);
+ERR_VFT:
+ pool_put(cs->entries, entry);
+ERR_ENTRY:
+ return NULL;
}
-void
-content_store_remove_entry(content_store_t * cs, content_store_entry_t * entry)
+int
+cs_remove_entry(cs_t * cs, cs_entry_t * entry)
{
assert(cs);
assert(entry);
- if (content_store_entry_has_expiry_time(entry))
+ if (cs_entry_has_expiry_time(entry))
; // XXX TODO listTimeOrdered_Remove(store->indexByExpirationTime, entryToPurge);
- msgbuf_t * msgbuf = content_store_entry_message(entry);
+ off_t msgbuf_id = cs_entry_get_msgbuf_id(entry);
+
+ const msgbuf_pool_t * msgbuf_pool = cs_get_msgbuf_pool(cs);
+ const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
khiter_t k = kh_get_cs_name(cs->index_by_name, msgbuf_get_name(msgbuf));
if (k != kh_end(cs->index_by_name))
kh_del(cs_name, cs->index_by_name, k);
// This will take care of LRU entry for instance
- content_store_vft[cs->type]->remove_entry(cs, entry);
+ cs_vft[cs->type]->remove_entry(cs, entry);
//store->objectCount--;
pool_put(cs->entries, entry);
+ return 0;
}
//
// XXX TODO what is the difference between purge and remove ?
bool
-content_store_remove(content_store_t * cs, msgbuf_t * msgbuf)
+cs_remove(cs_t * cs, msgbuf_t * msgbuf)
{
assert(cs);
assert(msgbuf);
- assert(msgbuf_get_type(msgbuf) == MESSAGE_TYPE_DATA);
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA);
/* Lookup entry by name */
khiter_t k = kh_get_cs_name(cs->index_by_name, msgbuf_get_name(msgbuf));
if (k == kh_end(cs->index_by_name))
return false;
- content_store_entry_t * entry = cs->entries + kh_val(cs->index_by_name, k);
+ cs_entry_t * entry = cs->entries + kh_val(cs->index_by_name, k);
assert(entry);
- content_store_remove_entry(cs, entry);
+ cs_remove_entry(cs, entry);
return true;
}
diff --git a/hicn-light/src/hicn/core/content_store.h b/hicn-light/src/hicn/core/content_store.h
index 5cddeaa87..2973b3955 100644
--- a/hicn-light/src/hicn/core/content_store.h
+++ b/hicn-light/src/hicn/core/content_store.h
@@ -1,41 +1,44 @@
-#ifndef HICNLIGHT_CONTENT_STORE_H
-#define HICNLIGHT_CONTENT_STORE_H
+#ifndef HICNLIGHT_CS_H
+#define HICNLIGHT_CS_H
-#include <hicn/base/khash.h>
-#include <hicn/base/pool.h>
-#include <hicn/core/msgbuf.h>
-#include <hicn/core/name.h>
-#include <hicn/content_store/lru.h>
+#include "msgbuf.h"
+#include "msgbuf_pool.h"
+#include "name.h"
+#include "../base/khash.h"
+#include "../base/pool.h"
+#include "../content_store/lru.h"
+
+#define INVALID_ENTRY_ID ~0ul /* off_t */
typedef struct {
- msgbuf_t * message;
+ off_t msgbuf_id;
//ListLruEntry *lruEntry;
bool hasExpiryTimeTicks;
uint64_t expiryTimeTicks; // single value for both ? 0 allowed ?
-} content_store_entry_t;
+ union {
+ off_t prev;
+ off_t next;
+ } lru;
+} cs_entry_t;
-#define content_store_entry_message(entry) ((entry)->message)
-#define content_store_entry_has_expiry_time(entry) ((entry)->hasExpiryTimeTicks)
-#define content_store_entry_expiry_time(entry) ((entry)->expiryTimeTicks)
+#define cs_entry_get_msgbuf_id(entry) ((entry)->msgbuf_id)
+#define cs_entry_has_expiry_time(entry) ((entry)->hasExpiryTimeTicks)
+#define cs_entry_get_expiry_time(entry) ((entry)->expiryTimeTicks)
typedef enum {
- CONTENT_STORE_TYPE_UNDEFINED,
- CONTENT_STORE_TYPE_LRU,
- CONTENT_STORE_TYPE_N,
-} content_store_type_t;
+ CS_TYPE_UNDEFINED,
+ CS_TYPE_LRU,
+ CS_TYPE_N,
+} cs_type_t;
-#define CONTENT_STORE_TYPE_VALID(type) \
- (type != CONTENT_STORE_TYPE_UNDEFINED) && \
- (type != CONTENT_STORE_TYPE_N)
+#define CS_TYPE_VALID(type) \
+ (type != CS_TYPE_UNDEFINED) && \
+ (type != CS_TYPE_N)
typedef struct {
/* The maximum allowed expiry time (will never be exceeded). */
uint64_t max_expiry_time; // XXX part of lru ?
-} content_store_options_t;
-
-typedef union {
- content_store_lru_stats_t lru;
-} content_store_stats_t;
+} cs_options_t;
// XXX TODO
#define name_hash(name) (name_HashCode(name))
@@ -44,22 +47,30 @@ typedef union {
KHASH_INIT(cs_name, const Name *, unsigned, 0, name_hash, name_hash_eq);
typedef struct {
- content_store_type_t type;
- size_t max_size;
+ cs_type_t type;
// XXX TODO api to dynamically set max size
- content_store_entry_t * entries; // pool
+ cs_entry_t * entries; // pool
kh_cs_name_t * index_by_name;
+#if 0
void * index_by_expiry_time;
- //ListTimeOrdered *indexByExpirationTime;
-
+#endif
+ const msgbuf_pool_t * msgbuf_pool;
void * data; // per cs type data
void * options;
- content_store_stats_t stats;
-} content_store_t;
+
+ union {
+ cs_lru_stats_t lru;
+ } stats;
+
+
+ union {
+ cs_lru_state_t lru;
+ };
+} cs_t;
/**
* @brief Create a new content store (extended parameters)
@@ -68,42 +79,53 @@ typedef struct {
* @param[in] init_size Initially allocated size (hint, 0 = use default value)
* @param[in] max_size Maximum size (0 = unlimited)
*
- * @return content_store_t* - The newly created content store
+ * @return cs_t* - The newly created content store
*/
-content_store_t * _content_store_create(content_store_type_t type, size_t init_size, size_t max_size);
+cs_t * _cs_create(cs_type_t type, size_t init_size, size_t max_size);
/**
* @brief Create a new content store
*
* @param[in] type Content store type
*
- * @return content_store_t* - The newly created content store
+ * @return cs_t* - The newly created content store
*/
-#define content_store_create( TYPE) _content_store_create((TYPE), 0, 0)
+#define cs_create(TYPE) _cs_create((TYPE), 0, 0)
+
+void cs_free(cs_t * cs);
+
+void cs_clear(cs_t * cs);
+
+off_t cs_match(cs_t * cs, off_t msgbuf_id, uint64_t now);
-void content_store_free(content_store_t * cs);
+cs_entry_t * cs_add(cs_t * cs, off_t msgbuf_id, uint64_t now);
-void content_store_clear(content_store_t * cs);
+int cs_remove_entry(cs_t * cs, cs_entry_t * entry);
-msgbuf_t * content_store_match(content_store_t * cs, msgbuf_t * msgbuf, uint64_t now);
+bool cs_remove(cs_t * cs, msgbuf_t * msgbuf);
-void content_store_add(content_store_t * cs, msgbuf_t * msgbuf, uint64_t now);
+#define cs_size(content_store) (pool_len(cs->entries))
-void content_store_remove_entry(content_store_t * cs, content_store_entry_t * entry);
+void cs_purge_entry(cs_t * cs, cs_entry_t * entry);
-bool content_store_remove(content_store_t * cs, msgbuf_t * msgbuf);
+#define cs_get_entry_id(cs, entry) (entry - cs->entries)
-#define content_store_size(content_store) (pool_len(cs->entries))
+#define cs_entry_at(cs, id) (&(cs)->entries[id])
-void content_store_purge_entry(content_store_t * cs, content_store_entry_t * entry);
+static inline
+const msgbuf_pool_t *
+cs_get_msgbuf_pool(const cs_t * cs)
+{
+ return cs->msgbuf_pool;
+}
typedef struct {
const char * name;
- void (*initialize)(content_store_t * cs);
+ void (*initialize)(cs_t * cs);
- void (*finalize)(content_store_t * cs);
+ void (*finalize)(cs_t * cs);
/**
* Place a Message representing a ContentObject into the ContentStore. If
@@ -116,7 +138,7 @@ typedef struct {
* UTC epoch.
*/
// XXX Do we always get now before adding ?
- bool (*add_entry)(content_store_t * cs, content_store_entry_t * entry);
+ int (*add_entry)(cs_t * cs, off_t entry_id);
/**
* The function to call to remove content from the ContentStore.
@@ -126,19 +148,19 @@ typedef struct {
* @param storeImpl - a pointer to this ContentStoreInterface instance.
* @param content - a pointer to a `Message` to remove from the store.
*/
- void (*remove_entry)(content_store_t * cs, content_store_entry_t * entry);
+ int (*remove_entry)(cs_t * cs, cs_entry_t * entry);
-} content_store_ops_t;
+} cs_ops_t;
-extern const content_store_ops_t * const content_store_vft[];
+extern const cs_ops_t * const cs_vft[];
-#define DECLARE_CONTENT_STORE(NAME) \
- const content_store_ops_t content_store_ ## NAME = { \
+#define DECLARE_CS(NAME) \
+ const cs_ops_t cs_ ## NAME = { \
.name = #NAME, \
- .initialize = content_store_ ## NAME ## _initialize, \
- .finalize = content_store_ ## NAME ## _finalize, \
- .add_entry = content_store_ ## NAME ## _add_entry, \
- .remove_entry = content_store_ ## NAME ## _remove_entry, \
+ .initialize = cs_ ## NAME ## _initialize, \
+ .finalize = cs_ ## NAME ## _finalize, \
+ .add_entry = cs_ ## NAME ## _add_entry, \
+ .remove_entry = cs_ ## NAME ## _remove_entry, \
}
-#endif /* HICNLIGHT_CONTENT_STORE_H */
+#endif /* HICNLIGHT_CS_H */
diff --git a/hicn-light/src/hicn/core/forwarder.c b/hicn-light/src/hicn/core/forwarder.c
index 9c3df906d..543fc99e4 100644
--- a/hicn-light/src/hicn/core/forwarder.c
+++ b/hicn-light/src/hicn/core/forwarder.c
@@ -31,7 +31,7 @@
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
-#include <hicn/hicn-light/config.h>
+//#include <hicn/hicn-light/config.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -41,18 +41,20 @@
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
-#include <hicn/core/connection_table.h>
-#include <hicn/core/listener_table.h>
-#include <hicn/core/pit.h>
-#include <hicn/core/fib.h>
-#include <hicn/core/content_store.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/core/messagePacketType.h>
+#include "connection_table.h"
+#include "content_store.h"
+#include "fib.h"
+#include "forwarder.h"
+#include "listener_table.h"
#ifdef WITH_MAPME
-#include <hicn/core/mapme.h>
+#include "mapme.h"
#endif /* WITH_MAPME */
-#include <hicn/config/configuration.h>
-#include <hicn/config/configuration_file.h>
+#include "msgbuf.h"
+#include "msgbuf_pool.h"
+#include "pit.h"
+#include "../config/configuration.h"
+#include "../config/configuration_file.h"
+#include "../io/base.h" // MAX_MSG
#ifdef WITH_PREFIX_STATS
#include <hicn/core/prefix_stats.h>
@@ -61,10 +63,8 @@
#include <hicn/core/wldr.h>
#include <hicn/util/log.h>
-#define DEFAULT_PIT_SIZE 65535
-
typedef struct {
- uint32_t countReceived;
+ uint32_t countReceived; // Interest & Data only
uint32_t countInterestsReceived;
uint32_t countObjectsReceived;
@@ -110,15 +110,16 @@ struct forwarder_s {
pit_t * pit;
- content_store_t * content_store;
+ cs_t * cs;
fib_t * fib;
+ msgbuf_pool_t * msgbuf_pool;
#ifdef WITH_MAPME
mapme_t * mapme;
#endif /* WITH_MAPME */
- bool store_in_content_store;
- bool serve_from_content_store;
+ bool store_in_cs;
+ bool serve_from_cs;
forwarder_stats_t stats;
#ifdef WITH_PREFIX_STATS
@@ -132,7 +133,7 @@ struct forwarder_s {
unsigned pending_conn[MAX_MSG];
size_t num_pending_conn;
- msgbuf_t msgbuf; /* Storage for msgbuf, which are currently processed 1 by 1 */
+ //msgbuf_t msgbuf; /* Storage for msgbuf, which are currently processed 1 by 1 */
};
@@ -172,27 +173,6 @@ forwarder_seed(forwarder_t * forwarder) {
#endif
}
-int
-init_batch_buffers(batch_buffer_t * bb)
-{
- /* Setup recvmmsg data structures. */
- for (unsigned i = 0; i < MAX_MSG; i++) {
- char *buf = &bb->buffers[i][0];
- struct iovec *iovec = &bb->iovecs[i];
- struct mmsghdr *msg = &bb->msghdr[i];
-
- msg->msg_hdr.msg_iov = iovec;
- msg->msg_hdr.msg_iovlen = 1;
-
- msg->msg_hdr.msg_name = &bb->addrs[i];
- msg->msg_hdr.msg_namelen = sizeof(struct sockaddr_storage);
-
- iovec->iov_base = &buf[0];
- iovec->iov_len = MTU;
- }
- return 0;
-}
-
forwarder_t *
forwarder_create()
{
@@ -218,22 +198,26 @@ forwarder_create()
if (!forwarder->fib)
goto ERR_FIB;
- forwarder->pit = pit_create(DEFAULT_PIT_SIZE);
+ forwarder->msgbuf_pool = msgbuf_pool_create();
+ if (!forwarder->msgbuf_pool)
+ goto ERR_PACKET_POOL;
+
+ forwarder->pit = pit_create();
if (!forwarder->pit)
goto ERR_PIT;
size_t objectStoreSize =
- configuration_content_store_get_size(forwarder_get_configuration(forwarder));
- forwarder->content_store = _content_store_create(CONTENT_STORE_TYPE_LRU,
+ configuration_cs_get_size(forwarder_get_configuration(forwarder));
+ forwarder->cs = _cs_create(CS_TYPE_LRU,
objectStoreSize, 0);
- if (!forwarder->content_store)
- goto ERR_CONTENT_STORE;
+ if (!forwarder->cs)
+ goto ERR_CS;
- // the two flags for the content_store are set to true by default. If the content_store
+ // the two flags for the cs are set to true by default. If the cs
// is active it always work as expected unless the use modifies this
// values using controller
- forwarder->store_in_content_store = true;
- forwarder->serve_from_content_store = true;
+ forwarder->store_in_cs = true;
+ forwarder->serve_from_cs = true;
#if 0
forwarder->signal_term = dispatcher_CreateSignalEvent(
@@ -293,10 +277,12 @@ ERR_MAPME:
dispatcher_Destroy(&(forwarder->dispatcher));
#endif
- content_store_free(forwarder->content_store);
-ERR_CONTENT_STORE:
+ cs_free(forwarder->cs);
+ERR_CS:
pit_free(forwarder->pit);
ERR_PIT:
+ msgbuf_pool_free(forwarder->msgbuf_pool);
+ERR_PACKET_POOL:
fib_free(forwarder->fib);
ERR_FIB:
connection_table_free(forwarder->connection_table);
@@ -335,8 +321,9 @@ forwarder_free(forwarder_t * forwarder)
dispatcher_Destroy(&(forwarder->dispatcher));
#endif
- content_store_free(forwarder->content_store);
+ cs_free(forwarder->cs);
pit_free(forwarder->pit);
+ msgbuf_pool_free(forwarder->msgbuf_pool);
fib_free(forwarder->fib);
connection_table_free(forwarder->connection_table);
listener_table_free(forwarder->listener_table);
@@ -394,63 +381,56 @@ forwarder_get_listener_table(forwarder_t * forwarder)
}
void
-forwarder_content_store_set_store(forwarder_t * forwarder, bool val)
+forwarder_cs_set_store(forwarder_t * forwarder, bool val)
{
assert(forwarder);
- forwarder->store_in_content_store = val;
+ forwarder->store_in_cs = val;
}
bool
-forwarder_content_store_get_store(forwarder_t * forwarder)
+forwarder_cs_get_store(forwarder_t * forwarder)
{
assert(forwarder);
- return forwarder->store_in_content_store;
+ return forwarder->store_in_cs;
}
void
-forwarder_content_store_set_serve(forwarder_t * forwarder, bool val)
+forwarder_cs_set_serve(forwarder_t * forwarder, bool val)
{
assert(forwarder);
- forwarder->serve_from_content_store = val;
+ forwarder->serve_from_cs = val;
}
bool
-forwarder_content_store_get_serve(forwarder_t * forwarder)
+forwarder_cs_get_serve(forwarder_t * forwarder)
{
assert(forwarder);
- return forwarder->serve_from_content_store;
+ return forwarder->serve_from_cs;
}
void
-forwarder_content_store_set_size(forwarder_t * forwarder, size_t size)
+forwarder_cs_set_size(forwarder_t * forwarder, size_t size)
{
assert(forwarder);
- content_store_free(forwarder->content_store);
+ cs_free(forwarder->cs);
// XXX TODO
#if 0
- ContentStoreConfig content_storeConfig = {.objectCapacity =
+ ContentStoreConfig csConfig = {.objectCapacity =
maximumContentStoreSize};
- forwarder->content_store =
- content_storeLRU_Create(&content_storeConfig, forwarder->logger);
+ forwarder->cs =
+ csLRU_Create(&csConfig, forwarder->logger);
#endif
}
void
-forwarder_content_store_clear(forwarder_t * forwarder)
+forwarder_cs_clear(forwarder_t * forwarder)
{
assert(forwarder);
- content_store_clear(forwarder->content_store);
-}
-
-void
-forwarder_receive_command(forwarder_t * forwarder, command_type_t command_type,
- uint8_t * packet, unsigned connection_id)
-{
- configuration_receive_command(forwarder->config, command_type, packet, connection_id);
+ cs_clear(forwarder->cs);
}
/**
@@ -465,17 +445,20 @@ forwarder_receive_command(forwarder_t * forwarder, command_type_t command_type,
*
*/
static
-void
-forwarder_drop(forwarder_t * forwarder, msgbuf_t *message)
+ssize_t
+forwarder_drop(forwarder_t * forwarder, off_t msgbuf_id)
{
forwarder->stats.countDropped++;
- switch (msgbuf_get_type(message)) {
- case MESSAGE_TYPE_INTEREST:
+ const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
+ switch (msgbuf_get_type(msgbuf)) {
+ case MSGBUF_TYPE_INTEREST:
forwarder->stats.countInterestsDropped++;
break;
- case MESSAGE_TYPE_DATA:
+ case MSGBUF_TYPE_DATA:
forwarder->stats.countObjectsDropped++;
break;
@@ -484,6 +467,7 @@ forwarder_drop(forwarder_t * forwarder, msgbuf_t *message)
break;
}
+ return msgbuf_get_len(msgbuf);
// dont destroy message here, its done at end of receive
}
@@ -493,23 +477,26 @@ forwarder_drop(forwarder_t * forwarder, msgbuf_t *message)
*
*/
static
-void
-forwarder_forward_via_connection(forwarder_t * forwarder, msgbuf_t * msgbuf,
+ssize_t
+forwarder_forward_via_connection(forwarder_t * forwarder, off_t msgbuf_id,
unsigned conn_id)
{
connection_table_t * table = forwarder_get_connection_table(forwarder);
+
+ const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
const connection_t * conn = connection_table_get_by_id(table, conn_id);
if (!conn) {
forwarder->stats.countDroppedConnectionNotFound++;
- DEBUG("forward msgbuf %p to interface %u not found (count %u)",
- msgbuf, conn_id, forwarder->stats.countDroppedConnectionNotFound);
- forwarder_drop(forwarder, msgbuf);
- return;
+ DEBUG("forward msgbuf %lu to interface %u not found (count %u)",
+ msgbuf_id, conn_id, forwarder->stats.countDroppedConnectionNotFound);
+ return forwarder_drop(forwarder, msgbuf_id);
}
/* Always queue the packet... */
- bool success = connection_send(conn, msgbuf, true);
+ bool success = connection_send(conn, msgbuf_id, true);
/* ... and mark the connection as pending if this is not yet the case */
unsigned i;
@@ -523,18 +510,17 @@ forwarder_forward_via_connection(forwarder_t * forwarder, msgbuf_t * msgbuf,
if (!success) {
forwarder->stats.countSendFailures++;
- DEBUG("forward msgbuf %p to interface %u send failure (count %u)", msgbuf,
- conn_id, forwarder->stats.countSendFailures);
- forwarder_drop(forwarder, msgbuf);
- return;
+ DEBUG("forward msgbuf %llu to interface %u send failure (count %u)",
+ msgbuf_id, conn_id, forwarder->stats.countSendFailures);
+ return forwarder_drop(forwarder, msgbuf_id);
}
switch (msgbuf_get_type(msgbuf)) {
- case MESSAGE_TYPE_INTEREST:
+ case MSGBUF_TYPE_INTEREST:
forwarder->stats.countInterestForwarded++;
break;
- case MESSAGE_TYPE_DATA:
+ case MSGBUF_TYPE_DATA:
forwarder->stats.countObjectsForwarded++;
break;
@@ -546,6 +532,7 @@ forwarder_forward_via_connection(forwarder_t * forwarder, msgbuf_t * msgbuf,
conn_id, forwarder->stats.countInterestForwarded,
forwarder->stats.countObjectsForwarded);
+ return (msgbuf_get_len(msgbuf));
}
/**
@@ -559,14 +546,16 @@ forwarder_forward_via_connection(forwarder_t * forwarder, msgbuf_t * msgbuf,
static
unsigned
forwarder_forward_to_nexthops(forwarder_t * forwarder,
- msgbuf_t *msgbuf, const nexthops_t * nexthops)
+ off_t msgbuf_id, const nexthops_t * nexthops)
{
unsigned forwardedCopies = 0;
+ const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
unsigned ingressId = msgbuf_get_connection_id(msgbuf);
uint32_t old_path_label = 0;
- if (msgbuf_get_type(msgbuf) == MESSAGE_TYPE_DATA)
+ if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA)
old_path_label = msgbuf_get_pathlabel(msgbuf);
unsigned nexthop;
@@ -575,13 +564,13 @@ forwarder_forward_to_nexthops(forwarder_t * forwarder,
continue;
forwardedCopies++;
- forwarder_forward_via_connection(forwarder, msgbuf, nexthop);
+ forwarder_forward_via_connection(forwarder, msgbuf_id, nexthop);
// everytime we send out a message we need to restore the original path
// label of the message this is important because we keep a single copy
// of the message (single pointer) and we modify the path label at each
// send.
- if (msgbuf_get_type(msgbuf) == MESSAGE_TYPE_DATA)
+ if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA)
msgbuf_set_pathlabel(msgbuf, old_path_label);
});
@@ -591,12 +580,15 @@ forwarder_forward_to_nexthops(forwarder_t * forwarder,
static
bool
-forwarder_forward_via_fib(forwarder_t * forwarder, msgbuf_t *msgbuf,
+forwarder_forward_via_fib(forwarder_t * forwarder, off_t msgbuf_id,
pit_verdict_t verdict)
{
assert(forwarder);
- assert(msgbuf);
- assert(msgbuf_get_type(msgbuf) == MESSAGE_TYPE_INTEREST);
+ assert(msgbuf_id_is_valid(msgbuf_id));
+
+ const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
fib_entry_t *fib_entry = fib_match_message(forwarder->fib, msgbuf);
if (!fib_entry)
@@ -650,7 +642,7 @@ forwarder_forward_via_fib(forwarder_t * forwarder, msgbuf_t *msgbuf,
entry_Release(&entry);
#endif
- if (forwarder_forward_to_nexthops(forwarder, msgbuf, nexthops) <= 0) {
+ if (forwarder_forward_to_nexthops(forwarder, msgbuf_id, nexthops) <= 0) {
DEBUG("Message %p returned an emtpy next hop set", msgbuf);
return false;
}
@@ -661,43 +653,49 @@ forwarder_forward_via_fib(forwarder_t * forwarder, msgbuf_t *msgbuf,
static
bool
-_satisfy_from_content_store(forwarder_t * forwarder, msgbuf_t *interest_msgbuf)
+_satisfy_from_cs(forwarder_t * forwarder, off_t msgbuf_id)
{
assert(forwarder);
- assert(msgbuf_get_type(interest_msgbuf) == MESSAGE_TYPE_INTEREST);
+ assert(msgbuf_id_is_valid(msgbuf_id));
+
+ const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
- if (msgbuf_get_interest_lifetime(interest_msgbuf) == 0)
+ if (msgbuf_get_lifetime(msgbuf) == 0)
return false;
- if (!forwarder->serve_from_content_store)
+ if (!forwarder->serve_from_cs)
return false;
// See if there's a match in the store.
- msgbuf_t * data_msgbuf = content_store_match(forwarder->content_store,
- interest_msgbuf, ticks_now());
+ off_t data_msgbuf_id = cs_match(forwarder_get_cs(forwarder), msgbuf_id,
+ ticks_now());
- if (!data_msgbuf)
+ if (msgbuf_id_is_valid(data_msgbuf_id))
return false;
// Remove it from the PIT. nexthops is allocated, so need to destroy
- nexthops_t * nexthops = pit_on_data(forwarder->pit, data_msgbuf);
+ nexthops_t * nexthops = pit_on_data(forwarder->pit, data_msgbuf_id);
assert(nexthops); // Illegal state: got a null nexthops for an interest we just inserted
// send message in reply, then done
forwarder->stats.countInterestsSatisfiedFromStore++;
- DEBUG("Message %p satisfied from content store (satisfied count %u)",
- interest_msgbuf, forwarder->stats.countInterestsSatisfiedFromStore);
+ DEBUG("Message %lu satisfied from content store (satisfied count %u)",
+ msgbuf_id, forwarder->stats.countInterestsSatisfiedFromStore);
+ msgbuf_t * data_msgbuf = msgbuf_pool_at(msgbuf_pool, data_msgbuf_id);
msgbuf_reset_pathlabel(data_msgbuf);
- forwarder_forward_to_nexthops(forwarder, data_msgbuf, nexthops);
+ forwarder_forward_to_nexthops(forwarder, data_msgbuf_id, nexthops);
return true;
}
/**
- * @function forwarder_receive_interest
+ * @function forwarder_process_interest
* @abstract Receive an interest from the network
* @discussion
* (1) if interest in the PIT, aggregate in PIT
@@ -707,22 +705,34 @@ _satisfy_from_content_store(forwarder_t * forwarder, msgbuf_t *interest_msgbuf)
*
*/
static
-void
-forwarder_receive_interest(forwarder_t * forwarder, msgbuf_t * msgbuf)
+ssize_t
+forwarder_process_interest(forwarder_t * forwarder, off_t msgbuf_id)
{
assert(forwarder);
- assert(msgbuf);
- assert(msgbuf_get_type(msgbuf) == MESSAGE_TYPE_INTEREST);
+ assert(msgbuf_id_is_valid(msgbuf_id));
+
+ const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
+
+ forwarder->stats.countReceived++;
forwarder->stats.countInterestsReceived++;
+ char *nameString = name_ToString(msgbuf_get_name(msgbuf));
+ DEBUG( "Message %p ingress %3u length %5u received name %s", msgbuf,
+ msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf), nameString);
+ free(nameString);
+
+
// (1) Try to aggregate in PIT
- pit_verdict_t verdict = pit_on_interest(forwarder->pit, msgbuf);
+ pit_verdict_t verdict = pit_on_interest(forwarder->pit, msgbuf_id);
switch(verdict) {
case PIT_VERDICT_AGGREGATE:
forwarder->stats.countInterestsAggregated++;
DEBUG("Message %p aggregated in PIT (aggregated count %u)",
msgbuf, forwarder->stats.countInterestsAggregated);
- return;
+ return msgbuf_get_len(msgbuf);
case PIT_VERDICT_FORWARD:
case PIT_VERDICT_RETRANSMIT:
@@ -735,30 +745,30 @@ forwarder_receive_interest(forwarder_t * forwarder, msgbuf_t * msgbuf)
// interest, we need to remove the PIT entry.
// (2) Try to satisfy from content store
- if (_satisfy_from_content_store(forwarder, msgbuf)) {
+ if (_satisfy_from_cs(forwarder, msgbuf_id)) {
// done
// If we found a content object in the CS,
- // messageProcess_Satisfy_from_content_store already cleared the PIT state
- return;
+ // messageProcess_Satisfy_from_cs already cleared the PIT state
+ return msgbuf_get_len(msgbuf);
}
// (3) Try to forward it
- if (forwarder_forward_via_fib(forwarder, msgbuf, verdict)) {
+ if (forwarder_forward_via_fib(forwarder, msgbuf_id, verdict)) {
// done
- return;
+ return msgbuf_get_len(msgbuf);
}
// Remove the PIT entry?
forwarder->stats.countDroppedNoRoute++;
- DEBUG("Message %p did not match FIB, no route (count %u)",
- msgbuf, forwarder->stats.countDroppedNoRoute);
+ DEBUG("Message %lu did not match FIB, no route (count %u)",
+ msgbuf_id, forwarder->stats.countDroppedNoRoute);
- forwarder_drop(forwarder, msgbuf);
+ return forwarder_drop(forwarder, msgbuf_id);
}
/**
- * @function forwarder_receive_data
+ * @function forwarder_process_data
* @abstract Process an in-bound content object
* @discussion
* (1) If it does not match anything in the PIT, drop it
@@ -768,19 +778,27 @@ forwarder_receive_interest(forwarder_t * forwarder, msgbuf_t * msgbuf)
* @param <#param1#>
*/
static
-void
-forwarder_receive_data(forwarder_t * forwarder,
- msgbuf_t *msgbuf)
+ssize_t
+forwarder_process_data(forwarder_t * forwarder, off_t msgbuf_id)
{
+ const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
+ char *nameString = name_ToString(msgbuf_get_name(msgbuf));
+ DEBUG( "Message %lu ingress %3u length %5u received name %s", msgbuf_id,
+ msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf), nameString);
+ free(nameString);
+
+ forwarder->stats.countReceived++;
forwarder->stats.countObjectsReceived++;
- nexthops_t * ingressSetUnion = pit_on_data(forwarder->pit, msgbuf);
+ nexthops_t * ingressSetUnion = pit_on_data(forwarder->pit, msgbuf_id);
if (!ingressSetUnion) {
// (1) If it does not match anything in the PIT, drop it
forwarder->stats.countDroppedNoReversePath++;
- DEBUG("Message %p did not match PIT, no reverse path (count %u)",
- msgbuf, forwarder->stats.countDroppedNoReversePath);
+ DEBUG("Message %lu did not match PIT, no reverse path (count %u)",
+ msgbuf_id, forwarder->stats.countDroppedNoReversePath);
// MOVE PROBE HOOK ELSEWHERE
// XXX relationship with forwarding strategy... insert hooks
@@ -803,95 +821,68 @@ forwarder_receive_data(forwarder_t * forwarder,
const connection_table_t * table = forwarder_get_connection_table(forwarder);
const connection_t * conn = connection_table_get_by_id(table, msgbuf_get_connection_id(msgbuf));
- if (forwarder->store_in_content_store && connection_is_local(conn)) {
- content_store_add(forwarder->content_store, msgbuf, ticks_now());
+ if (forwarder->store_in_cs && connection_is_local(conn)) {
+ cs_add(forwarder->cs, msgbuf_id, ticks_now());
DEBUG("Message %p store in CS anyway", msgbuf);
}
- forwarder_drop(forwarder, msgbuf);
+ return forwarder_drop(forwarder, msgbuf_id);
} else {
// (2) Add to Content Store. Store may remove expired content, if necessary,
// depending on store policy.
- if (forwarder->store_in_content_store) {
- content_store_add(forwarder->content_store, msgbuf, ticks_now());
+ if (forwarder->store_in_cs) {
+ cs_add(forwarder->cs, msgbuf_id, ticks_now());
}
// (3) Reverse path forward via PIT entries
- forwarder_forward_to_nexthops(forwarder, msgbuf, ingressSetUnion);
+ return forwarder_forward_to_nexthops(forwarder, msgbuf_id, ingressSetUnion);
}
}
-
-/**
- * A NULL msgbuf is used to indicate the end of a batch
- */
void
-forwarder_receive(forwarder_t * forwarder, msgbuf_t * msgbuf)
+forwarder_flush_connections(forwarder_t * forwarder)
{
- assert(forwarder);
-
- /* Send batch ? */
- if (!msgbuf) {
- const connection_table_t * table = forwarder_get_connection_table(forwarder);
- for (unsigned i = 0; i < forwarder->num_pending_conn; i++) {
- const connection_t * conn = connection_table_at(table, forwarder->pending_conn[i]);
- // flush
- connection_send(conn, NULL, false);
+ const connection_table_t * table = forwarder_get_connection_table(forwarder);
+
+ for (unsigned i = 0; i < forwarder->num_pending_conn; i++) {
+ unsigned conn_id = forwarder->pending_conn[i];
+ const connection_t * conn = connection_table_at(table, conn_id);
+ if (!connection_flush(conn)) {
+ WARN("Could not flush connection queue");
+ // XXX keep track of non flushed connections...
}
- forwarder->num_pending_conn = 0;
}
+ forwarder->num_pending_conn = 0;
+}
+// XXX move to wldr file, worst case in connection.
+void
+forwarder_apply_wldr(const forwarder_t * forwarder, const msgbuf_t * msgbuf, connection_t * connection)
+{
// this are the checks needed to implement WLDR. We set wldr only on the STAs
- // and we let the AP to react according to choise of the client.
+ // and we let the AP to react according to choice of the client.
// if the STA enables wldr using the set command, the AP enable wldr as well
// otherwise, if the STA disable it the AP remove wldr
// WLDR should be enabled only on the STAs using the command line
// TODO
// disable WLDR command line on the AP
- connection_table_t * table = forwarder_get_connection_table(forwarder);
- connection_t * conn = connection_table_get_by_id(table, msgbuf_get_connection_id(msgbuf));
- if (!conn)
- return;
-
if (msgbuf_has_wldr(msgbuf)) {
- if (connection_has_wldr(conn)) {
+ if (connection_has_wldr(connection)) {
// case 1: WLDR is enabled
- connection_wldr_detect_losses(conn, msgbuf);
- } else if (!connection_has_wldr(conn) &&
- connection_wldr_autostart_is_allowed(conn)) {
+ connection_wldr_detect_losses(connection, msgbuf);
+ } else if (!connection_has_wldr(connection) &&
+ connection_wldr_autostart_is_allowed(connection)) {
// case 2: We are on an AP. We enable WLDR
- connection_wldr_enable(conn, true);
- connection_wldr_detect_losses(conn, msgbuf);
+ connection_wldr_enable(connection, true);
+ connection_wldr_detect_losses(connection, msgbuf);
}
// case 3: Ignore WLDR
} else {
- if (connection_has_wldr(conn) && connection_wldr_autostart_is_allowed(conn)) {
+ if (connection_has_wldr(connection) && connection_wldr_autostart_is_allowed(connection)) {
// case 1: STA do not use WLDR, we disable it
- connection_wldr_enable(conn, false);
+ connection_wldr_enable(connection, false);
}
}
-
- forwarder->stats.countReceived++;
-
- char *nameString = name_ToString(msgbuf_get_name(msgbuf));
- DEBUG( "Message %p ingress %3u length %5u received name %s", msgbuf,
- msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf), nameString);
- free(nameString);
-
- switch (msgbuf_get_type(msgbuf)) {
- case MESSAGE_TYPE_INTEREST:
- forwarder_receive_interest(forwarder, msgbuf);
- break;
-
- case MESSAGE_TYPE_DATA:
- forwarder_receive_data(forwarder, msgbuf);
- break;
-
- default:
- forwarder_drop(forwarder, msgbuf);
- break;
- }
-
}
bool
@@ -1006,7 +997,7 @@ forwarder_set_strategy(forwarder_t * forwarder, Name * name_prefix,
{
assert(forwarder);
assert(name_prefix);
- // assert(strategy_type_is_valid(strategy_type));
+ assert(STRATEGY_TYPE_VALID(strategy_type));
/* strategy_options might be NULL */
fib_entry_t * entry = fib_contains(forwarder->fib, name_prefix);
@@ -1016,12 +1007,12 @@ forwarder_set_strategy(forwarder_t * forwarder, Name * name_prefix,
fib_entry_set_strategy(entry, strategy_type, strategy_options);
}
-content_store_t *
-forwarder_get_content_store(const forwarder_t * forwarder)
+cs_t *
+forwarder_get_cs(const forwarder_t * forwarder)
{
assert(forwarder);
- return forwarder->content_store;
+ return forwarder->cs;
}
// =======================================================
@@ -1055,10 +1046,17 @@ static void _signal_cb(int sig, PARCEventType events, void *user_data) {
#endif
fib_t *
-forwarder_get_fib(forwarder_t * forwarder) {
+forwarder_get_fib(forwarder_t * forwarder)
+{
return forwarder->fib;
}
+msgbuf_pool_t *
+forwarder_get_msgbuf_pool(const forwarder_t * forwarder)
+{
+ return forwarder->msgbuf_pool;
+}
+
#ifdef WITH_MAPME
void
forwarder_on_connection_event(const forwarder_t * forwarder,
@@ -1082,116 +1080,120 @@ forwarder_get_prefix_stats_mgr(const forwarder_t * forwarder)
}
#endif /* WITH_PREFIX_STATS */
-static
-void
-process_interest(forwarder_t * forwarder, listener_t * listener,
- unsigned conn_id, uint8_t * packet, size_t size, const address_pair_t * pair)
-{
- if (!connection_id_is_valid(conn_id)) {
- conn_id = listener_create_connection(listener, pair);
- }
-
- assert(messageHandler_GetTotalPacketLength(packet) == size);
-
- msgbuf_from_packet(&forwarder->msgbuf, packet, size, MESSAGE_TYPE_INTEREST, conn_id, ticks_now());
- forwarder_receive(listener->forwarder, &forwarder->msgbuf);
-}
+/**
+ * @brief Process a packet by creating the corresponding message buffer and
+ * dispatching it to the forwarder for further processing.
+ * @param[in] forwarder Forwarder instance.
+ *
+ */
+// XXX ??? XXX = process for listener as we are resolving connection id
+//
-static
-void
-process_data(forwarder_t * forwarder, listener_t * listener,
- unsigned conn_id, uint8_t * packet, size_t size, const address_pair_t * pair)
+msgbuf_type_t get_type_from_packet(uint8_t * packet)
{
- if (!connection_id_is_valid(conn_id)) {
- INFO("Ignoring data packet associated to no connection");
- return;
- }
+ if (messageHandler_IsTCP(packet)) {
+ if (messageHandler_IsData(packet)) {
+ return MSGBUF_TYPE_DATA;
+ } else if (messageHandler_IsInterest(packet)) {
+ return MSGBUF_TYPE_INTEREST;
+ } else {
+ return MSGBUF_TYPE_UNDEFINED;
+ }
- assert(messageHandler_GetTotalPacketLength(packet) == size);
+ } else if (messageHandler_IsWldrNotification(packet)) {
+ return MSGBUF_TYPE_WLDR_NOTIFICATION;
- msgbuf_from_packet(&forwarder->msgbuf, packet, size, MESSAGE_TYPE_DATA, conn_id, ticks_now());
- forwarder_receive(listener->forwarder, &forwarder->msgbuf);
+ } else if (mapme_match_packet(packet)) {
+ return MSGBUF_TYPE_MAPME;
-}
+ } else if (*packet == REQUEST_LIGHT) {
+ return MSGBUF_TYPE_COMMAND;
-static
-void
-process_wldr_notification(forwarder_t * forwarder, listener_t * listener,
- unsigned conn_id, uint8_t * packet, size_t size, const address_pair_t * pair)
-{
- if (!connection_id_is_valid(conn_id)) {
- INFO("Ignoring WLDR notification not associated to a connection");
- return;
+ } else {
+ return MSGBUF_TYPE_UNDEFINED;
}
-
- assert(messageHandler_GetTotalPacketLength(packet) == size);
-
- connection_table_t * table = forwarder_get_connection_table(forwarder);
- connection_t * connection = connection_table_at(table, conn_id);
-
- msgbuf_from_packet(&forwarder->msgbuf, packet, size, MESSAGE_TYPE_WLDR_NOTIFICATION, conn_id, ticks_now());
- connection_wldr_handle_notification(connection, &forwarder->msgbuf);
-
}
-static
-void
-process_mapme(forwarder_t * forwarder, listener_t * listener,
- unsigned conn_id, uint8_t * packet, size_t size, const address_pair_t * pair)
+ssize_t
+forwarder_receive(forwarder_t * forwarder, listener_t * listener,
+ off_t msgbuf_id, address_pair_t * pair, Ticks now)
{
- if (!connection_id_is_valid(conn_id))
- conn_id = listener_create_connection(listener, pair);
- mapme_process(forwarder->mapme, packet, conn_id);
-}
+ assert(forwarder);
+ /* listener can be NULL */
+ assert(msgbuf_id_is_valid(msgbuf_id));
+ assert(pair);
-static
-void
-process_command(const forwarder_t * forwarder, listener_t * listener,
- unsigned conn_id, uint8_t * packet, size_t size, const address_pair_t * pair)
-{
- if (!connection_id_is_valid(conn_id))
- conn_id = listener_create_connection(listener, pair);
+ const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
- command_type_t command_type= *(packet + 1);
- if (command_type >= COMMAND_TYPE_N) {
- ERROR("Invalid command");
- return;
- }
- forwarder_receive_command(listener->forwarder, command_type, packet, conn_id);
+ assert(msgbuf);
-}
+ uint8_t * packet = msgbuf_get_packet(msgbuf);
+ size_t size = msgbuf_get_len(msgbuf);
+ assert(messageHandler_GetTotalPacketLength(packet) == size); // XXX confirm ?
-// = process for listener as we are resolving connection id
-// XXX this would typically be inside the forwarder
-void
-process_packet(forwarder_t * forwarder, listener_t * listener, uint8_t * packet, size_t size, address_pair_t * pair)
-{
/* Connection lookup */
const connection_table_t * table = forwarder_get_connection_table(listener->forwarder);
- const connection_t * conn = connection_table_get_by_pair(table, pair);
- unsigned conn_id = conn ? connection_table_get_connection_id(table, conn): CONNECTION_ID_UNDEFINED;
+ connection_t * connection = connection_table_get_by_pair(table, pair);
+ unsigned conn_id = connection
+ ? connection_table_get_connection_id(table, connection)
+ : CONNECTION_ID_UNDEFINED;
assert((conn_id != CONNECTION_ID_UNDEFINED) || listener);
- // Actually hooks should be defined for each packet type to avoid this
- // spaghetti code
- if (messageHandler_IsTCP(packet)) {
- if (messageHandler_IsData(packet)) {
- process_data(forwarder, listener, conn_id, packet, size, pair);
- } else if (messageHandler_IsInterest(packet)) {
- process_interest(forwarder, listener, conn_id, packet, size, pair);
- } else {
- INFO("Unknown TCP packet received");
- forwarder_drop(forwarder, NULL);
- }
- } else if (messageHandler_IsWldrNotification(packet)) {
- process_wldr_notification(forwarder, listener, conn_id, packet, size, pair);
- } else if (mapme_match_packet(packet)) {
- process_mapme(forwarder, listener, conn_id, packet, size, pair);
- } else if (*packet == REQUEST_LIGHT) {
- process_command(forwarder, listener, conn_id, packet, size, pair);
- } else {
- INFO("Unknown packet received");
- forwarder_drop(forwarder, NULL);
+ msgbuf_type_t type = get_type_from_packet(msgbuf_get_packet(msgbuf));
+
+ msgbuf->type = type;
+ msgbuf->connection_id = conn_id;
+ msgbuf->recv_ts = now;
+ msgbuf->refs = 1;
+
+ switch(type) {
+ case MSGBUF_TYPE_INTEREST:
+ if (!connection_id_is_valid(msgbuf->connection_id))
+ msgbuf->connection_id = listener_create_connection(listener, pair);
+ msgbuf->id.name = name_create_from_interest(packet);
+ forwarder_apply_wldr(forwarder, msgbuf, connection);
+ forwarder_process_interest(forwarder, msgbuf_id);
+ break;
+
+ case MSGBUF_TYPE_DATA:
+ if (!connection_id_is_valid(msgbuf->connection_id))
+ return forwarder_drop(forwarder, msgbuf_id);
+ msgbuf->id.name = name_create_from_data(packet);
+ forwarder_apply_wldr(forwarder, msgbuf, connection);
+ forwarder_process_data(forwarder, msgbuf_id);
+ break;
+
+ case MSGBUF_TYPE_WLDR_NOTIFICATION:
+ if (!connection_id_is_valid(msgbuf->connection_id))
+ return forwarder_drop(forwarder, msgbuf_id);
+ connection_wldr_handle_notification(connection, msgbuf);
+ return msgbuf_get_len(msgbuf);
+
+ case MSGBUF_TYPE_MAPME:
+ // XXX what about acks ?
+ if (!connection_id_is_valid(msgbuf->connection_id))
+ msgbuf->connection_id = listener_create_connection(listener, pair);
+ mapme_process(forwarder->mapme, msgbuf);
+ return msgbuf_get_len(msgbuf);
+
+ case MSGBUF_TYPE_COMMAND:
+ // XXX before it used to create the connection
+ if (!connection_id_is_valid(msgbuf->connection_id))
+ return forwarder_drop(forwarder, msgbuf_id);
+ msgbuf->command.type = *(packet + 1); // XXX use header
+ if (msgbuf->command.type >= COMMAND_TYPE_N) {
+ ERROR("Invalid command");
+ return -msgbuf_get_len(msgbuf);
+ }
+ return configuration_receive_command(forwarder->config, msgbuf);
+
+ case MSGBUF_TYPE_UNDEFINED:
+ case MSGBUF_TYPE_N:
+ // XXX Unexpected... shall we abort ?
+ return forwarder_drop(forwarder, msgbuf_id);
}
+
+ return size;
}
diff --git a/hicn-light/src/hicn/core/forwarder.h b/hicn-light/src/hicn/core/forwarder.h
index 5d999a319..a76e36530 100644
--- a/hicn-light/src/hicn/core/forwarder.h
+++ b/hicn-light/src/hicn/core/forwarder.h
@@ -18,8 +18,8 @@
* only be called within the forwarders thread of execution.
*/
-#ifndef forwarder_h
-#define forwarder_h
+#ifndef HICNLIGHT_FORWARDER_H
+#define HICN_LIGHT_FORWARDER_H
//#ifndef _WIN32
//#include <sys/time.h>
@@ -34,6 +34,7 @@
#include <hicn/core/connection.h>
#include <hicn/core/connection_table.h>
#include <hicn/core/listener_table.h>
+#include <hicn/core/msgbuf_pool.h>
#include <hicn/config/configuration.h>
@@ -46,27 +47,12 @@
#include <hicn/utils/commands.h>
-#define MAX_MSG 64 //16 //32
-#define MTU 1500
-
-
-typedef struct batch_buffer_s {
- /* sendmmsg / recvmmsg data structures */
- struct mmsghdr msghdr[MAX_MSG]; // XXX = {0};
- char buffers[MAX_MSG][MTU];
- struct iovec iovecs[MAX_MSG]; // XXX = {0};
- struct sockaddr_storage addrs[MAX_MSG];
-} batch_buffer_t;
-
-int init_batch_buffers(batch_buffer_t * bb);
-
// ==============================================
typedef struct forwarder_s forwarder_t;
/**
- * @function forwarder_Create
- * @abstract Create the forwarder and use the provided logger for diagnostic
+ * @brief Create the forwarder and use the provided logger for diagnostic
* output
* @discussion
* If the logger is null, hicn-light will create a STDOUT logger.
@@ -76,14 +62,12 @@ typedef struct forwarder_s forwarder_t;
forwarder_t * forwarder_create();
/**
- * @function forwarder_Destroy
- * @abstract Destroys the forwarder, stopping all traffic and freeing all memory
+ * @brief Destroys the forwarder, stopping all traffic and freeing all memory
*/
void forwarder_free(forwarder_t * forwarder);
/**
- * @function forwarder_SetupAllListeners
- * @abstract Setup all listeners (tcp, udp, local, ether, ip multicast) on all
+ * @brief Setup all listeners (tcp, udp, local, ether, ip multicast) on all
* interfaces
* @discussion
* Sets up all listeners on all running interfaces. This provides a quick and
@@ -97,8 +81,7 @@ void forwarder_free(forwarder_t * forwarder);
void forwarder_setup_all_listeners(forwarder_t * forwarder, uint16_t port, const
char *local_path);
/**
- * @function forwarder_SetupAllListeners
- * @abstract Setup one tcp and one udp listener on address 127.0.0.1 and the
+ * @brief Setup one tcp and one udp listener on address 127.0.0.1 and the
* given port
*/
void forwarder_setup_local_listeners(forwarder_t * forwarder, uint16_t port);
@@ -110,14 +93,13 @@ void forwarder_setup_local_listeners(forwarder_t * forwarder, uint16_t port);
* You need to have "add listener" lines in the file to receive connections. No
* default listeners are configured.
*
- * @param [in] forwarder An alloated forwarder_t
- * @param [in] filename The path to the configuration file
+ * @param[in] forwarder An alloated forwarder_t
+ * @param[in] filename The path to the configuration file
*/
void forwarder_read_config(forwarder_t * forwarder, const char * filename);
/**
- * @function forwarder_GetConfiguration
- * @abstract The configuration object
+ * @brief The configuration object
* @discussion
* The configuration contains all user-issued commands. It does not include
* dynamic state.
@@ -127,7 +109,7 @@ configuration_t * forwarder_get_configuration(forwarder_t * forwarder);
/**
* Returns the set of currently active listeners
*
- * @param [in] forwarder An allocated hicn-light forwarder
+ * @param[in] forwarder An allocated hicn-light forwarder
*
* @retval non-null The set of active listeners
* @retval null An error
@@ -137,7 +119,7 @@ listener_table_t * forwarder_get_listener_table(forwarder_t *forwarder);
/**
* Returns the forwrder's connection table
*
- * @param [in] forwarder An allocated hicn-light forwarder
+ * @param[in] forwarder An allocated hicn-light forwarder
*
* @retval non-null The connection tabler
* @retval null An error
@@ -145,54 +127,46 @@ listener_table_t * forwarder_get_listener_table(forwarder_t *forwarder);
*/
connection_table_t * forwarder_get_connection_table(const forwarder_t *forwarder);
-void forwarder_content_store_set_store(forwarder_t * forwarder, bool val);
+void forwarder_cs_set_store(forwarder_t * forwarder, bool val);
-bool forwarder_content_store_get_store(forwarder_t * forwarder);
+bool forwarder_cs_get_store(forwarder_t * forwarder);
-void forwarder_content_store_set_serve(forwarder_t * forwarder, bool val);
+void forwarder_cs_set_serve(forwarder_t * forwarder, bool val);
-bool forwarder_content_store_get_serve(forwarder_t * forwarder);
+bool forwarder_cs_get_serve(forwarder_t * forwarder);
/**
* Sets the maximum number of content objects in the content store
*
* Implementation dependent - may wipe the cache.
*/
-void forwarder_content_store_set_size(forwarder_t * forwarder, size_t size);
+void forwarder_cs_set_size(forwarder_t * forwarder, size_t size);
-void forwarder_content_store_clear(forwarder_t *forwarder);
+void forwarder_cs_clear(forwarder_t *forwarder);
-void forwarder_receive_command(forwarder_t * forwarder, command_type_t command_type,
- uint8_t * packet, unsigned connection_id);
-
-void forwarder_receive(forwarder_t * forwarder, msgbuf_t * message);
+ssize_t forwarder_receive_command(forwarder_t * forwarder, msgbuf_t * msgbuf);
/**
- * @function forwarder_add_or_update_route
- * @abstract Adds or updates a route on all the message processors
+ * @brief Adds or updates a route on all the message processors
*/
bool forwarder_add_or_update_route(forwarder_t * forwarder,
ip_prefix_t * prefix, unsigned ingress_id);
/**
- * @function forwarder_remove_route
- * @abstract Removes a route from all the message processors
+ * @brief Removes a route from all the message processors
*/
bool forwarder_remove_route(forwarder_t * forwarder, ip_prefix_t * prefix,
unsigned ingress_id);
#ifdef WITH_POLICY
/**
- * @function forwarder_add_or_update_policy
- * @abstract Adds or updates a policy on the message processor
+ * @brief Adds or updates a policy on the message processor
*/
bool forwarder_add_or_update_policy(forwarder_t * forwarder,
ip_prefix_t * prefix, policy_t * policy);
-
/**
- * @function forwarder_RemovePolicy
- * @abstract Removes a policy from the message processor
+ * @brief Removes a policy from the message processor
*/
bool forwarder_remove_policy(forwarder_t * forwarder, ip_prefix_t * prefix);
@@ -207,37 +181,42 @@ void forwarder_remove_connection_id_from_routes(forwarder_t * forwarder,
void forwarder_set_strategy(forwarder_t * forwarder, Name * name_prefix,
strategy_type_t strategy_type, strategy_options_t * strategy_options);
-content_store_t * forwarder_get_content_store(const forwarder_t * forwarder);
+cs_t * forwarder_get_cs(const forwarder_t * forwarder);
/**
- * @function forwarder_getFib
- * @abstract Returns the hICN forwarder's FIB.
- * @param [in] forwarder - Pointer to the hICN forwarder.
+ * @brief Returns the forwarder's FIB.
+ * @param[in] forwarder - Pointer to the forwarder.
* @returns Pointer to the hICN FIB.
*/
fib_t * forwarder_get_fib(forwarder_t * forwarder);
+/**
+ * @brief Return the forwarder packet pool.
+ * @param[in] forwarder The forwarder from which to retrieve the packet
+ * pool.
+ * @return msgbuf_pool_t * The forwarder packet pool.
+ */
+msgbuf_pool_t * forwarder_get_msgbuf_pool(const forwarder_t * forwarder);
+
#ifdef WITH_MAPME
/**
- * @function forwarder_onConnectionEvent
- * @abstract Callback fired upon addition of a new connection through the
+ * @brief Callback fired upon addition of a new connection through the
* control protocol.
- * @param [in] forwarder - Pointer to the hICN forwarder.
- * @param [in] conn - Pointer to the newly added connection.
- * @param [in] event - Connection event
+ * @param[in] forwarder - Pointer to the forwarder.
+ * @param[in] conn - Pointer to the newly added connection.
+ * @param[in] event - Connection event
*/
void forwarder_on_connection_event(const forwarder_t * forwarder,
const connection_t * connection, connection_event_t event);
/**
- * @function forwarder_ProcessMapMe
- * @abstract Callback fired by an hICN listener upon reception of a MAP-Me
+ * @brief Callback fired by an hICN listener upon reception of a MAP-Me
* message.
- * @param [in] forwarder - Pointer to the hICN forwarder.
- * @param [in] msgBuffer - MAP-Me buffer
- * @param [in] conn_id - Ingress connection id
+ * @param[in] forwarder - Pointer to the forwarder.
+ * @param[in] msgBuffer - MAP-Me buffer
+ * @param[in] conn_id - Ingress connection id
*/
void forwarder_process_mapme(const forwarder_t * forwarder, const uint8_t * packet,
unsigned conn_id);
@@ -250,7 +229,15 @@ struct mapme_s * forwarder_get_mapme(const forwarder_t * forwarder);
const prefix_stats_mgr_t * forwarder_get_prefix_stats_mgr(const forwarder_t * forwarder);
#endif /* WITH_PREFIX_STATS */
-void process_packet(forwarder_t * forwarder, listener_t * listener,
- uint8_t * packet, size_t size, address_pair_t * pair);
+void forwarder_flush_connections(forwarder_t * forwarder);
+
+/**
+ * @brief Handles a newly received packet from a listener.
+ *
+ * NOTE: the received msgbuf is incomplete and only holds the packet content and
+ * size/
+ */
+ssize_t forwarder_receive(forwarder_t * forwarder, listener_t * listener,
+ off_t msgbuf_id, address_pair_t * pair, Ticks now);
-#endif // forwarder_h
+#endif // HICN_LIGHT_FORWARDER_H
diff --git a/hicn-light/src/hicn/core/listener.c b/hicn-light/src/hicn/core/listener.c
index 5857c0c88..d24fafba0 100644
--- a/hicn-light/src/hicn/core/listener.c
+++ b/hicn-light/src/hicn/core/listener.c
@@ -19,14 +19,14 @@
*/
-
#include <string.h> // strdup
-#include <hicn/core/listener_vft.h>
-#include <hicn/base/loop.h>
-#include <hicn/core/forwarder.h>
#include <hicn/util/log.h>
-#include "listener.h"
+
+#include "forwarder.h"
+#include "listener_vft.h"
+#include "../base/loop.h"
+#include "../io/base.h"
listener_t *
listener_create(face_type_t type, const address_t * address,
@@ -89,7 +89,7 @@ listener_initialize(listener_t * listener, face_type_t type, const char * name,
// XXX data should be pre-allocated here
loop_fd_event_create(&listener->event_data, MAIN_LOOP, listener->fd, listener,
- (fd_callback_t)listener_vft[listener->type]->read_callback, NULL);
+ (fd_callback_t)listener_read_callback, NULL);
if (!listener->event_data) {
goto ERR_REGISTER_FD;
@@ -151,7 +151,8 @@ int listener_get_socket(const listener_t * listener, const address_t * local,
{
assert(listener);
assert(listener_has_valid_type(listener));
- // assert(pair);
+ assert(local);
+ assert(remote);
return listener_vft[listener->type]->get_socket(listener, local, remote,
interface_name);
@@ -201,63 +202,115 @@ listener_punt(const listener_t * listener, const char * prefix_s)
return listener_vft[listener_get_type(listener)]->punt(listener, prefix_s);
}
+
ssize_t
-listener_read_callback(forwarder_t * forwarder, listener_t * listener, int fd,
- address_t * local_addr, uint8_t * packet, size_t size)
+listener_read_single(listener_t * listener)
{
- // XXX TODO mutualize code across all listeners
- // some do not support batches
- //
- // XXX negative in case of error
- // 0 if we don't consume yet because we don't have enough
- // needed for TCP !!
- return size;
+ assert(listener);
+
+ size_t processed_size;
+ size_t total_size = 0;
+
+ msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(listener->forwarder);
+
+ for (;;) {
+
+ msgbuf_t * msgbuf = NULL;
+ off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, msgbuf);
+ if (!msgbuf_id_is_valid(msgbuf_id))
+ return 0;
+
+ address_pair_t pair;
+ pair.local = *listener_get_address(listener);
+
+ ssize_t n = listener_vft[listener->type]->read_single(listener->fd, msgbuf,
+ address_pair_get_remote(&pair));
+ if (n < 1)
+ return 0;
+
+ /* Process received packet */
+ processed_size = forwarder_receive(listener->forwarder, listener,
+ msgbuf_id, &pair, ticks_now());
+ if (processed_size <= 0)
+ break;
+
+ total_size += processed_size;
+ }
+
+ /*
+ * Even through the current listener does not allow batching, the connection
+ * on which we went packets might do batching (even without sendmmsg), and
+ * we need to inform the system that we want to proceed to sending packets.
+ */
+ forwarder_flush_connections(listener->forwarder);
+ return total_size;
+
}
-void
-listener_batch_read_callback(forwarder_t * forwarder, listener_t * listener,
- int fd, address_t * local_addr, batch_buffer_t * bb)
+ssize_t
+listener_read_batch(listener_t * listener)
{
- assert(bb);
+ assert(listener);
- // XXX potential improvement : receive in a loop while we have messages to
- // read
+ size_t processed_size;
+ size_t total_size = 0;
+
+ forwarder_t * forwarder = listener->forwarder;
+ msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ /* Receive messages in the loop as long as we manage to fill the buffers */
+ int r = 0;
+ do {
+ /* Prepare the msgbuf and address pair arrays */
+ msgbuf_t * msgbuf[MAX_MSG];
+ if (!msgbuf_pool_getn(msgbuf_pool, msgbuf, MAX_MSG))
+ break;
+
+ address_pair_t pair[MAX_MSG];
+ address_t * address_remote[MAX_MSG];
+ for (unsigned i = 0; i < MAX_MSG; i++)
+ address_remote[i] = address_pair_get_remote(&pair[i]);
+
+ ssize_t n = listener_vft[listener->type]->read_batch(listener->fd,
+ msgbuf, address_remote, MAX_MSG);
+ // XXX error check
+
+ for (unsigned i = 0; i < n; i++) {
+ processed_size = forwarder_receive(forwarder, listener,
+ msgbuf_pool_get_id(msgbuf_pool, msgbuf[i]),
+ &pair[i], ticks_now());
+ if (processed_size <= 0)
+ break;
+
+ total_size += processed_size;
+ }
- // XXX
- int r = recvmmsg(fd, bb->msghdr, MAX_MSG, 0, NULL);
- if (r == 0)
- return;
+ } while(r == MAX_MSG); /* backpressure based on queue size ? */
- if (r < 0) {
- if (errno == EINTR)
- return;
- perror("recv()");
- return;
- }
+ /*
+ * Signal to the forwarder that we reached the end of a batch and we need to
+ * flush connections out
+ */
+ forwarder_flush_connections(forwarder);
- for (int i = 0; i < r; i++) {
- struct mmsghdr *msg = &bb->msghdr[i];
- uint8_t * packet = msg->msg_hdr.msg_iov->iov_base;
- size_t size = msg->msg_hdr.msg_iovlen;
+ return total_size;
- /* BEGIN packet processing */
+}
-#ifdef __APPLE__
- // XXX explain
- msg->msg_hdr.msg_namelen = 0x00;
-#endif
+ssize_t
+listener_read_callback(listener_t * listener, int fd, void * user_data)
+{
+ // XXX make a single callback and arbitrate between read and readbatch
+ assert(listener);
+ assert(fd == listener->fd);
- /* Construct address pair used for connection lookup */
- address_pair_t pair;
- pair.local = *local_addr;
- pair.remote = *(address_t*)msg->msg_hdr.msg_name;
- // in the case of a connection, we should assert the remote
+ if (listener_vft[listener->type]->read_batch)
+ return listener_read_batch(listener);
- process_packet(forwarder, listener, packet, size, &pair);
- }
+ return listener_read_single(listener);
}
+
#if 0
void
_listener_callback(evutil_socket_t fd, short what, void * arg)
diff --git a/hicn-light/src/hicn/core/listener.h b/hicn-light/src/hicn/core/listener.h
index ea2a5d3d8..eb1ec6893 100644
--- a/hicn-light/src/hicn/core/listener.h
+++ b/hicn-light/src/hicn/core/listener.h
@@ -23,10 +23,11 @@
#include <hicn/core/address_pair.h>
#include <hicn/face.h>
-#include <hicn/base/loop.h>
+
+#include "msgbuf.h"
+#include "../base/loop.h"
struct forwarder_s;
-struct batch_buffer_s;
typedef struct {
address_t address;
@@ -89,11 +90,21 @@ void listener_setup_local_ipv4(const struct forwarder_s * forwarder, uint16_t p
void listener_process_packet(const listener_t * listener,
const uint8_t * packet, size_t size);
-ssize_t listener_read_callback(struct forwarder_s * forwarder, listener_t * listener,
- int fd, address_t * local_addr, uint8_t * packet, size_t size);
-void listener_batch_read_callback(struct forwarder_s * forwarder,
- listener_t * listener, int fd, address_t * local_addr,
- struct batch_buffer_s * bb);
+ssize_t listener_read_single(listener_t * listener);
+ssize_t listener_read_batch(listener_t * listener);
+
+/**
+ * @brief Callback helper function for batch reading data from listener fd.
+ *
+ * This function is usually called from the listener read callback to proceed to
+ * actual reading of data from the fd.
+ *
+ * @see listener_read_callback
+ *
+ * NOTE: the function returns size_t as for TCP we might need to know how much
+ * data we can consume from the socket.
+ */
+ssize_t listener_read_callback(listener_t * listener, int fd, void * user_data);
#endif /* HICNLIGHT_LISTENER_H */
diff --git a/hicn-light/src/hicn/core/listener_table.c b/hicn-light/src/hicn/core/listener_table.c
index f69ad7535..9750fbbe8 100644
--- a/hicn-light/src/hicn/core/listener_table.c
+++ b/hicn-light/src/hicn/core/listener_table.c
@@ -46,7 +46,7 @@ _listener_table_create(size_t init_size, size_t max_size)
* We start by allocating a reasonably-sized pool, as this will eventually
* be resized if needed.
*/
- pool_init(table->listeners, init_size);
+ pool_init(table->listeners, init_size, 0);
return table;
}
diff --git a/hicn-light/src/hicn/core/listener_vft.h b/hicn-light/src/hicn/core/listener_vft.h
index 2f70dd67d..6440475e7 100644
--- a/hicn-light/src/hicn/core/listener_vft.h
+++ b/hicn-light/src/hicn/core/listener_vft.h
@@ -36,7 +36,9 @@ typedef struct {
msgbuf_t * msgbuf, bool queue);
int (*send_packet)(const connection_t * connection,
const uint8_t * packet, size_t size);
- void (*read_callback)(listener_t * listener, int fd, void * data);
+ ssize_t (*read_single)(int fd, msgbuf_t * msgbuf, address_t * address);
+ ssize_t (*read_batch)(int fd, msgbuf_t ** msgbuf, address_t ** address,
+ size_t len);
size_t data_size;
} listener_ops_t;
@@ -46,7 +48,8 @@ const listener_ops_t listener_ ## NAME = { \
.finalize = listener_ ## NAME ## _finalize, \
.punt = listener_ ## NAME ## _punt, \
.get_socket = listener_ ## NAME ## _get_socket, \
- .read_callback = listener_ ## NAME ## _read_callback, \
+ .read_single = listener_ ## NAME ## _read_single, \
+ .read_batch = listener_ ## NAME ## _read_batch, \
.data_size = sizeof(listener_ ## NAME ## _data_t), \
}
diff --git a/hicn-light/src/hicn/core/mapme.c b/hicn-light/src/hicn/core/mapme.c
index ae4a29f13..8f40cb34a 100644
--- a/hicn-light/src/hicn/core/mapme.c
+++ b/hicn-light/src/hicn/core/mapme.c
@@ -120,7 +120,6 @@
#include <hicn/core/connection.h>
#include <hicn/core/forwarder.h>
#include <hicn/core/msgbuf.h>
-#include <hicn/core/messagePacketType.h> // packet types
#include <hicn/core/ticks.h>
#include <hicn/core/fib_entry.h>
#include <hicn/core/pit.h>
@@ -757,7 +756,7 @@ mapme_on_interest(mapme_t * mapme, uint8_t * packet,
ERROR("Failed to send ACK packet");
}
- Name *name = name_CreateFromPacket(packet, MESSAGE_TYPE_INTEREST);
+ Name *name = name_create_from_interest(packet);
name_setLen(name, prefix->len);
char *name_str = name_ToString(name);
@@ -871,8 +870,7 @@ mapme_on_data(mapme_t *mapme, const uint8_t * packet,
{
INFO("Receive IU/IN Ack on connection %d", ingress_id);
- const Name * name =
- name_CreateFromPacket(packet, MESSAGE_TYPE_DATA);
+ const Name * name = name_create_from_data(packet);
name_setLen((Name*) name, prefix->len);
char * name_str = name_ToString(name);
@@ -919,10 +917,14 @@ mapme_on_data(mapme_t *mapme, const uint8_t * packet,
* processed by MAP-Me core.
*/
void
-mapme_process(mapme_t *mapme, uint8_t *packet, unsigned conn_id)
+mapme_process(mapme_t *mapme, msgbuf_t * msgbuf)
{
hicn_prefix_t prefix;
mapme_params_t params;
+
+ uint8_t * packet = msgbuf_get_packet(msgbuf);
+ unsigned conn_id = msgbuf_get_connection_id(msgbuf);
+
int rc = hicn_mapme_parse_packet(packet, &prefix, &params);
if (rc < 0)
return;
diff --git a/hicn-light/src/hicn/core/mapme.h b/hicn-light/src/hicn/core/mapme.h
index 2bf5a413b..d1d21079f 100644
--- a/hicn-light/src/hicn/core/mapme.h
+++ b/hicn-light/src/hicn/core/mapme.h
@@ -27,9 +27,11 @@
#include <stdint.h>
#include <hicn/hicn.h>
-#include <hicn/core/connection.h>
-#include <hicn/utils/commands.h>
-#include <hicn/core/fib_entry.h>
+
+#include "connection.h"
+#include "fib_entry.h"
+#include "msgbuf.h"
+#include "../utils/commands.h"
typedef struct mapme_s mapme_t;
@@ -64,7 +66,7 @@ bool mapme_match_packet(const uint8_t *msgBuffer);
* @param [in] message - MAP-Me buffer
* @param [in] conn_id - Ingress connection id
*/
-void mapme_process(mapme_t *mapme, uint8_t * packet, unsigned conn_id);
+void mapme_process(mapme_t *mapme, msgbuf_t * msgbuf);
int mapme_send_to_nexthop(const mapme_t * mapme, fib_entry_t * fib_entry, unsigned nexthop);
@@ -117,10 +119,6 @@ void mapme_on_connection_event(const mapme_t *mapme, const connection_t * conn,
nexthops_t * mapme_get_nexthops(const mapme_t *mapme, fib_entry_t *fib_entry,
const msgbuf_t *interest);
-hicn_mapme_type_t mapme_PktType_To_LibHicnPktType(MessagePacketType type);
-
-MessagePacketType mapme_LibHicnPktType_To_PktType(hicn_mapme_type_t type);
-
#endif /* WITH_MAPME */
#endif // mapme_h
diff --git a/hicn-light/src/hicn/core/messageHandler.h b/hicn-light/src/hicn/core/messageHandler.h
index e0eef5e7c..bc7ecf597 100644
--- a/hicn-light/src/hicn/core/messageHandler.h
+++ b/hicn-light/src/hicn/core/messageHandler.h
@@ -13,8 +13,8 @@
* limitations under the License.
*/
-#ifndef messageHandler
-#define messageHandler
+#ifndef HICNLIGHT_MESSAGE_HANDLER_H
+#define HICNLIGHT_MESSAGE_HANDLER_H
#include <stdlib.h>
#ifndef _WIN32
@@ -22,7 +22,6 @@
#endif /* _WIN32 */
#include <hicn/hicn.h>
-#include <hicn/core/messagePacketType.h>
//#include <hicn/core/connection_table.h>
@@ -620,4 +619,4 @@ static inline bool messageHandler_IsAProbe(const uint8_t *packet){
return false;
}
-#endif // Metis_metis_MessageHandler
+#endif /* HICNLIGHT_MESSAGE_HANDLER_H */
diff --git a/hicn-light/src/hicn/core/msgbuf.h b/hicn-light/src/hicn/core/msgbuf.h
index 3e96b3bbc..72480b535 100644
--- a/hicn-light/src/hicn/core/msgbuf.h
+++ b/hicn-light/src/hicn/core/msgbuf.h
@@ -18,63 +18,83 @@
* \brief hICN message buffer
*/
-#ifndef HICN_MSGBUF
-#define HICN_MSGBUF
+#ifndef HICNLIGHT_MSGBUF
+#define HICNLIGHT_MSGBUF
-#include <hicn/core/name.h>
-#include <hicn/core/ticks.h>
-#include <hicn/core/messageHandler.h>
+#include "name.h"
+#include "ticks.h"
+#include "messageHandler.h"
+#include "../utils/commands.h"
+
+struct name_s;
+
+#define MTU 1500
+#define INVALID_MSGBUF_ID ~0ul
+
+#define msgbuf_id_is_valid(msgbuf_id) (msgbuf_id != INVALID_MSGBUF_ID)
+
+#define foreach_type \
+ _(UNDEFINED) \
+ _(INTEREST) \
+ _(DATA) \
+ _(WLDR_NOTIFICATION) \
+ _(MAPME) \
+ _(COMMAND) \
+ _(N)
+
+typedef enum {
+#define _(x) MSGBUF_TYPE_ ## x,
+ foreach_type
+#undef _
+} msgbuf_type_t;
typedef struct {
- Ticks receiveTime;
- unsigned connection_id;
- Name *name;
- uint8_t *messageHead;
unsigned length;
- uint8_t packetType;
+ msgbuf_type_t type;
+ unsigned connection_id;
+ Ticks recv_ts;
+ unsigned refs;
+ union {
+ /* Interest or data packet */
+ struct {
+ struct name_s * name;
+ } id;
+ /* Command packet */
+ struct {
+ command_type_t type;
+ } command;
+ };
+ uint8_t packet[MTU];
} msgbuf_t;
-#define msgbuf_from_packet(MSGBUF, PACKET, LENGTH, TYPE, CONNID, RECV_TIME) \
-do { \
- *MSGBUF = (msgbuf_t) { \
- .receiveTime = (RECV_TIME), \
- .connection_id = (CONNID), \
- .messageHead = (PACKET), \
- .length = (LENGTH), \
- .packetType = (TYPE), \
- .name = (TYPE != MESSAGE_TYPE_WLDR_NOTIFICATION \
- ? name_CreateFromPacket((PACKET), (TYPE)) \
- : NULL), \
- }; \
-} while(0)
-
-#define msgbuf_get_name(M) ((M)->name)
+#define msgbuf_get_name(M) ((M)->id.name)
#define msgbuf_get_connection_id(M) ((M)->connection_id)
-#define msgbuf_get_type(M) ((M)->packetType)
-#define msgbuf_has_wldr(M) (messageHandler_HasWldr((M)->messageHead))
+#define msgbuf_get_type(M) ((M)->type)
+#define msgbuf_has_wldr(M) (messageHandler_HasWldr((M)->packet))
#define msgbuf_get_len(M) ((M)->length)
-#define msgbuf_get_packet(M) ((M)->messageHead)
+#define msgbuf_get_packet(M) ((M)->packet)
+#define msgbuf_get_command_type(M) ((M)->command.type) \
// XXX TODO EXPLAIN THE CONSTANT
-#define msgbuf_get_interest_lifetime(M) (NSEC_TO_TICKS(messageHandler_GetInterestLifetime((M)->messageHead) * 1000000ULL))
+#define msgbuf_get_lifetime(M) (NSEC_TO_TICKS(messageHandler_GetInterestLifetime((M)->packet) * 1000000ULL))
-#define msgbuf_is_probe(M) messageHandler_IsAProbe((M)->messageHead)
+#define msgbuf_is_probe(M) messageHandler_IsAProbe((M)->packet)
/* Path label */
-#define msgbuf_get_pathlabel(M) (messageHandler_GetPathLabel((M)->messageHead))
-#define msgbuf_set_pathlabel(M, label) (messageHandler_SetPathLabel((M)->messageHead, label))
-#define msgbuf_update_pathlabel(M, outface) (messageHandler_SetPathLabel((M)->messageHead, outface))
-#define msgbuf_reset_pathlabel(M) (messageHandler_ResetPathLabel((M)->messageHead))
+#define msgbuf_get_pathlabel(M) (messageHandler_GetPathLabel((M)->packet))
+#define msgbuf_set_pathlabel(M, label) (messageHandler_SetPathLabel((M)->packet, label))
+#define msgbuf_update_pathlabel(M, outface) (messageHandler_SetPathLabel((M)->packet, outface))
+#define msgbuf_reset_pathlabel(M) (messageHandler_ResetPathLabel((M)->packet))
/* WLDR */
-#define msgbuf_reset_wldr_label(M) (messageHandler_ResetWldrLabel((M)->messageHead))
-#define msgbuf_get_wldr_label(M) (messageHandler_GetWldrLabel((M)->messageHead))
-#define msgbuf_get_wldr_expected_label(M) (messageHandler_GetWldrExpectedLabel((M)->messageHead))
-#define msgbuf_get_wldr_last_received(M) (messageHandler_GetWldrLastReceived((M)->messageHead))
-#define msgbuf_set_wldr_label(M, label) (messageHandler_GetWldrLabel((M)->messageHead, label))
+#define msgbuf_reset_wldr_label(M) (messageHandler_ResetWldrLabel((M)->packet))
+#define msgbuf_get_wldr_label(M) (messageHandler_GetWldrLabel((M)->packet))
+#define msgbuf_get_wldr_expected_label(M) (messageHandler_GetWldrExpectedLabel((M)->packet))
+#define msgbuf_get_wldr_last_received(M) (messageHandler_GetWldrLastReceived((M)->packet))
+#define msgbuf_set_wldr_label(M, label) (messageHandler_GetWldrLabel((M)->packet, label))
-#endif /* HICN_MSGBUF */
+#endif /* HICNLIGHT_MSGBUF */
diff --git a/hicn-light/src/hicn/core/msgbuf_pool.c b/hicn-light/src/hicn/core/msgbuf_pool.c
new file mode 100644
index 000000000..597123a7a
--- /dev/null
+++ b/hicn-light/src/hicn/core/msgbuf_pool.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file msgbuf_pool.c
+ * @brief Implementation of hICN packet pool.
+ */
+
+#include "../base/pool.h"
+#include "msgbuf_pool.h"
+
+#define PACKET_POOL_DEFAULT_INIT_SIZE 1024
+
+msgbuf_pool_t *
+_msgbuf_pool_create(size_t init_size, size_t max_size)
+{
+ msgbuf_pool_t * msgbuf_pool = malloc(sizeof(msgbuf_pool_t));
+
+ if (init_size == 0)
+ init_size = PACKET_POOL_DEFAULT_INIT_SIZE;
+
+ pool_init(msgbuf_pool->buffers, init_size, 0);
+
+ return msgbuf_pool;
+}
+
+void
+msgbuf_pool_free(msgbuf_pool_t * msgbuf_pool)
+{
+ pool_free(msgbuf_pool->buffers);
+ free(msgbuf_pool);
+}
+
+int
+msgbuf_pool_get(msgbuf_pool_t * msgbuf_pool, msgbuf_t * msgbuf)
+{
+ pool_get(msgbuf_pool->buffers, msgbuf);
+ return 0;
+}
+
+void
+msgbuf_pool_put(msgbuf_pool_t * msgbuf_pool, msgbuf_t * msgbuf)
+{
+ pool_put(msgbuf_pool->buffers, msgbuf);
+}
+
+int
+msgbuf_pool_getn(msgbuf_pool_t * msgbuf_pool, msgbuf_t ** msgbuf, size_t n)
+{
+ for (unsigned i = 0; i < n; i++) {
+ if (!msgbuf_pool_get(msgbuf_pool, msgbuf[i])) {
+ for (unsigned j = 0; j < i; j++) {
+ msgbuf_pool_put(msgbuf_pool, msgbuf[j]);
+ return 0;
+ }
+ break;
+ }
+ }
+ return -1;
+}
+
+off_t
+msgbuf_pool_get_id(msgbuf_pool_t * msgbuf_pool, msgbuf_t * msgbuf)
+{
+ return msgbuf - msgbuf_pool->buffers;
+}
+
+msgbuf_t *
+msgbuf_pool_at(const msgbuf_pool_t * msgbuf_pool, off_t id)
+{
+ return msgbuf_pool->buffers + id;
+}
diff --git a/hicn-light/src/hicn/core/msgbuf_pool.h b/hicn-light/src/hicn/core/msgbuf_pool.h
new file mode 100644
index 000000000..2ada9fa14
--- /dev/null
+++ b/hicn-light/src/hicn/core/msgbuf_pool.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file msgbuf_pool.h
+ * @brief hICN msgbuf pool.
+ *
+ * THe msgbuf pool is used to store packet payloads while the packets are in
+ * transit, as well as holding them into the packet cache (PIT, CSS), WLDR,
+ * mapme, etc.
+ *
+ * Control packets might receive a special treatment in that they are eventually
+ * transformed into a ack/nack, but this should not affect any part of this
+ * design.
+ *
+ * Do we need a reference count, or simply a lock ?
+ * What about weak references ?
+ * We need to be sure that a pool element is never referenced ever again after
+ * it is deleted from the pool as its ID might be reaffected.
+ *
+ * It might even be better to store references to msgbuf's as they might hold
+ * additional information of interest about the packet... a bit like a skbuff in
+ * linux. Is this relevant for the packet cache ?
+ */
+
+#ifndef HICNLIGHT_MSGBUF_POOL_H
+#define HICNLIGHT_MSGBUF_POOL_H
+
+#include "msgbuf.h"
+
+#define MTU 1500
+
+typedef struct {
+ msgbuf_t * buffers;
+} msgbuf_pool_t;
+
+// 0 for init size means a default value (of 1024)
+// 0 for max_size means no limit
+msgbuf_pool_t * _msgbuf_pool_create(size_t init_size, size_t max_size);
+
+#define msgbuf_pool_create() _msgbuf_pool_create(0, 0)
+
+void msgbuf_pool_free(msgbuf_pool_t * msgbuf_pool);
+
+int msgbuf_pool_get(msgbuf_pool_t * msgbuf_pool, msgbuf_t * msgbuf);
+
+int msgbuf_pool_getn(msgbuf_pool_t * msgbuf_pool, msgbuf_t ** msgbuf, size_t n);
+
+off_t msgbuf_pool_get_id(msgbuf_pool_t * msgbuf_pool, msgbuf_t * msgbuf);
+
+msgbuf_t * msgbuf_pool_at(const msgbuf_pool_t * msgbuf_pool, off_t id);
+
+#endif /* HICNLIGHT_MSGBUF_POOL_H */
diff --git a/hicn-light/src/hicn/core/name.c b/hicn-light/src/hicn/core/name.c
index d50ce4cc2..1b606d3c1 100644
--- a/hicn-light/src/hicn/core/name.c
+++ b/hicn-light/src/hicn/core/name.c
@@ -30,7 +30,9 @@
// assumption: the IPv6 address is the name, the TCP segment number is the ICN
// segment
-struct name {
+// XXX leverage libhicn more here
+
+struct name_s {
NameBitvector *content_name;
uint32_t segment;
uint32_t name_hash;
@@ -71,33 +73,44 @@ static uint32_t _computeHash(Name *name) {
// ============================================================================
Name *
-name_CreateFromPacket(const uint8_t *packet, MessagePacketType type)
+name_create_from_interest(const uint8_t * packet)
{
Name *name = malloc(sizeof(Name));
assert(name); // XXX TODO error handling
if (messageHandler_GetIPPacketType(packet) == IPv6_TYPE) {
- if (type == MESSAGE_TYPE_INTEREST) {
- name->content_name = nameBitvector_CreateFromIn6Addr(
- (struct in6_addr *)messageHandler_GetDestination(packet), 128);
- } else if (type == MESSAGE_TYPE_DATA) {
- name->content_name = nameBitvector_CreateFromIn6Addr(
- (struct in6_addr *)messageHandler_GetSource(packet), 128);
- } else {
- free(name);
- return NULL;
- }
+ name->content_name = nameBitvector_CreateFromIn6Addr( (struct in6_addr
+ *)messageHandler_GetDestination(packet), 128);
} else if (messageHandler_GetIPPacketType(packet) == IPv4_TYPE) {
- if (type == MESSAGE_TYPE_INTEREST) {
- name->content_name = nameBitvector_CreateFromInAddr(
- *((uint32_t *)messageHandler_GetDestination(packet)), 32);
- } else if (type == MESSAGE_TYPE_DATA) {
- name->content_name = nameBitvector_CreateFromInAddr(
- *((uint32_t *)messageHandler_GetSource(packet)), 32);
- } else {
- free(name);
- return NULL;
- }
+ name->content_name = nameBitvector_CreateFromInAddr( *((uint32_t
+ *)messageHandler_GetDestination(packet)), 32);
+ } else {
+ printf("Error: unknown message type\n");
+ free(name);
+ return NULL;
+ }
+
+ name->segment = messageHandler_GetSegment(packet);
+ name->name_hash = _computeHash(name);
+
+ name->refCountPtr = malloc(sizeof(unsigned));
+ assert(name->refCountPtr); // XXX TODO error handling
+ *name->refCountPtr = 1;
+ return name;
+}
+
+Name *
+name_create_from_data(const uint8_t * packet)
+{
+ Name *name = malloc(sizeof(Name));
+ assert(name); // XXX TODO error handling
+
+ if (messageHandler_GetIPPacketType(packet) == IPv6_TYPE) {
+ name->content_name = nameBitvector_CreateFromIn6Addr( (struct in6_addr
+ *)messageHandler_GetSource(packet), 128);
+ } else if (messageHandler_GetIPPacketType(packet) == IPv4_TYPE) {
+ name->content_name = nameBitvector_CreateFromInAddr( *((uint32_t
+ *)messageHandler_GetSource(packet)), 32);
} else {
printf("Error: unknown message type\n");
free(name);
diff --git a/hicn-light/src/hicn/core/name.h b/hicn-light/src/hicn/core/name.h
index f3b3f2a02..ef725c00f 100644
--- a/hicn-light/src/hicn/core/name.h
+++ b/hicn-light/src/hicn/core/name.h
@@ -19,20 +19,20 @@
#include <stdbool.h>
#include <stdlib.h>
-#include <hicn/core/messagePacketType.h>
-#include <hicn/core/nameBitvector.h>
+#include "nameBitvector.h"
//#include <hicn/utils/address.h>
//#include <hicn/utils/commands.h>
-struct name;
-typedef struct name Name;
+struct name_s;
+typedef struct name_s Name;
/**
* Creates a name from packet
*
*/
-Name *name_CreateFromPacket(const uint8_t *memory, MessagePacketType type);
+Name *name_create_from_interest(const uint8_t * packet);
+Name *name_create_from_data(const uint8_t * packet);
/**
* Releases one reference count, and frees memory after last reference
diff --git a/hicn-light/src/hicn/core/nexthops.h b/hicn-light/src/hicn/core/nexthops.h
index b45ae360f..8e4878b45 100644
--- a/hicn-light/src/hicn/core/nexthops.h
+++ b/hicn-light/src/hicn/core/nexthops.h
@@ -18,11 +18,12 @@
* \brief Nexthops
*/
-#ifndef HICN_NEXTHOPS_H
-#define HICN_NEXTHOPS_H
+#ifndef HICNLIGHT_NEXTHOPS_H
+#define HICNLIGHT_NEXTHOPS_H
#include <stdint.h>
#include <stdbool.h>
+#include <stdlib.h>
#include <hicn/core/strategy.h>
@@ -151,4 +152,4 @@ nexthops_contains(nexthops_t * nexthops, unsigned nexthop)
#define nexthops_select(nexthops, i) ((nexthops)->flags = 1 << (i))
#define nexthops_select_one(nexthops) (nexthops_select((nexthops), 0))
-#endif /* HICN_NEXTHOPS_H */
+#endif /* HICNLIGHT_NEXTHOPS_H */
diff --git a/hicn-light/src/hicn/core/pit.c b/hicn-light/src/hicn/core/pit.c
index fa54e2429..e80d895ec 100644
--- a/hicn-light/src/hicn/core/pit.c
+++ b/hicn-light/src/hicn/core/pit.c
@@ -31,43 +31,56 @@
#include <assert.h>
#include <stdio.h>
+#include <stdlib.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
-#include <hicn/core/msgbuf.h>
-#include <hicn/base/pool.h>
-#include <hicn/core/ticks.h>
#include <hicn/util/log.h>
+#include "msgbuf.h"
+#include "msgbuf_pool.h"
+#include "ticks.h"
+#include "../base/pool.h"
+
#include "pit.h"
// XXX TODO Should not be defined here
#define DEFAULT_INTEREST_LIFETIME 4000000000ULL
-static Ticks _pit_calculate_lifetime(pit_t * pit,
- msgbuf_t *interest_msgbuf) {
- uint64_t interestLifetimeTicks =
- msgbuf_get_interest_lifetime(interest_msgbuf);
- if (interestLifetimeTicks == 0) {
- interestLifetimeTicks = NSEC_TO_TICKS(DEFAULT_INTEREST_LIFETIME);
- }
+static
+Ticks
+_pit_calculate_lifetime(pit_t * pit, const msgbuf_t * msgbuf)
+{
+ uint64_t lifetime = msgbuf_get_lifetime(msgbuf);
+ if (lifetime == 0)
+ lifetime = NSEC_TO_TICKS(DEFAULT_INTEREST_LIFETIME);
- Ticks expiry_time = ticks_now() + interestLifetimeTicks;
- return expiry_time;
+ return ticks_now() + lifetime;
}
-// max_elts default is 65535
+/* This is only used as a hint for first allocation, as the table is resizeable */
+#define DEFAULT_PIT_SIZE 65535
+
pit_t *
-pit_create(size_t max_elts)
+_pit_create(size_t init_size, size_t max_size)
{
pit_t * pit = malloc(sizeof(pit_t));
if (!pit)
return NULL;
- pool_init(pit->entries, max_elts);
+ if (init_size == 0)
+ init_size = DEFAULT_PIT_SIZE;
+
+ pit->max_size = max_size;
+
+ /* Initialize indices */
pit->index_by_name = kh_init(pit_name);
- DEBUG("PIT %p created", pit);
+ /*
+ * We start by allocating a reasonably-sized pool, as this will eventually
+ * be resized if needed.
+ */
+ pool_init(pit->entries, init_size, 0);
return pit;
}
@@ -76,53 +89,57 @@ void
pit_free(pit_t * pit)
{
assert(pit);
- // XXX TODO
+
+ free(pit);
DEBUG("PIT %p destroyed", pit);
}
pit_verdict_t
-pit_on_interest(pit_t * pit, msgbuf_t * interest_msgbuf)
+pit_on_interest(pit_t * pit, off_t msgbuf_id)
{
assert(pit);
- assert(interest_msgbuf);
- assert(msgbuf_get_type(interest_msgbuf) == MESSAGE_TYPE_INTEREST);
+ assert(msgbuf_id_is_valid(msgbuf_id));
+
+ const msgbuf_pool_t * msgbuf_pool = pit_get_msgbuf_pool(pit);
+ const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
fib_entry_t * fib_entry;
- Ticks expiry_time;
+ Ticks expire_ts;
/* Lookup entry by name */
- khiter_t k = kh_get_pit_name(pit->index_by_name, msgbuf_get_name(interest_msgbuf));
+ khiter_t k = kh_get_pit_name(pit->index_by_name, msgbuf_get_name(msgbuf));
if (k == kh_end(pit->index_by_name))
goto NOT_FOUND;
pit_entry_t * entry = pit->entries + kh_val(pit->index_by_name, k);
assert(entry);
// has it expired?
- if (ticks_now() >= pit_entry_get_expiry_time(entry))
+ if (ticks_now() >= pit_entry_get_expire_ts(entry))
goto TIMEOUT;
/* Extend entry lifetime */
- expiry_time = _pit_calculate_lifetime(pit, interest_msgbuf);
- if (expiry_time > pit_entry_get_expiry_time(entry))
- pit_entry_set_expiry_time(entry, expiry_time);
+ expire_ts = _pit_calculate_lifetime(pit, msgbuf);
+ if (expire_ts > pit_entry_get_expire_ts(entry))
+ pit_entry_set_expire_ts(entry, expire_ts);
- unsigned connection_id = msgbuf_get_connection_id(interest_msgbuf);
+ unsigned connection_id = msgbuf_get_connection_id(msgbuf);
// Is the reverse path already in the PIT entry?
if (pit_entry_ingress_contains(entry, connection_id)) {
// It is already in the PIT entry, so this is a retransmission, so
// forward it.
- DEBUG("Message %p existing entry (expiry %" PRIu64 ") and reverse path, forwarding",
- interest_msgbuf, pit_entry_get_expiry_time(entry));
+ DEBUG("Message %lu existing entry (expiry %" PRIu64 ") and reverse path, forwarding",
+ msgbuf_id, pit_entry_get_expire_ts(entry));
return PIT_VERDICT_RETRANSMIT;
}
// It is in the PIT but this is the first interest for the reverse path
pit_entry_ingress_add(entry, connection_id);
- DEBUG("Message %p existing entry (expiry %" PRIu64 ") and reverse path is new, aggregate",
- interest_msgbuf, pit_entry_get_expiry_time(entry));
+ DEBUG("Message %lu existing entry (expiry %" PRIu64 ") and reverse path is new, aggregate",
+ msgbuf_id, pit_entry_get_expire_ts(entry));
return PIT_VERDICT_AGGREGATE;
TIMEOUT:
@@ -131,36 +148,46 @@ TIMEOUT:
fib_entry_on_timeout(fib_entry, pit_entry_get_egress(entry));
// it's an old entry, remove it
- k = kh_get(pit_name, pit->index_by_name, msgbuf_get_name(interest_msgbuf));
+ k = kh_get(pit_name, pit->index_by_name, msgbuf_get_name(msgbuf));
if (k != kh_end(pit->index_by_name))
kh_del(pit_name, pit->index_by_name, k);
NOT_FOUND:
/* Create PIT entry */
- expiry_time = _pit_calculate_lifetime(pit, interest_msgbuf);
+ expire_ts = _pit_calculate_lifetime(pit, msgbuf);
- pit_allocate(pit, entry, interest_msgbuf);
- pit_entry_from_msgbuf(entry, interest_msgbuf, expiry_time, ticks_now());
+ pit_allocate(pit, entry, msgbuf);
- DEBUG("Message %p added to PIT (expiry %" PRIu64 ") ingress %u",
- interest_msgbuf, pit_entry_get_expiry_time(entry),
- msgbuf_get_connection_id(interest_msgbuf));
+ *entry = (pit_entry_t) {
+ .msgbuf_id = msgbuf_id,
+ .fib_entry = NULL,
+ .create_ts = ticks_now(),
+ .expire_ts = expire_ts,
+ };
+ pit_entry_ingress_add(entry, msgbuf_get_connection_id(msgbuf));
+
+ DEBUG("Message %lu added to PIT (expiry %" PRIu64 ") ingress %u",
+ msgbuf_id, pit_entry_get_expire_ts(entry),
+ msgbuf_get_connection_id(msgbuf));
return PIT_VERDICT_FORWARD;
}
nexthops_t *
-pit_on_data(pit_t * pit, const msgbuf_t * data_msgbuf)
+pit_on_data(pit_t * pit, off_t msgbuf_id)
{
assert(pit);
- assert(data_msgbuf);
- assert(msgbuf_get_type(data_msgbuf) == MESSAGE_TYPE_DATA);
+ assert(msgbuf_id_is_valid(msgbuf_id));
+
+ const msgbuf_pool_t * msgbuf_pool = pit_get_msgbuf_pool(pit);
+ const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA);
nexthops_t * nexthops = NULL;
/* Lookup entry by name */
- khiter_t k = kh_get_pit_name(pit->index_by_name, msgbuf_get_name(data_msgbuf));
+ khiter_t k = kh_get_pit_name(pit->index_by_name, msgbuf_get_name(msgbuf));
if (k == kh_end(pit->index_by_name))
goto NOT_FOUND;
@@ -170,14 +197,14 @@ pit_on_data(pit_t * pit, const msgbuf_t * data_msgbuf)
// here we need to check if the PIT entry is expired
// if so, remove the PIT entry.
Ticks now = ticks_now();
- if (now >= pit_entry_get_expiry_time(entry))
+ if (now >= pit_entry_get_expire_ts(entry))
goto TIMEOUT;
/* PIT entry is not expired, use it */
fib_entry_t * fib_entry = pit_entry_get_fib_entry(entry);
if (fib_entry)
fib_entry_on_data(fib_entry, pit_entry_get_egress(entry),
- data_msgbuf, pit_entry_get_creation_time(entry), ticks_now());
+ msgbuf, pit_entry_get_create_ts(entry), ticks_now());
// XXX TODO : be sure nexthops are valid b/c pit entry is removed
// XXX TODO eventually pass holding structure as parameter
@@ -192,20 +219,25 @@ NOT_FOUND:
}
void
-pit_remove(pit_t * pit, const msgbuf_t * interest_msgbuf)
+pit_remove(pit_t * pit, off_t msgbuf_id)
{
assert(pit);
- assert(interest_msgbuf);
- assert(msgbuf_get_type(interest_msgbuf) == MESSAGE_TYPE_INTEREST);
+ assert(msgbuf_id_is_valid(msgbuf_id));
+
+ const msgbuf_pool_t * msgbuf_pool = pit_get_msgbuf_pool(pit);
+ const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
+ assert(msgbuf);
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
- khiter_t k = kh_get(pit_name, pit->index_by_name, msgbuf_get_name(interest_msgbuf));
+ khiter_t k = kh_get(pit_name, pit->index_by_name, msgbuf_get_name(msgbuf));
if (k == kh_end(pit->index_by_name))
return;
//off_t index = kh_val(pit->index_by_name, k);
//pit_entry_t * entry = pit_at(pit, index);
kh_del(pit_name, pit->index_by_name, k);
- DEBUG("Message %p removed from PIT", interest_msgbuf);
+ DEBUG("Message %p removed from PIT", msgbuf);
}
pit_entry_t *
@@ -213,7 +245,7 @@ pit_lookup(const pit_t * pit, const msgbuf_t * interest_msgbuf)
{
assert(pit);
assert(interest_msgbuf);
- assert(msgbuf_get_type(interest_msgbuf) == MESSAGE_TYPE_INTEREST);
+ assert(msgbuf_get_type(interest_msgbuf) == MSGBUF_TYPE_INTEREST);
khiter_t k = kh_get(pit_name, pit->index_by_name,
msgbuf_get_name(interest_msgbuf));
diff --git a/hicn-light/src/hicn/core/pit.h b/hicn-light/src/hicn/core/pit.h
index 1aedcfab9..5607827fe 100644
--- a/hicn-light/src/hicn/core/pit.h
+++ b/hicn-light/src/hicn/core/pit.h
@@ -1,7 +1,26 @@
+/*
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file pit.h
+ * @brief hICN Pending Interest Table (PIT)
+ */
+
#ifndef HICNLIGHT_PIT_H
#define HICNLIGHT_PIT_H
-
#include <hicn/base/khash.h>
#include <hicn/core/nexthops.h>
#include <hicn/core/msgbuf.h>
@@ -10,14 +29,14 @@
#include <hicn/core/ticks.h>
typedef struct {
- msgbuf_t * msgbuf;
+ off_t msgbuf_id;
nexthops_t ingressIdSet;
nexthops_t egressIdSet;
fib_entry_t * fib_entry;
- Ticks creation_time;
- Ticks expiry_time;
+ Ticks create_ts;
+ Ticks expire_ts;
} pit_entry_t;
typedef enum {
@@ -30,10 +49,10 @@ typedef enum {
#define pit_entry_get_egress(E) (&((E)->egressIdSet))
#define pit_entry_get_fib_entry(E) ((E)->fib_entry)
#define pit_entry_set_fib_entry(E, FIB_ENTRY) ((E)->fib_entry = FIB_ENTRY)
-#define pit_entry_get_creation_time(E) ((E)->creation_time)
-#define pit_entry_get_expiry_time(E) ((E)->expiry_time)
-#define pit_entry_set_expiry_time(E, EXPIRY_TIME) \
- (entry)->expiry_time = EXPIRY_TIME
+#define pit_entry_get_create_ts(E) ((E)->create_ts)
+#define pit_entry_get_expire_ts(E) ((E)->expire_ts)
+#define pit_entry_set_expire_ts(E, EXPIRY_TIME) \
+ (entry)->expire_ts = EXPIRY_TIME
#define pit_entry_ingress_add(E, NH) \
nexthops_add(pit_entry_get_ingress(E), (NH))
@@ -44,26 +63,34 @@ typedef enum {
#define pit_entry_egress_add(E, NH) \
nexthops_add(pit_entry_get_egress(E), (NH))
-#define pit_entry_from_msgbuf(E, MSGBUF, EXPIRY_TIME, CREATION_TIME) \
-do { \
- E->msgbuf = MSGBUF; \
- pit_entry_ingress_add(E, msgbuf_get_connection_id(MSGBUF)); \
- E->fib_entry = NULL; \
- E->creation_time = CREATION_TIME; \
- E->expiry_time = EXPIRY_TIME; \
-} while(0)
-
#define name_hash(name) (name_HashCode(name))
#define name_hash_eq(a, b) (name_hash(b) - name_hash(a))
KHASH_INIT(pit_name, const Name *, unsigned, 0, name_hash, name_hash_eq);
typedef struct {
+ msgbuf_pool_t * msgbuf_pool;
+ size_t max_size;
pit_entry_t * entries; // pool
kh_pit_name_t * index_by_name;
} pit_t;
-pit_t * pit_create(size_t max_elts);
+/**
+ * @brief Allocate a new PIT data structure (extended parameters)
+ *
+ * @param init_size Initial size (0 = default)
+ * @param max_size Maximum size (0 = unbounded)
+ *
+ * @return pit_t* Newly allocated PIT data structure
+ */
+pit_t * _pit_create(size_t init_size, size_t max_size);
+
+/**
+ * @brief Allocate a new PIT data structure
+ *
+ * @return pit_t* Newly allocated PIT data structure
+ */
+#define pit_create() _pit_create(0, 0)
void pit_free(pit_t * pit);
@@ -81,12 +108,14 @@ do {
#define pit_at(pit, i) (pit->entries + i)
-pit_verdict_t pit_on_interest(pit_t * pit, msgbuf_t * msgbuf);
+pit_verdict_t pit_on_interest(pit_t * pit, off_t msgbuf_id);
-nexthops_t * pit_on_data(pit_t * pit, const msgbuf_t * msgbuf);
+nexthops_t * pit_on_data(pit_t * pit, off_t msgbuf_id);
-void pit_remove(pit_t * pit, const msgbuf_t * msgbuf);
+void pit_remove(pit_t * pit, off_t msgbuf_id);
pit_entry_t * pit_lookup(const pit_t * pit, const msgbuf_t * msgbuf);
+#define pit_get_msgbuf_pool(pit) (pit->msgbuf_pool)
+
#endif /* HICNLIGHT_PIT_H */
diff --git a/hicn-light/src/hicn/core/strategy.h b/hicn-light/src/hicn/core/strategy.h
index 3d48c5510..67630bbab 100644
--- a/hicn-light/src/hicn/core/strategy.h
+++ b/hicn-light/src/hicn/core/strategy.h
@@ -17,15 +17,12 @@
* \file strategy.h
* \brief hICN forwarding strategy
*/
-#ifndef HICN_STRATEGY_H
-#define HICN_STRATEGY_H
+#ifndef HICNLIGHT_STRATEGY_H
+#define HICNLIGHT_STRATEGY_H
-#include <hicn/core/name.h>
-#include <hicn/core/msgbuf.h>
-
-#include <hicn/strategies/load_balancer.h>
-#include <hicn/strategies/low_latency.h>
-#include <hicn/strategies/random.h>
+#include "../strategies/load_balancer.h"
+#include "../strategies/low_latency.h"
+#include "../strategies/random.h"
typedef enum {
STRATEGY_TYPE_UNDEFINED,
@@ -67,4 +64,4 @@ typedef struct {
} strategy_entry_t;
-#endif /* HICN_STRATEGY_H */
+#endif /* HICNLIGHT_STRATEGY_H */
diff --git a/hicn-light/src/hicn/core/strategy_vft.h b/hicn-light/src/hicn/core/strategy_vft.h
index e698c9d94..61166d3dd 100644
--- a/hicn-light/src/hicn/core/strategy_vft.h
+++ b/hicn-light/src/hicn/core/strategy_vft.h
@@ -17,11 +17,12 @@
* \file strategy_vft.h
* \brief hICN forwarding strategy VFT
*/
-#ifndef HICN_STRATEGY_VFT_H
-#define HICN_STRATEGY_VFT_H
+#ifndef HICNLIGHT_STRATEGY_VFT_H
+#define HICNLIGHT_STRATEGY_VFT_H
-#include <hicn/core/strategy.h>
-#include <hicn/core/nexthops.h>
+#include "msgbuf.h"
+#include "nexthops.h"
+#include "strategy.h"
/**
* @typedef strategy_ops_t
@@ -73,4 +74,4 @@ const strategy_ops_t strategy_ ## NAME = { \
.on_timeout = strategy_ ## NAME ## _on_timeout, \
}
-#endif /* HICN_STRATEGY_VFT_H */
+#endif /* HICNLIGHT_STRATEGY_VFT_H */
diff --git a/hicn-light/src/hicn/core/wldr.c b/hicn-light/src/hicn/core/wldr.c
index 5a6c876b9..e9b1f77f9 100644
--- a/hicn-light/src/hicn/core/wldr.c
+++ b/hicn-light/src/hicn/core/wldr.c
@@ -151,7 +151,9 @@ void wldr_set_label(wldr_t * wldr, msgbuf_t *msgbuf) {
#endif
}
-void wldr_detect_losses(wldr_t * wldr, const connection_t * conn, msgbuf_t *msgbuf) {
+void wldr_detect_losses(wldr_t * wldr, const connection_t * connection,
+ const msgbuf_t * msgbuf)
+{
#if 0
if (message_HasWldr(msgbuf)) {
// this is a normal wldr packet
@@ -179,8 +181,9 @@ void wldr_detect_losses(wldr_t * wldr, const connection_t * conn, msgbuf_t *msgb
#endif
}
-void wldr_handle_notification(wldr_t * wldr, const connection_t * conn,
- msgbuf_t *msgbuf) {
+void wldr_handle_notification(wldr_t * wldr, const connection_t * connection,
+ const msgbuf_t *msgbuf)
+{
#if 0
uint16_t expected_lbl = (uint16_t)message_GetWldrExpectedLabel(msgbuf);
uint16_t received_lbl = (uint16_t)message_GetWldrLastReceived(msgbuf);
diff --git a/hicn-light/src/hicn/core/wldr.h b/hicn-light/src/hicn/core/wldr.h
index cb2f0e2cf..529977223 100644
--- a/hicn-light/src/hicn/core/wldr.h
+++ b/hicn-light/src/hicn/core/wldr.h
@@ -44,8 +44,9 @@ void wldr_reset_state(wldr_t * wldr);
void wldr_set_label(wldr_t * wldr, msgbuf_t * msgbuf);
-void wldr_detect_losses(wldr_t * wldr, const connection_t * conn, msgbuf_t * msgbuf);
+void wldr_detect_losses(wldr_t * wldr, const connection_t * connection,
+ const msgbuf_t * msgbuf);
-void wldr_handle_notification(wldr_t *wldr, const connection_t * conn,
- msgbuf_t * msgbuf);
+void wldr_handle_notification(wldr_t *wldr, const connection_t * connection,
+ const msgbuf_t * msgbuf);
#endif // wldr_h
diff --git a/hicn-light/src/hicn/io/CMakeLists.txt b/hicn-light/src/hicn/io/CMakeLists.txt
index d7e6977d6..80a1ba867 100644
--- a/hicn-light/src/hicn/io/CMakeLists.txt
+++ b/hicn-light/src/hicn/io/CMakeLists.txt
@@ -17,6 +17,7 @@ list(APPEND HEADER_FILES
)
list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/base.c
${CMAKE_CURRENT_SOURCE_DIR}/hicn.c
${CMAKE_CURRENT_SOURCE_DIR}/tcp.c
${CMAKE_CURRENT_SOURCE_DIR}/udp.c
diff --git a/hicn-light/src/hicn/io/base.c b/hicn-light/src/hicn/io/base.c
new file mode 100644
index 000000000..35d8915a8
--- /dev/null
+++ b/hicn-light/src/hicn/io/base.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file base.c
+ * #brief Implementation of base IO functions.
+ */
+
+#include <hicn/util/log.h>
+
+#include "base.h"
+
+/**
+ * @brief Helper function for listener to read a single packet on a socket
+ */
+ssize_t io_read_single_fd(int fd, msgbuf_t * msgbuf, address_t * address)
+{
+ uint8_t * packet = msgbuf_get_packet(msgbuf);
+ size_t size = msgbuf_get_len(msgbuf);
+
+ for(;;) {
+ ssize_t n = read(fd, packet, size);
+ if (n == 0)
+ return n;
+ if (n < 0) {
+ if (errno == EINTR)
+ continue; // XXX was break;
+ ERROR("read failed %d: (%d) %s", fd, errno, strerror(errno));
+ return -1;
+ }
+
+ msgbuf->length = n;
+ *address = ADDRESS_ANY(AF_UNSPEC, 0); // XXX placeholder, see hicn.c
+ }
+
+ return 1;
+}
+
+ssize_t io_read_single_socket(int fd, msgbuf_t * msgbuf, address_t * address)
+{
+
+ struct sockaddr_storage * sa = (struct sockaddr_storage *)address;
+ socklen_t sa_len = sizeof(sa);
+
+ uint8_t * packet = msgbuf_get_packet(msgbuf);
+
+ for (;;) {
+ ssize_t n = recvfrom(fd, packet, MTU, 0, (struct sockaddr *)&sa, &sa_len);
+ if (n == 0)
+ return n;
+ if (n < 0) {
+ if (errno == EINTR)
+ continue; // XXX was break;
+ ERROR("recvfrom failed %d: (%d) %s", fd, errno, strerror(errno));
+ return -1;
+ }
+
+ msgbuf->length = n;
+ }
+
+ return 1;
+}
+
+#ifdef __linux__
+ssize_t io_read_batch_socket(int fd, msgbuf_t ** msgbuf,
+ address_t ** address, size_t batch_size)
+{
+ struct mmsghdr msghdr[batch_size];
+ struct iovec iovecs[batch_size];
+ struct sockaddr_storage addrs[batch_size];
+
+ /* Prepare the mmghdr struct for recvmmsg */
+ for (unsigned i = 0; i < MAX_MSG; i++) {
+ struct mmsghdr *msg = &msghdr[i];
+ *msg = (struct mmsghdr) {
+ .msg_hdr = {
+ .msg_iov = &iovecs[i],
+ .msg_iovlen = 1,
+ .msg_name = &addrs[i],
+ .msg_namelen = sizeof(struct sockaddr_storage),
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ },
+ };
+
+ iovecs[i] = (struct iovec) {
+ .iov_base = msgbuf_get_packet(msgbuf[i]),
+ .iov_len = MTU,
+ };
+ }
+
+ int n;
+ for (;;) {
+ n = recvmmsg(fd, msghdr, batch_size, /* flags */ 0,
+ /* timeout */ NULL);
+ if (n == 0)
+ return 0;
+ if (n < 0) {
+ if (errno == EINTR)
+ continue; // XXX was break;
+ ERROR("read failed %d: (%d) %s", fd, errno, strerror(errno));
+ return (ssize_t) n;
+ }
+
+ /* Assign size to msgbuf, and build address pair */
+ for (int i = 0; i < n; i++) {
+ struct mmsghdr *msg = &msghdr[i];
+ msgbuf[i]->length = msg->msg_hdr.msg_iovlen;
+ **address = *(address_t*)msg->msg_hdr.msg_name;
+ }
+ }
+
+ return n;
+}
+#endif /* __linux__ */
+
diff --git a/hicn-light/src/hicn/core/messagePacketType.h b/hicn-light/src/hicn/io/base.h
index 9a559069e..639334072 100644
--- a/hicn-light/src/hicn/core/messagePacketType.h
+++ b/hicn-light/src/hicn/io/base.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2020 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:
@@ -14,22 +14,25 @@
*/
/**
- * @file message_packet_type_h
- * @brief Defines the packet type for a HICN message
- *
+ * @file base.h
+ * #brief Base IO functions.
*/
-#ifndef message_packet_type_h
-#define message_packet_type_h
+#ifndef HICNLIGHT_IO_BASE
+#define HICNLIGHT_IO_BASE
+
+#include "../core/address_pair.h"
+#include "../core/msgbuf.h"
+
+#define MAX_MSG 64 //16 //32
+
+ssize_t io_read_single_fd(int fd, msgbuf_t * msgbuf,
+ address_t * address);
+
+ssize_t io_read_single_socket(int fd, msgbuf_t * msgbuf,
+ address_t * address);
-typedef enum message_type {
- MESSAGE_TYPE_UNDEFINED,
- MESSAGE_TYPE_INTEREST,
- MESSAGE_TYPE_DATA,
- MESSAGE_TYPE_WLDR_NOTIFICATION,
- MESSAGE_TYPE_MAPME,
- MESSAGE_TYPE_COMMAND,
- MESSAGE_TYPE_N,
-} MessagePacketType;
+ssize_t io_read_batch_socket(int fd, msgbuf_t ** msgbuf,
+ address_t ** address, size_t n);
-#endif // message_packet_type_h
+#endif /* HICNLIGHT_IO_BASE */
diff --git a/hicn-light/src/hicn/io/hicn.c b/hicn-light/src/hicn/io/hicn.c
index 26c641e51..02b6728a9 100644
--- a/hicn-light/src/hicn/io/hicn.c
+++ b/hicn-light/src/hicn/io/hicn.c
@@ -26,17 +26,18 @@
#include <string.h>
#include <unistd.h>
-#include <hicn/core/listener.h>
-#include <hicn/core/listener_vft.h>
-#include <hicn/core/connection.h>
-#include <hicn/core/connection_vft.h>
-#include <hicn/core/connection_table.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/core/mapme.h>
-#include <hicn/core/messagePacketType.h>
-#include <hicn/socket/api.h>
#include <hicn/util/log.h>
+#include "base.h"
+#include "../core/listener.h"
+#include "../core/listener_vft.h"
+#include "../core/connection.h"
+#include "../core/connection_vft.h"
+#include "../core/connection_table.h"
+#include "../core/forwarder.h"
+#include "../core/mapme.h"
+#include "../socket/api.h"
+
#define IPv6 6
#define IPv4 4
#define MTU_SIZE 1500 // bytes
@@ -242,65 +243,7 @@ typedef struct {
} listener_hicn_data_t;
-static
-void
-listener_hicn_read_callback(listener_t * listener, int fd, void * data)
-{
- assert(listener);
- assert(!data); /* No user data */
- uint8_t packet[MTU_SIZE];
-
- int family = address_family(&listener->address);
- if ((family != AF_INET) && (family != AF_INET6)) {
- /*
- * We need to discard the frame. Read 1 byte. This will clear it off
- * the stack.
- */
- int nread = read(fd, packet, 1);
-
- if (nread > 0) {
- DEBUG("Discarded frame from fd %d", fd);
- } else if (nread < 0) {
- ERROR("Error trying to discard frame from fd %d: (%d) %s", fd, errno,
- strerror(errno));
- }
- return;
- }
-
-#if 0
- if (!(what & PARCEventType_Read))
- return;
-#endif
-
- ssize_t n = read(fd, packet, MTU_SIZE);
- if (n < 0) {
- ERROR("read failed %d: (%d) %s", fd, errno, strerror(errno));
- return;
- }
-
-#if 0
- address_t packet_addr;
- if (_createAddressFromPacket(packet, &packet_addr) < 0)
- return;
-
- address_pair_t pair_find = {
- .local = packet_addr,
- .remote = /* dummy */ hicn->localAddress,
- };
- const Connection *conn = _lookupConnection(listener, &pair_find);
- if (!conn) {
- address_pair_t pair = {
- .local = hicn->localAddress,
- .remote = packet_addr,
- };
- connid = _createNewConnection(listener, fd, &pair);
- } else {
- connid = connection_GetConnectionId(conn);
- }
-#endif
-
- listener_read_callback(listener->forwarder, listener, fd, &listener->address, packet, n);
-}
+#define listener_hicn_read_callback listener_read_callback
bool
listener_hicn_bind(listener_t * listener, const address_t * address)
@@ -426,7 +369,8 @@ listener_hicn_get_socket(const listener_t * listener, const address_t * local,
{
assert(listener);
assert(listener_get_type(listener) == FACE_TYPE_HICN);
- // assert(pair);
+ assert(local);
+ assert(remote);
/* ... */
@@ -434,6 +378,9 @@ listener_hicn_get_socket(const listener_t * listener, const address_t * local,
}
+#define listener_hicn_read_single io_read_single_fd
+#define listener_hicn_read_batch NULL
+
DECLARE_LISTENER(hicn);
/******************************************************************************
@@ -503,7 +450,7 @@ static
int
connection_hicn_send_packet(const connection_t * connection, const uint8_t * packet, size_t size)
{
- // assert(ops);
+ assert(connection);
assert(packet);
/* ... */
@@ -511,12 +458,4 @@ connection_hicn_send_packet(const connection_t * connection, const uint8_t * pac
return 0;
}
-static
-void
-connection_hicn_read_callback(connection_t * connection, int fd, void * data)
-{
- ERROR("Unexpected read callback for hicn connection");
- return;
-}
-
DECLARE_CONNECTION(hicn);
diff --git a/hicn-light/src/hicn/io/tcp.c b/hicn-light/src/hicn/io/tcp.c
index 0ed9b4650..e4e2b06af 100644
--- a/hicn-light/src/hicn/io/tcp.c
+++ b/hicn-light/src/hicn/io/tcp.c
@@ -27,19 +27,19 @@
#include <stdio.h>
#include <string.h>
-#include <hicn/core/connection.h>
-#include <hicn/core/connection_vft.h>
-#include <hicn/core/listener.h>
-#include <hicn/core/listener_vft.h>
-#include <hicn/core/msgbuf.h>
-#include <hicn/core/forwarder.h>
-
-#include <hicn/core/messageHandler.h>
-
-#include <hicn/utils/commands.h>
+#include <hicn/hicn.h>
#include <hicn/util/log.h>
-#include <hicn/hicn.h>
+#include "base.h"
+#include "../core/connection.h"
+#include "../core/connection_vft.h"
+#include "../core/listener.h"
+#include "../core/listener_vft.h"
+#include "../core/msgbuf.h"
+#include "../core/forwarder.h"
+#include "../core/messageHandler.h"
+#include "../utils/commands.h"
+
// 128 KB output queue
#define OUTPUT_QUEUE_BYTES (128 * 1024)
@@ -93,13 +93,8 @@ listener_tcp_get_socket(const listener_t * listener, const address_t * local,
}
-static
-void
-listener_tcp_read_callback(listener_t * listener, int fd, void * data)
-{
- ERROR("[listener_tcp_read_callback] Not implemented");
-
-}
+#define listener_tcp_read_single io_read_single_socket
+#define listener_tcp_read_batch NULL
DECLARE_LISTENER(tcp);
@@ -324,11 +319,10 @@ connection_tcp_sendv(connnection_t * connection, struct iovec * iov,
// XXX too much repeated code with sendv here
static
int
-connection_tcp_send(const connection_t * connection, //const address_t * address,
- msgbuf_t * msgbuf, bool queue)
+connection_tcp_send(const connection_t * connection, msgbuf_t * msgbuf,
+ bool queue)
{
assert(connection);
- // assert(address);
/* msgbuf can be NULL */
/* No need to flush */
@@ -459,12 +453,13 @@ ERR:
* @param <#param1#>
* @return <#return#>
*/
+#if 0
static
void
connection_tcp_read_callback(connection_t * connection, int fd, void * user_data)
{
- // assert(!!(what & PARCEventType_Read));
assert(connection);
+ /* user_data can be NULL */
connection_tcp_data_t * data = connection->data;
assert(RECV_BUFLEN - data->woff > MTU);
@@ -487,7 +482,7 @@ connection_tcp_read_callback(connection_t * connection, int fd, void * user_data
uint8_t * packet = data->buf + data->roff;
size_t size = data->woff - data->roff; /* > 0 */
- ssize_t used = listener_read_callback(connection->forwarder, NULL, fd,
+ ssize_t used = listener_read_callback(NULL, fd,
address_pair_get_local(&connection->pair), packet, size);
if (used < 0)
return; // XXX close connection ?
@@ -517,6 +512,7 @@ connection_tcp_read_callback(connection_t * connection, int fd, void * user_data
return;
}
+#endif
#if 0
static
diff --git a/hicn-light/src/hicn/io/udp.c b/hicn-light/src/hicn/io/udp.c
index f0eaf8fd0..38d643838 100644
--- a/hicn-light/src/hicn/io/udp.c
+++ b/hicn-light/src/hicn/io/udp.c
@@ -31,6 +31,7 @@
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <sys/uio.h>
@@ -46,19 +47,20 @@
#define UDP_GRO 104
#endif /* WITH_GSO */
-#include <hicn/core/address_pair.h>
-#include <hicn/core/connection.h>
-#include <hicn/core/connection_vft.h>
-#include <hicn/core/listener.h>
-#include <hicn/core/listener_vft.h>
-#include <hicn/base/loop.h>
-#include <hicn/core/msgbuf.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/core/messageHandler.h>
-#include <hicn/core/messagePacketType.h>
-#include <hicn/hicn-light/config.h>
#include <hicn/util/log.h>
+#include "base.h"
+#include "../base/loop.h"
+#include "../core/address_pair.h"
+#include "../core/connection.h"
+#include "../core/connection_vft.h"
+#include "../core/forwarder.h"
+#include "../core/listener.h"
+#include "../core/listener_vft.h"
+#include "../core/messageHandler.h"
+#include "../core/msgbuf.h"
+//#include "../hicn-light/config.h"
+
// Batching based on recvmmsg is also generic
// the difference is the handling of packet as in tcp we need to go through the
// ring buffer first to do the framing, while in UDP this is already done
@@ -75,8 +77,6 @@
typedef struct {
uint16_t port; // in address ?
-
- batch_buffer_t bb;
} listener_udp_data_t;
#ifdef __ANDROID__
@@ -211,10 +211,10 @@ listener_udp_initialize(listener_t * listener)
{
assert(listener);
+#if 0
listener_udp_data_t * data = listener->data;
assert(data);
-
- init_batch_buffers(&data->bb);
+#endif
// XXX Socket creation should be a function per-se and not be called in
// initialize !
@@ -287,18 +287,13 @@ ERR_SOCKET:
return -1;
}
-static
-void
-listener_udp_read_callback(listener_t * listener, int fd, void * user_data)
-{
- assert(listener);
- assert(!user_data);
-
- listener_udp_data_t * data = listener->data;
- assert(data);
+#define listener_udp_read_single io_read_single_socket
- listener_batch_read_callback(listener->forwarder, listener, fd, &listener->address, &data->bb);
-}
+#ifdef __linux__
+#define listener_udp_read_batch io_read_batch_socket
+#else
+#define listener_udp_read_batch NULL
+#endif /* __linux__ */
DECLARE_LISTENER(udp);
@@ -307,7 +302,8 @@ DECLARE_LISTENER(udp);
******************************************************************************/
typedef struct {
- batch_buffer_t bb;
+ // XXX queue storage : msfbuf id
+ off_t queue[MAX_MSG]; // sized according to the max batch
int queue_len;
} connection_udp_data_t;
@@ -323,8 +319,6 @@ connection_udp_initialize(connection_t * connection)
connection_udp_data_t * data = connection->data;
assert(data);
- init_batch_buffers(&data->bb);
-
data->queue_len = 0;
return 0;
@@ -358,6 +352,10 @@ connection_udp_send(const connection_t * connection, msgbuf_t * msgbuf, bool que
connection_udp_data_t * data = connection->data;
assert(data);
+ forwarder_t * forwarder = connection->forwarder;
+ msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+
+
/* Flush if required or if queue is full */
if ((!msgbuf) || (queue && (data->queue_len > MAX_MSG))) {
/* Flush operation */
@@ -366,7 +364,38 @@ connection_udp_send(const connection_t * connection, msgbuf_t * msgbuf, bool que
#else
int flags = 0;
#endif /* WITH_ZEROCOPY */
- int n = sendmmsg(connection->fd, data->bb.msghdr, data->queue_len, flags);
+
+
+ // BEGIN : send batch
+
+ /* Preparing the struct mmsghdr for batch sending */
+ struct mmsghdr msghdr[MAX_MSG];
+ struct iovec iovecs[MAX_MSG];
+
+ /* Prepare the mmghdr struct for recvmmsg */
+ for (unsigned i = 0; i < data->queue_len; i++) {
+ struct mmsghdr *msg = &msghdr[i];
+ *msg = (struct mmsghdr) {
+ .msg_hdr = {
+ .msg_iov = &iovecs[i],
+ .msg_iovlen = 1,
+ .msg_name = NULL,
+ .msg_namelen = 0,
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ },
+ };
+
+ msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, data->queue[i]);
+ iovecs[i] = (struct iovec) {
+ .iov_base = msgbuf_get_packet(msgbuf),
+ .iov_len = msgbuf_get_len(msgbuf),
+ };
+ }
+
+ // XXX build mmsghdr from the msgbuf queue
+
+ int n = sendmmsg(connection->fd, msghdr, data->queue_len, flags);
if (n == -1) {
perror("sendmmsg()");
data->queue_len = 0;
@@ -384,11 +413,10 @@ connection_udp_send(const connection_t * connection, msgbuf_t * msgbuf, bool que
}
if (queue) {
- struct iovec *iovec = &data->bb.iovecs[data->queue_len++];
- iovec->iov_base = msgbuf_get_packet(msgbuf);
- iovec->iov_len = msgbuf_get_len(msgbuf);
-
+ /* Queue packet */
+ data->queue[data->queue_len++] = msgbuf_pool_get_id(msgbuf_pool, msgbuf);
} else {
+ /* Send one */
ssize_t writeLength = write(connection->fd, msgbuf_get_packet(msgbuf),
msgbuf_get_len(msgbuf));
@@ -467,16 +495,13 @@ connection_udp_send_packet(const connection_t * connection, const uint8_t * pack
return 0;
}
-static
-void
-connection_udp_read_callback(connection_t * connection, int fd, void * user_data)
-{
- assert(connection);
- assert(!user_data);
+#define connection_udp_read_single listener_read_batch_socket listener_single_socket
+
+#ifdef __linux__
+#define connection_udp_read_batch listener_read_batch_socket
+#else
+#define connection_udp_read_batch NULL
+#endif /* __linux__ */
- connection_udp_data_t * data = connection->data;
- assert(data);
- listener_batch_read_callback(connection->forwarder, NULL, fd, address_pair_get_local(&connection->pair), &data->bb);
-}
DECLARE_CONNECTION(udp);
diff --git a/hicn-light/src/hicn/strategies/low_latency.h b/hicn-light/src/hicn/strategies/low_latency.h
index 4745c4c47..ff8255eae 100644
--- a/hicn-light/src/hicn/strategies/low_latency.h
+++ b/hicn-light/src/hicn/strategies/low_latency.h
@@ -22,6 +22,8 @@
#define MAX_FWD_STRATEGY_RELATED_PREFIXES 10
+struct name_s;
+
typedef struct {
} strategy_low_latency_nexthop_state_t;
@@ -30,7 +32,7 @@ typedef struct {
typedef struct {
//Name ** related_prefixes;
- Name *related_prefixes[MAX_FWD_STRATEGY_RELATED_PREFIXES];
+ struct name_s * related_prefixes[MAX_FWD_STRATEGY_RELATED_PREFIXES];
unsigned related_prefixes_len;
} strategy_low_latency_options_t;