diff options
author | Jordan Augé <jordan.auge+fdio@cisco.com> | 2020-09-23 17:50:52 +0200 |
---|---|---|
committer | Jordan Augé <jordan.auge+fdio@cisco.com> | 2020-09-28 18:25:30 +0200 |
commit | 32dccec98e4c7d7e4ce902e19ba8d1b29b823758 (patch) | |
tree | 95c5dec2083a3774c13bd5f896743cd6c5c42a7a | |
parent | 7356408ca1554468c9d7b9840aaaee28b4341c8d (diff) |
[HICN-570] Message buffer (incl. CS and PIT changes)
Change-Id: I4c508e4b04dee3acbfc3da1d26e1770cb826f22b
Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com>
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, ¶ms); 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; |