aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/.clang-format10
-rw-r--r--lib/CMakeLists.txt49
-rw-r--r--lib/cmake/packaging.cmake (renamed from lib/cmake/Modules/Packaging.cmake)16
-rw-r--r--lib/includes/CMakeLists.txt38
-rw-r--r--lib/includes/hicn/base.h348
-rw-r--r--lib/includes/hicn/common.h263
-rw-r--r--lib/includes/hicn/compat.h469
-rw-r--r--lib/includes/hicn/error.h31
-rw-r--r--lib/includes/hicn/face.h245
-rw-r--r--lib/includes/hicn/header.h129
-rw-r--r--lib/includes/hicn/hicn.h41
-rw-r--r--lib/includes/hicn/interest_manifest.h220
-rw-r--r--lib/includes/hicn/mapme.h114
-rw-r--r--lib/includes/hicn/name.h246
-rw-r--r--lib/includes/hicn/ops.h871
-rw-r--r--lib/includes/hicn/packet.h668
-rw-r--r--lib/includes/hicn/policy.h263
-rw-r--r--lib/includes/hicn/protocol/ah.h16
-rw-r--r--lib/includes/hicn/protocol/icmp.h12
-rw-r--r--lib/includes/hicn/protocol/icmprd.h12
-rw-r--r--lib/includes/hicn/protocol/ipv4.h49
-rw-r--r--lib/includes/hicn/protocol/ipv6.h36
-rw-r--r--lib/includes/hicn/protocol/new.h88
-rw-r--r--lib/includes/hicn/protocol/tcp.h102
-rw-r--r--lib/includes/hicn/protocol/udp.h4
-rw-r--r--lib/includes/hicn/strategy.h64
-rw-r--r--lib/includes/hicn/util/array.h323
-rw-r--r--lib/includes/hicn/util/bitmap.h332
-rw-r--r--lib/includes/hicn/util/hash.h368
-rw-r--r--lib/includes/hicn/util/ip_address.h211
-rw-r--r--lib/includes/hicn/util/khash.h826
-rw-r--r--lib/includes/hicn/util/log.h77
-rw-r--r--lib/includes/hicn/util/map.h444
-rw-r--r--lib/includes/hicn/util/pool.h292
-rw-r--r--lib/includes/hicn/util/ring.h227
-rw-r--r--lib/includes/hicn/util/set.h370
-rw-r--r--lib/includes/hicn/util/slab.h126
-rw-r--r--lib/includes/hicn/util/sstrncpy.h76
-rw-r--r--lib/includes/hicn/util/token.h8
-rw-r--r--lib/includes/hicn/util/types.h56
-rw-r--r--lib/includes/hicn/util/vector.h470
-rw-r--r--lib/includes/hicn/util/win_portability.h88
-rw-r--r--lib/includes/hicn/util/windows/dlfcn.h15
-rw-r--r--[-rwxr-xr-x]lib/includes/hicn/util/windows/windows_utils.h326
-rw-r--r--lib/includes/hicn/validation.h55
-rw-r--r--lib/src/CMakeLists.txt145
-rw-r--r--lib/src/base.c51
-rw-r--r--lib/src/common.c79
-rw-r--r--lib/src/compat.c1273
-rw-r--r--lib/src/error.c4
-rw-r--r--lib/src/face.c455
-rw-r--r--lib/src/libhicn-config.cmake.in12
-rw-r--r--lib/src/mapme.c111
-rw-r--r--lib/src/name.c741
-rw-r--r--lib/src/ops.c50
-rw-r--r--lib/src/ops.h979
-rw-r--r--lib/src/packet.c806
-rw-r--r--lib/src/policy.c70
-rw-r--r--lib/src/protocol.h (renamed from lib/includes/hicn/protocol.h)15
-rw-r--r--lib/src/protocol/ah.c200
-rw-r--r--lib/src/protocol/ah.h83
-rw-r--r--lib/src/protocol/icmp.c175
-rw-r--r--lib/src/protocol/icmp.h84
-rw-r--r--lib/src/protocol/icmprd.h72
-rw-r--r--lib/src/protocol/ipv4.c441
-rw-r--r--lib/src/protocol/ipv4.h112
-rw-r--r--lib/src/protocol/ipv6.c398
-rw-r--r--lib/src/protocol/ipv6.h86
-rw-r--r--lib/src/protocol/new.c563
-rw-r--r--lib/src/protocol/new.h95
-rw-r--r--lib/src/protocol/tcp.c429
-rw-r--r--lib/src/protocol/tcp.h165
-rw-r--r--lib/src/protocol/udp.c308
-rw-r--r--lib/src/protocol/udp.h44
-rw-r--r--lib/src/strategy.c22
-rw-r--r--lib/src/test/CMakeLists.txt55
-rw-r--r--lib/src/test/main.cc23
-rw-r--r--lib/src/test/test_bitmap.cc261
-rw-r--r--lib/src/test/test_interest_manifest.cc224
-rw-r--r--lib/src/test/test_ip_address.cc73
-rw-r--r--lib/src/test/test_khash.cc179
-rw-r--r--lib/src/test/test_name.cc401
-rw-r--r--lib/src/test/test_new_header.cc346
-rw-r--r--lib/src/test/test_pool.cc209
-rw-r--r--lib/src/test/test_ring.cc104
-rw-r--r--lib/src/test/test_slab.cc148
-rw-r--r--lib/src/test/test_udp_header.cc360
-rw-r--r--lib/src/test/test_validation.cc55
-rw-r--r--lib/src/test/test_vector.cc254
-rw-r--r--lib/src/util/ip_address.c373
-rw-r--r--lib/src/util/log.c247
-rw-r--r--lib/src/util/pool.c175
-rw-r--r--lib/src/util/ring.c49
-rw-r--r--lib/src/util/slab.c203
-rw-r--r--lib/src/util/types.c56
-rw-r--r--lib/src/util/vector.c101
-rw-r--r--lib/src/util/windows/dlfcn.c84
97 files changed, 15229 insertions, 5913 deletions
diff --git a/lib/.clang-format b/lib/.clang-format
index 351a70e20..b4846b63a 100644
--- a/lib/.clang-format
+++ b/lib/.clang-format
@@ -10,11 +10,5 @@ BreakBeforeBinaryOperators: None
ContinuationIndentWidth: 2
ForEachMacros:
- - 'clib_bitmap_foreach'
- - 'pool_foreach'
- - 'pool_foreach_index'
- - 'vec_foreach'
- - 'vec_foreach_backwards'
- - 'vec_foreach_index'
- - 'vec_foreach_index_backwards'
- - 'vlib_foreach_rx_tx'
+ - 'interest_manifest_foreach_suffix'
+
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 65c1cd4ee..ca845ab48 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-2022 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
@@ -11,41 +11,50 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+##############################################################
+# Project and cmake version
+##############################################################
cmake_minimum_required (VERSION 3.10 FATAL_ERROR)
project(libhicn C)
-#include(CTest)
+
+##############################################################
+# Cmake modules
+##############################################################
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules"
- "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
)
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ include(CommonSetup)
endif()
+
+##############################################################
+# Libs and Bins names
+##############################################################
set(LIBHICN hicn CACHE INTERNAL "" FORCE)
+set(LIBHICN_COMPONENT lib${LIBHICN} CACHE INTERNAL "" FORCE)
set(LIBHICN_SHARED ${LIBHICN}.shared CACHE INTERNAL "" FORCE)
set(LIBHICN_STATIC ${LIBHICN}.static CACHE INTERNAL "" FORCE)
-set(HICN_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/includes CACHE INTERNAL "" FORCE)
-
-include (Packaging)
-option(CMAKE_BUILD_TEST "Build unit tests" OFF)
+##############################################################
+# Dependencies
+##############################################################
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
+if(INTERNAL_ENVIRONMENT)
+ include(ImportInternal)
+ ImportInternal()
+ set(INTERNAL_ENVIRONMENT_FOUND True CACHE STRING "Internal dependency found")
endif()
-if (NOT WIN32)
- set(CMAKE_C_FLAGS -Wall)
-else ()
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996")
-endif ()
+##############################################################
+# Packaging and versioning
+##############################################################
+include(${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake)
-add_subdirectory(includes)
-add_subdirectory (src)
+add_subdirectory(includes)
+add_subdirectory(src)
diff --git a/lib/cmake/Modules/Packaging.cmake b/lib/cmake/packaging.cmake
index 2ceda1426..5f1691722 100644
--- a/lib/cmake/Modules/Packaging.cmake
+++ b/lib/cmake/packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-2022 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
@@ -32,11 +32,21 @@ set(lib${LIBHICN}-dev_DESCRIPTION ${${LIBHICN}_DESCRIPTION}
)
set(lib${LIBHICN}-dev_DEB_DEPENDENCIES
- "libhicn (>= stable_version)"
+ "libhicn (= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
+
+if (INTERNAL_ENVIRONMENT)
+ include(CheckSafeC)
+ CheckSafeC()
+ set(lib${LIBHICN}-dev_DEB_DEPENDENCIES
+ "${lib${LIBHICN}-dev_DEB_DEPENDENCIES}, ${SAFEC_DEPENDENCY}"
+ CACHE STRING "Dependencies for deb/rpm package."
+ )
+endif()
+
set(lib${LIBHICN}-dev_RPM_DEPENDENCIES
- "libhicn >= stable_version"
+ "libhicn = stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
diff --git a/lib/includes/CMakeLists.txt b/lib/includes/CMakeLists.txt
index 6c2c34b86..3c79fb891 100644
--- a/lib/includes/CMakeLists.txt
+++ b/lib/includes/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-2022 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
@@ -11,8 +11,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-set(HICN_INCLUDE_DIRS
- ${CMAKE_CURRENT_SOURCE_DIR} ""
+##############################################################
+# Public headers directory
+##############################################################
+set(Libhicn_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}
CACHE INTERNAL
"" FORCE
)
@@ -21,38 +24,35 @@ set(LIBHICN_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/hicn/hicn.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/base.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/common.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/compat.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/error.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/header.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/face.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/mapme.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/name.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/packet.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/policy.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ops.h
- PARENT_SCOPE
-)
-
-set(LIBHICN_HEADER_FILES_PROTOCOL
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/ah.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/icmp.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/icmprd.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/ipv4.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/ipv6.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/tcp.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/udp.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/strategy.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/validation.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/interest_manifest.h
PARENT_SCOPE
)
set(LIBHICN_HEADER_FILES_UTIL
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/array.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/bitmap.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/hash.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/ip_address.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/khash.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/log.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/map.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/pool.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/ring.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/set.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/slab.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/sstrncpy.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/token.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/vector.h
PARENT_SCOPE
)
set_property(GLOBAL PROPERTY LIBHICN_HEADER_FILES_UTIL_PROPERTY "${LIBHICN_HEADER_FILES_UTIL}")
-
diff --git a/lib/includes/hicn/base.h b/lib/includes/hicn/base.h
index 1061724ce..dcbe47877 100644
--- a/lib/includes/hicn/base.h
+++ b/lib/includes/hicn/base.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -21,6 +21,8 @@
#ifndef HICN_BASE_H
#define HICN_BASE_H
+#include <stdio.h>
+#include <stdbool.h>
#include "common.h"
#ifdef _WIN32
#include <Winsock2.h>
@@ -30,20 +32,29 @@
/* Default header fields */
#define HICN_DEFAULT_TTL 254
+#define SYMBOLIC_NAME_LEN 16
+
+/* hICN attribute types */
+
+/* Face id */
+
typedef u32 hicn_faceid_t;
-typedef u8 hicn_pathlabel_t;
+
+/* Lifetime */
+
typedef u32 hicn_lifetime_t;
-#define HICN_MAX_LIFETIME_SCALED 0xFFFF
-#define HICN_MAX_LIFETIME_MULTIPLIER 0x0F /* 4 bits */
-#define HICN_MAX_LIFETIME HICN_MAX_LIFETIME_SCALED << HICN_MAX_LIFETIME_MULTIPLIER
+#define HICN_MAX_LIFETIME_SCALED 0xFFFF
+#define HICN_MAX_LIFETIME_MULTIPLIER 0x0F /* 4 bits */
+#define HICN_MAX_LIFETIME \
+ HICN_MAX_LIFETIME_SCALED << HICN_MAX_LIFETIME_MULTIPLIER
/**
* @brief hICN packet format type
*
- * The hICN type represents the sequence of protocols that we can find in packet
- * headers. They are represented as a quartet of u8 values, correponding to
- * IANA protocol assignment, and read from right to left. This is done to
+ * The hICN type represents the sequence of protocols that we can find in
+ * packet headers. They are represented as a quartet of u8 values, correponding
+ * to IANA protocol assignment, and read from right to left. This is done to
* faciliate decapsulation of packet header by simple shift/mask operations.
*
* For instance, an IPv6/TCP packet will be identified as :
@@ -53,72 +64,168 @@ typedef u32 hicn_lifetime_t;
* currently used by an hypothetical signed MAP-Me update :
* [IPPROTO_ICMPRD, IPPROTO_AH, IPPROTO_ICMP, IPPROTO_IPV6]
*/
-typedef union
-{
- /** protocol layers representation */
- struct
- {
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- u8 l1; /**< First layer */
- u8 l2; /**< Second layer */
- u8 l3; /**< Third layer */
- u8 l4; /**< Fourth layer */
-#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
- u8 l4; /**< Fourth layer */
- u8 l3; /**< Third layer */
- u8 l2; /**< Second layer */
- u8 l1; /**< First layer */
-#elif _WIN32 /* Windows is assumed little-endian */
- u8 l1;
- u8 l2;
- u8 l3;
- u8 l4;
-#else
-#error "Unsupported endianness"
-#endif
- };
- /** u32 representation */
- u32 as_u32;
-} hicn_type_t;
+
+typedef uint32_t hicn_packet_format_t;
/* Common protocol layers */
-/* Common protocol layers */
-#ifndef _WIN32
-#define HICN_TYPE(x,y,z,t) (hicn_type_t) {{ .l1 = x, .l2 = y, .l3 = z, .l4 = t }}
-#else
-inline hicn_type_t
-HICN_TYPE(int x, int y, int z, int t)
-{
- hicn_type_t type;
- type.l1 = x;
- type.l2 = y;
- type.l3 = z;
- type.l4 = t;
- return type;
-}
+#define HICN_PACKET_FORMAT(x, y, z, t) \
+ (uint32_t) (((x) << 24) + ((y) << 16) + ((z) << 8) + (t))
+
+#define HICN_PACKET_FORMAT_SIZE 4
+
+// i = 0..3
+#define HICN_PACKET_FORMAT_GET(format, i) \
+ (i < 0 || i > 3) ? IPPROTO_NONE : ((format >> ((3 - (i)) << 3)) & 0xFF)
+
+#define HICN_PACKET_FORMAT_SET(format, i, val) \
+ format = ((val << ((3 - i) << 3)) | \
+ (format & (0xFFFFFFFF ^ (0xFF << ((3 - i) << 3)))))
+
+#define HICN_PACKET_FORMAT_ENUMERATE(FORMAT, POS, PROTOCOL, BODY) \
+ for (unsigned POS = 0; POS <= HICN_PACKET_FORMAT_SIZE - 1; POS++) \
+ { \
+ uint8_t PROTOCOL = HICN_PACKET_FORMAT_GET (FORMAT, POS); \
+ BODY; \
+ }
+
+#define HICN_PACKET_FORMAT_L1(format) HICN_PACKET_FORMAT_L ((format), 0)
+#define HICN_PACKET_FORMAT_L2(format) HICN_PACKET_FORMAT_L ((format), 1)
+#define HICN_PACKET_FORMAT_L3(format) HICN_PACKET_FORMAT_L ((format), 2)
+#define HICN_PACKET_FORMAT_L4(format) HICN_PACKET_FORMAT_L ((format), 3)
+
+extern const char *const _protocol_str[];
+
+#define protocol_str(x) protocol_str[x]
+
+int hicn_packet_format_snprintf (char *s, size_t size,
+ hicn_packet_format_t format);
+
+#define MAXSZ_HICN_PACKET_FORMAT 4 * 4 + 3 // ICMP/ICMP/ICMP/ICMP
+
+#if !defined(__cplusplus)
+#define constexpr const
#endif
-#define HICN_TYPE_IPV4_TCP HICN_TYPE(IPPROTO_IP, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV4_ICMP HICN_TYPE(IPPROTO_IP, IPPROTO_ICMP, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV6_TCP HICN_TYPE(IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV6_ICMP HICN_TYPE(IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV4_TCP_AH HICN_TYPE(IPPROTO_IP, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE)
-#define HICN_TYPE_IPV4_ICMP_AH HICN_TYPE(IPPROTO_IP, IPPROTO_ICMP, IPPROTO_AH, IPPROTO_NONE)
-#define HICN_TYPE_IPV6_TCP_AH HICN_TYPE(IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE)
-#define HICN_TYPE_IPV6_ICMP_AH HICN_TYPE(IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_AH, IPPROTO_NONE)
-#define HICN_TYPE_NONE HICN_TYPE(IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_IPV4_TCP \
+ HICN_PACKET_FORMAT (IPPROTO_IP, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_IPV4_ICMP \
+ HICN_PACKET_FORMAT (IPPROTO_IP, IPPROTO_ICMP, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_IPV6_TCP \
+ HICN_PACKET_FORMAT (IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_IPV6_ICMP \
+ HICN_PACKET_FORMAT (IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_NEW \
+ HICN_PACKET_FORMAT (IPPROTO_ENCAP, IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_IPV4_UDP \
+ HICN_PACKET_FORMAT (IPPROTO_IP, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_IPV6_UDP \
+ HICN_PACKET_FORMAT (IPPROTO_IPV6, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_IPV4_TCP_AH \
+ HICN_PACKET_FORMAT (IPPROTO_IP, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_IPV4_ICMP_AH \
+ HICN_PACKET_FORMAT (IPPROTO_IP, IPPROTO_ICMP, IPPROTO_AH, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_IPV6_TCP_AH \
+ HICN_PACKET_FORMAT (IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_IPV6_ICMP_AH \
+ HICN_PACKET_FORMAT (IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_AH, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_NEW_AH \
+ HICN_PACKET_FORMAT (IPPROTO_ENCAP, IPPROTO_AH, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_PACKET_FORMAT_IPV6_UDP_AH \
+ HICN_PACKET_FORMAT (IPPROTO_IPV6, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_AH)
+#define HICN_PACKET_FORMAT_IPV4_UDP_AH \
+ HICN_PACKET_FORMAT (IPPROTO_IP, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_AH)
+#define HICN_PACKET_FORMAT_NONE \
+ HICN_PACKET_FORMAT (IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE)
+
+/* Default packet format */
+
+#define HICN_PACKET_FORMAT_DEFAULT HICN_PACKET_FORMAT_IPV6_TCP
/**
- * @brief Check if type is none.
- * @return 1 if none, 0 otherwise
+ * @brief Return the hICN format with an additional AH header
+ * @param [in] format - hICN packet format
+ * @return Updated hICN packet format
*/
-always_inline int
-hicn_type_is_none(hicn_type_t type)
+static inline hicn_packet_format_t
+hicn_get_ah_format (hicn_packet_format_t format)
{
- return (type.l1 == IPPROTO_NONE) && (type.l2 == IPPROTO_NONE) &&
- (type.l3 == IPPROTO_NONE) && (type.l4 == IPPROTO_NONE);
+ HICN_PACKET_FORMAT_ENUMERATE (format, i, protocol, {
+ switch (protocol)
+ {
+ {
+ case IPPROTO_AH:
+ return format;
+ case IPPROTO_NONE:
+ HICN_PACKET_FORMAT_SET (format, i, IPPROTO_AH);
+ return format;
+ default:
+ break;
+ }
+ }
+ });
+ return format;
}
+/*
+ * MAX(IPV4_HDRLEN (20), IPV6_HDRLEN (40))
+ * + MAX (TCP_HDRLEN (20), UDP_HDRLEN (8), ICMP_HDRLEN (8), NEW_HDRLEN (32))
+ * + AH_HDRLEN
+ */
+#define HICN_HDRLEN_MAX 72
+
+#define HICN_PACKET_FORMAT_IS_NONE(format) \
+ ((HICN_PACKET_FORMAT_GET (format, 0) == IPPROTO_NONE) && \
+ (HICN_PACKET_FORMAT_GET (format, 1) == IPPROTO_NONE) && \
+ (HICN_PACKET_FORMAT_GET (format, 2) == IPPROTO_NONE) && \
+ (HICN_PACKET_FORMAT_GET (format, 3) == IPPROTO_NONE))
+
+#define HICN_PACKET_FORMAT_IS_AH(format) \
+ ((HICN_PACKET_FORMAT_GET (format, 0) == IPPROTO_AH) || \
+ (HICN_PACKET_FORMAT_GET (format, 1) == IPPROTO_AH) || \
+ (HICN_PACKET_FORMAT_GET (format, 2) == IPPROTO_AH) || \
+ (HICN_PACKET_FORMAT_GET (format, 3) == IPPROTO_AH))
+
+#define HICN_PACKET_FORMAT_IS_IPV4(format) \
+ (HICN_PACKET_FORMAT_GET (format, 0) == IPPROTO_IP)
+#define HICN_PACKET_FORMAT_IS_IPV6(format) \
+ (HICN_PACKET_FORMAT_GET (format, 0) == IPPROTO_IPV6)
+
+/*
+ * @brief hICN packet types
+ *
+ * probes are like normal interest & data but:
+ * - interests use BFD port as the destination
+ * - data use BFD port as the source + expiry time must be 0.
+ * if any of these conditions is not met, the packet is still matched as an
+ * interest or data packet.
+ *
+ */
+
+#define foreach_packet_type \
+ _ (UNDEFINED) \
+ _ (INTEREST) \
+ _ (DATA) \
+ _ (WLDR_NOTIFICATION) \
+ _ (MAPME) \
+ _ (PROBE) \
+ _ (COMMAND) \
+ _ (N)
+
+/**
+ * @brief hICN Packet type
+ */
+typedef enum
+{
+#define _(x) HICN_PACKET_TYPE_##x,
+ foreach_packet_type
+#undef _
+} hicn_packet_type_t;
+#undef foreach_type
+
+extern const char *_hicn_packet_type_str[];
+
+#define hicn_packet_type_str(x) _hicn_packet_type_str[x]
+
/**
* @brief hICN Payload type
*
@@ -132,39 +239,120 @@ typedef enum
HPT_UNSPEC = 999
} hicn_payload_type_t;
+/* Path label */
+
+typedef u8 hicn_path_label_t;
+
+#define INVALID_PATH_LABEL 0
+
/**
* @brief Path label computations
*
- * Path label is computed by accumulating the identifiers of successive output
- * faces as a Data packet is traveling from its producer back to the consumer
- * originating the Interest.
+ * Path label is computed by accumulating the identifiers of successive
+ * output faces as a Data packet is traveling from its producer back to the
+ * consumer originating the Interest.
*
* NOTE: this computation is not (yet) part of the hICN specification.
*/
-#define HICN_PATH_LABEL_MASK 0x000000ff
-#define HICN_PATH_LABEL_SIZE 8
+#define HICN_PATH_LABEL_MASK 0x000000ff
+#define HICN_PATH_LABEL_SIZE_BITS sizeof (hicn_path_label_t) * 8
/**
* @brief Path label update
- * @param [in] current_label Current pathlabel
+ * @param [in] current_label Current path_label
* @param [in] face_id The face identifier to combine into the path label
- * @param [out] new_label Computed pathlabel
+ * @param [out] new_label Computed path_label
*
- * This function updates the current_label based on the new face_id, and returns
+ * This function updates the current_label based on the new face_id, and
+ * returns
*/
-always_inline void
-update_pathlabel (hicn_pathlabel_t current_label, hicn_faceid_t face_id,
- hicn_pathlabel_t * new_label)
+static inline void
+update_path_label (hicn_path_label_t current_label, hicn_faceid_t face_id,
+ hicn_path_label_t *new_label)
{
- hicn_pathlabel_t pl_face_id =
- (hicn_pathlabel_t) (face_id & HICN_PATH_LABEL_MASK);
+ hicn_path_label_t pl_face_id =
+ (hicn_path_label_t) (face_id & HICN_PATH_LABEL_MASK);
- *new_label =
- ((current_label << 1) | (current_label >> (HICN_PATH_LABEL_SIZE - 1))) ^
- pl_face_id;
+ *new_label = ((current_label << 1) |
+ (current_label >> (HICN_PATH_LABEL_SIZE_BITS - 1))) ^
+ pl_face_id;
}
+/***************************************************************
+ * Statistics
+ ***************************************************************/
+
+typedef struct
+{
+ // Packets processed
+ uint32_t countReceived; // Interest and data only
+ uint32_t countInterestsReceived;
+ uint32_t countObjectsReceived;
+
+ // Packets Dropped
+ uint32_t countDropped;
+ uint32_t countInterestsDropped;
+ uint32_t countObjectsDropped;
+ uint32_t countOtherDropped;
+
+ // Forwarding
+ uint32_t countInterestForwarded;
+ uint32_t countObjectsForwarded;
+
+ // Errors while forwarding
+ uint32_t countDroppedConnectionNotFound;
+ uint32_t countSendFailures;
+ uint32_t countDroppedNoRoute;
+
+ // Interest processing
+ uint32_t countInterestsAggregated;
+ uint32_t countInterestsRetransmitted;
+ uint32_t countInterestsSatisfiedFromStore;
+ uint32_t countInterestsExpired;
+
+ // Data processing
+ uint32_t countDroppedNoReversePath;
+ uint32_t countDataExpired;
+
+ // TODO(eloparco): Currently not used
+ // uint32_t countDroppedNoHopLimit;
+ // uint32_t countDroppedZeroHopLimitFromRemote;
+ // uint32_t countDroppedZeroHopLimitToRemote;
+} forwarder_stats_t;
+
+typedef struct
+{
+ uint32_t n_pit_entries;
+ uint32_t n_cs_entries;
+ uint32_t n_lru_evictions;
+} pkt_cache_stats_t;
+
+typedef struct
+{
+ forwarder_stats_t forwarder;
+ pkt_cache_stats_t pkt_cache;
+} hicn_light_stats_t;
+
+typedef struct
+{
+ uint32_t conn_id;
+ struct
+ {
+ uint32_t rx_pkts;
+ uint32_t rx_bytes;
+ uint32_t tx_pkts;
+ uint32_t tx_bytes;
+ } interests;
+ struct
+ {
+ uint32_t rx_pkts;
+ uint32_t rx_bytes;
+ uint32_t tx_pkts;
+ uint32_t tx_bytes;
+ } data;
+} connection_stats_t;
+
#endif /* HICN_BASE_H */
/*
diff --git a/lib/includes/hicn/common.h b/lib/includes/hicn/common.h
index 05f8ad95f..64aca8f1f 100644
--- a/lib/includes/hicn/common.h
+++ b/lib/includes/hicn/common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -36,59 +36,23 @@
#include <stdint.h>
#include <assert.h>
-/* Concise type definitions */
+#include <hicn/util/types.h>
-typedef uint64_t u64;
-typedef uint32_t u32;
-typedef uint16_t u16;
-typedef uint8_t u8;
+#define HICN_EXPECT_FALSE(x) __builtin_expect ((x), 1)
+#define HICN_EXPECT_TRUE(x) __builtin_expect ((x), 0)
+#define HICN_UNUSED(x) x __attribute__ ((unused))
-/*
- * Code annotations
- *
- * NOTE: these are defined by default in VPP.
- */
-
-#ifndef HICN_VPP_PLUGIN
-
-#define PREDICT_FALSE(x) (x)
-#define PREDICT_TRUE(x) (x)
-#define always_inline static inline
-#define static_always_inline static inline
-#define STRUCT_SIZE_OF(type, member) sizeof(((type *)0)->member)
-#define ASSERT
-
-#define STATIC_ASSERT(x)
-
-/* Architecture-dependent uword size */
-#if INTPTR_MAX == INT64_MAX
-#define log2_uword_bits 6
-#elif INTPTR_MAX == INT32_MAX
-#define log2_uword_bits 5
+#ifndef NDEBUG
+#define _ASSERT(x) assert (x)
#else
-#error "Impossible to detect architecture"
+#define _ASSERT(x) ((void) (x))
#endif
-#define uword_bits (1 << log2_uword_bits)
-
-/* Word types. */
-#if uword_bits == 64
-/* 64 bit word machines. */
-typedef u64 uword;
-#else
-/* 32 bit word machines. */
-typedef u32 uword;
-#endif
-
-typedef uword ip_csum_t;
-
-#endif /* ! HICN_VPP_PLUGIN */
-
/*
- * Windows compilers do not support named initilizers when .h files are included
- * inside C++ files. For readability, we either use the following macro, or
- * duplicate some code, with the intent of preserving those safeguards for
- * non-Windows platforms.
+ * Windows compilers do not support named initilizers when .h files are
+ * included inside C++ files. For readability, we either use the following
+ * macro, or duplicate some code, with the intent of preserving those
+ * safeguards for non-Windows platforms.
*/
#ifndef _WIN32
#define ATTR_INIT(key, value) .key = value
@@ -97,12 +61,12 @@ typedef uword ip_csum_t;
#endif
#ifdef _WIN32
- /* Endianness detection for Windows platforms */
+/* Endianness detection for Windows platforms */
#define __ORDER_LITTLE_ENDIAN__ 0x41424344UL
-#define __ORDER_BIG_ENDIAN__ 0x44434241UL
-#define __BYTE_ORDER__ ('ABCD')
+#define __ORDER_BIG_ENDIAN__ 0x44434241UL
+#define __BYTE_ORDER__ ('ABCD')
- /* Windows compatibility headers */
+/* Windows compatibility headers */
#define WIN32_LEAN_AND_MEAN
#ifndef NOMINMAX
#define NOMINMAX
@@ -116,10 +80,10 @@ typedef uword ip_csum_t;
#define strdup _strdup
#define __attribute__(A)
-#ifndef IOVEC
+#ifndef IOVEC
#define IOVEC
#define UIO_MAXIOV 16
-#define IOV_MAX UIO_MAXIOV
+#define IOV_MAX UIO_MAXIOV
struct iovec
{
void *iov_base;
@@ -132,66 +96,20 @@ struct iovec
* Portable attribute packed.
*/
#ifndef _WIN32
-#define PACKED( __Declaration__ ) __Declaration__ __attribute__((__packed__))
+#define PACKED(__Declaration__) __Declaration__ __attribute__ ((__packed__))
#else
-#define PACKED( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) )
+#define PACKED(__Declaration__) \
+ __pragma (pack (push, 1)) __Declaration__ __pragma (pack (pop))
#endif
-
/*
* IP address types
*/
-#ifdef HICN_VPP_PLUGIN
-
-#include <vnet/ip/ip4_packet.h> // ip4_address_t
-#include <vnet/ip/ip6_packet.h> // ip6_address_t
-
-#if __GNUC__ >= 9
-#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
-#endif
-
-#include <vnet/ip/ip46_address.h>
-
-#if __GNUC__ >= 9
-#pragma GCC diagnostic pop
-#endif
-
-#else
-
-
#ifndef _WIN32
#include <netinet/in.h>
#endif
-typedef union
-{
- u32 as_u32;
- struct in_addr as_inaddr;
-} ip4_address_t;
-
-typedef union
-{
- u64 as_u64[2];
- u32 as_u32[4];
- u8 as_u8[16];
- struct in6_addr as_in6addr;
-} ip6_address_t;
-
-typedef union
-{
- struct
- {
- u32 pad[3];
- ip4_address_t ip4;
- };
- ip6_address_t ip6;
-} ip46_address_t;
-
-#define ip46_address_is_ip4(ip46) (((ip46)->pad[0] | (ip46)->pad[1] | (ip46)->pad[2]) == 0)
-
-#endif /* ! HICN_VPP_PLUGIN */
-
/**
* @brief Returns the family of an IP address
* @param [in] ip_address - IP address in presentation format
@@ -215,33 +133,33 @@ int get_addr_family (const char *ip_address);
* borrow this code here.
*/
-static_always_inline u16
-ip_csum_fold (ip_csum_t c)
+static inline u16
+ip_csum_fold (hicn_ip_csum_t c)
{
/* Reduce to 16 bits. */
#if uword_bits == 64
- c = (c & (ip_csum_t) 0xffffffff) + (c >> (ip_csum_t) 32);
+ c = (c & (hicn_ip_csum_t) 0xffffffff) + (c >> (hicn_ip_csum_t) 32);
c = (c & 0xffff) + (c >> 16);
#endif
c = (c & 0xffff) + (c >> 16);
c = (c & 0xffff) + (c >> 16);
- return (u16)c;
+ return (u16) c;
}
-static_always_inline ip_csum_t
-ip_csum_with_carry (ip_csum_t sum, ip_csum_t x)
+static inline hicn_ip_csum_t
+ip_csum_with_carry (hicn_ip_csum_t sum, hicn_ip_csum_t x)
{
- ip_csum_t t = sum + x;
+ hicn_ip_csum_t t = sum + x;
return t + (t < x);
}
/* Update checksum changing field at even byte offset from x -> 0. */
-static_always_inline ip_csum_t
-ip_csum_add_even (ip_csum_t c, ip_csum_t x)
+static inline hicn_ip_csum_t
+ip_csum_add_even (hicn_ip_csum_t c, hicn_ip_csum_t x)
{
- ip_csum_t d;
+ hicn_ip_csum_t d;
d = c - x;
@@ -252,19 +170,17 @@ ip_csum_add_even (ip_csum_t c, ip_csum_t x)
}
/* Update checksum changing field at even byte offset from 0 -> x. */
-static_always_inline ip_csum_t
-ip_csum_sub_even (ip_csum_t c, ip_csum_t x)
+static inline hicn_ip_csum_t
+ip_csum_sub_even (hicn_ip_csum_t c, hicn_ip_csum_t x)
{
return ip_csum_with_carry (c, x);
}
+#endif /* ! HICN_VPP_PLUGIN */
+
u32 cumulative_hash32 (const void *data, size_t len, u32 lastValue);
u32 hash32 (const void *data, size_t len);
-u64 cumulative_hash64 (const void *data, size_t len, u64 lastValue);
-u64 hash64 (const void *data, size_t len);
-void hicn_packet_dump (const uint8_t * buffer, size_t len);
-
-#endif /* ! HICN_VPP_PLUGIN */
+void hicn_packet_dump (const uint8_t *buffer, size_t len);
/**
* @brief Computes buffer checksum
@@ -273,7 +189,7 @@ void hicn_packet_dump (const uint8_t * buffer, size_t len);
* @param [in] init - Checksum initial value
* @return Checksum of specified buffer
*/
-always_inline u16
+static inline u16
csum (const void *addr, size_t size, u16 init)
{
u32 sum = init;
@@ -291,7 +207,7 @@ csum (const void *addr, size_t size, u16 init)
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
- return (u16) ~ sum;
+ return (u16) ~sum;
}
/*
@@ -305,19 +221,110 @@ csum (const void *addr, size_t size, u16 init)
* Query IP version from packet (either 4 or 6)
* (version is located as same offsets in both protocol headers)
*/
-#define HICN_IP_VERSION(packet) ((hicn_header_t *)packet)->v4.ip.version
+typedef struct
+{
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ u8 dummy : 4;
+ u8 version : 4;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ u8 version : 4;
+ u8 dummy : 4;
+#else
+#error "Unsupported endianness"
+#endif
+} ip_version_t;
+#define HICN_IP_VERSION(packet) ((ip_version_t *) packet)->version
/*
- * ntohll / htonll allows byte swapping for 64 bits integers
+ * Endianess utils
*/
-#ifndef htonll
-#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
+
+#if (__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)
+#define HICN_LITTLE_ENDIAN_ARCH
+#else
+#define HICN_BIG_ENDIAN_ARCH
#endif
-#ifndef ntohll
-#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
+static inline u16
+hicn_conditional_swap_u16 (u16 value)
+{
+#ifdef HICN_LITTLE_ENDIAN_ARCH
+ value = __builtin_bswap16 (value);
#endif
+ return value;
+}
+
+static inline u32
+hicn_conditional_swap_u32 (u32 value)
+{
+#ifdef HICN_LITTLE_ENDIAN_ARCH
+ value = __builtin_bswap32 (value);
+#endif
+
+ return value;
+}
+
+static inline u64
+hicn_conditional_swap_u64 (u64 value)
+{
+#ifdef HICN_LITTLE_ENDIAN_ARCH
+ value = __builtin_bswap64 (value);
+#endif
+
+ return value;
+}
+
+#define hicn_net_to_host_16(x) hicn_conditional_swap_u16 ((u16) (x))
+#define hicn_net_to_host_32(x) hicn_conditional_swap_u32 ((u32) (x))
+#define hicn_net_to_host_64(x) hicn_conditional_swap_u64 ((u64) (x))
+
+#define hicn_host_to_net_16(x) hicn_conditional_swap_u16 ((u16) (x))
+#define hicn_host_to_net_32(x) hicn_conditional_swap_u32 ((u32) (x))
+#define hicn_host_to_net_64(x) hicn_conditional_swap_u64 ((u64) (x))
+
+#define hicn_round_pow2(x, pow2) (((x) + (pow2) -1) & ~((pow2) -1))
+
+#define _SIZEOF_ALIGNED(x, size) hicn_round_pow2 (sizeof (x), size)
+#define SIZEOF_ALIGNED(x) _SIZEOF_ALIGNED (x, sizeof (void *))
+
+/* Definitions for builtins unavailable on MSVC */
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <intrin.h>
+
+uint32_t __inline __builtin_ctz (uint32_t value)
+{
+ uint32_t trailing_zero = 0;
+ if (_BitScanForward (&trailing_zero, value))
+ return trailing_zero;
+ else
+ return 32;
+}
+
+uint32_t __inline __builtin_clz (uint32_t value)
+{
+ uint32_t leading_zero = 0;
+ if (_BitScanReverse (&leading_zero, value))
+ return 31 - leading_zero;
+ else
+ return 32;
+}
+
+uint32_t __inline __builtin_clzl2 (uint64_t value)
+{
+ uint32_t leading_zero = 0;
+ if (_BitScanReverse64 (&leading_zero, value))
+ return 63 - leading_zero;
+ else
+ return 64;
+}
+
+#define __builtin_clzl __builtin_clzll
+#endif
+
+#define next_pow2(x) (x <= 1 ? 1 : 1ul << (64 - __builtin_clzl (x - 1)))
+#define _unused(x) ((void) (x))
+
#endif /* HICN_COMMON_H */
/*
diff --git a/lib/includes/hicn/compat.h b/lib/includes/hicn/compat.h
deleted file mode 100644
index 486c82348..000000000
--- a/lib/includes/hicn/compat.h
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * Copyright (c) 2017-2019 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 compat.h
- * @brief Implementation of the compatibility layer.
- *
- * The structure of the core API has evolved to support operations of a variety
- * of packet formats in addition to IPv4/TCP and IPv6/TCP, namely with the use
- * of ICMP for signalization and AH headers for integrity. The new API format
- * has been designed to scale better with the multiplicity of packet formats,
- * and provide a unified interface on top. We maintain an interface for the
- * former API in this file, which mainly acts as a wrapper on top of new calls.
- */
-#ifndef HICN_COMPAT_H
-#define HICN_COMPAT_H
-
-#include "common.h"
-#include "header.h"
-#include "name.h"
-
-/* HICN format options */
-#define HFO_INET 1 << 0
-#define HFO_INET6 1 << 1
-#define HFO_TCP 1 << 2
-#define HFO_ICMP 1 << 3
-#define HFO_AH 1 << 4
-
-#define _is_ipv4(format) ((format & HFO_INET))
-#define _is_ipv6(format) ((format & HFO_INET6) >> 1)
-#define _is_tcp(format) ((format & HFO_TCP) >> 2)
-#define _is_icmp(format) ((format & HFO_ICMP) >> 3)
-#define _is_ah(format) ((format & HFO_AH) >> 4)
-
-typedef enum
-{
- HF_UNSPEC = 0,
- HF_INET_TCP = HFO_INET | HFO_TCP,
- HF_INET6_TCP = HFO_INET6 | HFO_TCP,
- HF_INET_ICMP = HFO_INET | HFO_ICMP,
- HF_INET6_ICMP = HFO_INET6 | HFO_ICMP,
- HF_INET_TCP_AH = HFO_INET | HFO_TCP | HFO_AH,
- HF_INET6_TCP_AH = HFO_INET6 | HFO_TCP | HFO_AH,
- HF_INET_ICMP_AH = HFO_INET | HFO_ICMP | HFO_AH,
- HF_INET6_ICMP_AH = HFO_INET6 | HFO_ICMP | HFO_AH,
-} hicn_format_t;
-
-/**
- * Minimum required header length to determine the type and length of a
- * supposed hICN packet. This should be equal to the maximum value over all
- * possible hICN packet formats, and less than the minimum possible IP packet
- * size.
- */
-#define HICN_V6_MIN_HDR_LEN 6 /* bytes */
-#define HICN_V4_MIN_HDR_LEN 4 /* bytes */
-
-// #define HICN_MIN_HDR_LEN ((HICN_V6_MIN_HDR_LEN > HICN_V4_MIN_HDR_LEN) ?
-// HICN_V6_MIN_HDR_LEN : HICN_V4_MIN_HDR_LEN)
-#define HICN_MIN_HDR_LEN HICN_V6_MIN_HDR_LEN
-
-/**
- * @brief Parse packet headers and return hICN format
- * @param [in] format - hICN Format
- * @param [in, out] packet - Buffer containing the hICN header to be
- * initialized
- * @return hICN error code
- */
-int hicn_packet_init_header (hicn_format_t format, hicn_header_t *packet);
-
-/**
- * @brief Parse packet headers and return hICN format
- * @param [in] h - hICN header
- * @param [out] format - hICN format
- * @return hICN error code
- */
-int hicn_packet_get_format (const hicn_header_t *packet,
- hicn_format_t *format);
-
-/**
- * @brief Update checksums in packet headers
- * @param [in] format - hICN format
- * @param [in,out] packet - packet header
- * @return hICN error code
- */
-int hicn_packet_compute_checksum (hicn_format_t format, hicn_header_t *packet);
-
-/**
- * @brief compute the checksum of the packet header, adding init_sum to the
- * final value
- * @param [in] format - hICN format
- * @param [in,out] packet - packet header
- * @param [in] init_sum - value to add to the final checksum
- * @return hICN error code
- */
-int hicn_packet_compute_header_checksum (hicn_format_t format,
- hicn_header_t *packet, u16 init_sum);
-
-/**
- * @brief Verify checksums in packet headers
- * @param [in] format - hICN format
- * @param [in,out] packet - packet header
- * @return hICN error code
- */
-int hicn_packet_check_integrity_no_payload (hicn_format_t format,
- hicn_header_t *packet,
- u16 init_sum);
-
-// this is not accounted here
-/**
- * @brief Return total length of hicn headers (but signature payload)
- * @param [in] format - hICN format
- * @param [out] header_length - Total length of headers
- * @return hICN error code
- */
-int hicn_packet_get_header_length_from_format (hicn_format_t format,
- size_t *header_length);
-
-/**
- * @brief Return total length of hicn headers (before payload)
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [out] header_length - Total length of headers
- * @return hICN error code
- */
-int hicn_packet_get_header_length (hicn_format_t format,
- const hicn_header_t *packet,
- size_t *header_length);
-
-/**
- * @brief Return payload length
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [out] payload_length - payload length
- * @return hICN error code
- */
-int hicn_packet_get_payload_length (hicn_format_t format,
- const hicn_header_t *packet,
- size_t *payload_length);
-
-/**
- * @brief Sets payload length
- * @param [in] format - hICN format
- * @param [in,out] packet - packet header
- * @param [in] payload_length - payload length
- * @return hICN error code
- */
-int hicn_packet_set_payload_length (hicn_format_t format,
- hicn_header_t *packet,
- const size_t payload_length);
-
-/**
- * @brief Compare two hICN packets
- * @param [in] packet_1 - First packet
- * @param [in] packet_2 - Second packet
- * @return 0 if both packets are considered equal, any other value otherwise.
- */
-int hicn_packet_compare (const hicn_header_t *packet1,
- const hicn_header_t *packet2);
-
-/**
- * @brief Retrieve the name of an interest/data packet
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [out] name - name holding the result
- * @param [in] is_interest - Flag to determine whether it is an interest (1) or
- * data packet (0)
- * @return hICN error code
- */
-int hicn_packet_get_name (hicn_format_t format, const hicn_header_t *packet,
- hicn_name_t *name, u8 is_interest);
-
-/**
- * @brief Sets the name of an interest/data packet
- * @param [in] format - hICN format
- * @param [in,out] packet - packet header
- * @param [in] name - name to set into packet
- * @param [in] is_interest - Flag to determine whether it is an interest (1) or
- * data packet (0)
- * @return hICN error code
- */
-int hicn_packet_set_name (hicn_format_t format, hicn_header_t *packet,
- const hicn_name_t *name, u8 is_interest);
-
-/**
- * @brief Sets the payload of a packet
- * @param [in] format - hICN format
- * @param [in,out] packet - packet header
- * @param [in] payload - payload to set
- * @param [in] payload_length - size of the payload to set
- * @return hICN error code
- *
- * NOTE:
- * - The buffer holding payload is assumed sufficiently large
- * - This function updates header fields with the new length, but no checksum.
- */
-int hicn_packet_set_payload (hicn_format_t format, hicn_header_t *packet,
- const u8 *payload, u16 payload_length);
-
-/**
- * @brief Retrieves the payload of a packet
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [out] payload - pointer to buffer for storing the result
- * @param [out] payload_length - size of the retreived payload
- * @param [in] hard_copy - Flag : if true (eg. 1), a copy of the payload is
- * made into the payload buffer, otherwise (0) the pointer is changed to point
- * to the payload offset in the packet.
- * @return hICN error code
- *
- * NOTE:
- * - The buffer holding payload is assumed sufficiently large
- */
-int hicn_packet_get_payload (hicn_format_t format, const hicn_header_t *packet,
- u8 **payload, size_t *payload_size,
- bool hard_copy);
-
-/**
- * @brief Retrieve the locator of an interest / data packet
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [out] ip_address - retrieved locator
- * @param [in] is_interest - Flag to determine whether it is an interest (1) or
- * data packet (0)
- * @return hICN error code
- */
-int hicn_packet_get_locator (hicn_format_t format, const hicn_header_t *packet,
- ip_address_t *prefix, bool is_interest);
-
-/**
- * @brief Sets the locator of an interest / data packet
- * @param [in] format - hICN format
- * @param [in,out] packet - packet header
- * @param [out] ip_address - retrieved locator
- * @param [in] is_interest - Flag to determine whether it is an interest (1) or
- * data packet (0)
- * @return hICN error code
- */
-int hicn_packet_set_locator (hicn_format_t format, hicn_header_t *packet,
- const ip_address_t *prefix, bool is_interest);
-
-/**
- * @brief Retrieves the signature size
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [out] bytes - Retrieved signature size
- * @return hICN error code
- */
-int hicn_packet_get_signature_size (hicn_format_t format,
- const hicn_header_t *packet,
- size_t *bytes);
-
-/**
- * @brief Sets the signature size
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [in] bytes - Retrieved signature size
- * @return hICN error code
- */
-int hicn_packet_set_signature_size (hicn_format_t format,
- hicn_header_t *packet, size_t bytes);
-
-/**
- * @brief Sets the signature size
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [in] signature_timestamp - Signature timestamp to set
- * @return hICN error code
- */
-int hicn_packet_set_signature_timestamp (hicn_format_t format,
- hicn_header_t *h,
- uint64_t signature_timestamp);
-
-/**
- * @brief Sets the signature size
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [out] signature_timestamp - Retrieved signature timestamp
- * @return hICN error code
- */
-int hicn_packet_get_signature_timestamp (hicn_format_t format,
- const hicn_header_t *h,
- uint64_t *signature_timestamp);
-
-/**
- * @brief Sets the signature size
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [in] validation_algorithm - Validation algorithm to set
- * @return hICN error code
- */
-int hicn_packet_set_validation_algorithm (hicn_format_t format,
- hicn_header_t *h,
- uint8_t validation_algorithm);
-
-/**
- * @brief Sets the signature size
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [out] validation_algorithm - Retrieved validation algorithm
- * @return hICN error code
- */
-int hicn_packet_get_validation_algorithm (hicn_format_t format,
- const hicn_header_t *h,
- uint8_t *validation_algorithm);
-
-/**
- * @brief Sets the signature size
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [in] key_id - Key id to set
- * @return hICN error code
- */
-int hicn_packet_set_key_id (hicn_format_t format, hicn_header_t *h,
- uint8_t *key_id);
-
-/**
- * @brief Sets the signature size
- * @param [in] format - hICN format
- * @param [in] packet - packet header
- * @param [out] key_id - Retrieved key id
- * @return hICN error code
- */
-int hicn_packet_get_key_id (hicn_format_t format, hicn_header_t *h,
- uint8_t **key_id, uint8_t *key_id_length);
-
-/**
- * @brief Retrieves the packet hop limit
- * @param [in] packet - packet header
- * @param [out] hops - Retrieved hop limit
- * @return hICN error code
- */
-int hicn_packet_get_hoplimit (const hicn_header_t *packet, u8 *hops);
-
-/**
- * @brief Sets the packet hop limit
- * @param [in] packet - packet header
- * @param [in] hops - Hop limit to set
- * @return hICN error code
- */
-int hicn_packet_set_hoplimit (hicn_header_t *packet, u8 hops);
-
-int hicn_packet_copy_header (hicn_format_t format, const hicn_header_t *packet,
- hicn_header_t *destination, bool copy_ah);
-
-int hicn_packet_get_lifetime (const hicn_header_t *packet, u32 *lifetime);
-int hicn_packet_set_lifetime (hicn_header_t *packet, u32 lifetime);
-int hicn_packet_get_reserved_bits (const hicn_header_t *packet,
- u8 *reserved_bits);
-int hicn_packet_set_reserved_bits (hicn_header_t *packet,
- const u8 reserved_bits);
-int hicn_packet_get_payload_type (const hicn_header_t *packet,
- hicn_payload_type_t *payload_type);
-int hicn_packet_set_payload_type (hicn_header_t *packet,
- const hicn_payload_type_t payload_type);
-
-int hicn_packet_set_syn (hicn_format_t format, hicn_header_t *packet);
-int hicn_packet_reset_syn (hicn_format_t format, hicn_header_t *packet);
-int hicn_packet_test_syn (hicn_format_t format, const hicn_header_t *packet,
- bool *flag);
-int hicn_packet_set_ack (hicn_format_t format, hicn_header_t *packet);
-int hicn_packet_reset_ack (hicn_format_t format, hicn_header_t *packet);
-int hicn_packet_test_ack (hicn_format_t format, const hicn_header_t *packet,
- bool *flag);
-int hicn_packet_set_rst (hicn_format_t format, hicn_header_t *packet);
-int hicn_packet_reset_rst (hicn_format_t format, hicn_header_t *packet);
-int hicn_packet_test_rst (hicn_format_t format, const hicn_header_t *packet,
- bool *flag);
-int hicn_packet_set_fin (hicn_format_t format, hicn_header_t *packet);
-int hicn_packet_reset_fin (hicn_format_t format, hicn_header_t *packet);
-int hicn_packet_test_fin (hicn_format_t format, const hicn_header_t *packet,
- bool *flag);
-int hicn_packet_set_ece (hicn_format_t format, hicn_header_t *packet);
-int hicn_packet_reset_ece (hicn_format_t format, hicn_header_t *packet);
-int hicn_packet_test_ece (hicn_format_t format, const hicn_header_t *packet,
- bool *flag);
-
-int hicn_packet_set_src_port (hicn_format_t format, hicn_header_t *packet,
- u16 src_port);
-int hicn_packet_get_src_port (hicn_format_t format,
- const hicn_header_t *packet, u16 *src_port);
-int hicn_packet_set_dst_port (hicn_format_t format, hicn_header_t *packet,
- u16 dst_port);
-int hicn_packet_get_dst_port (hicn_format_t format,
- const hicn_header_t *packet, u16 *dst_port);
-int hicn_packet_get_signature (hicn_format_t format, hicn_header_t *packet,
- uint8_t **sign_buf);
-
-/* Interest */
-int hicn_interest_get_name (hicn_format_t format,
- const hicn_header_t *interest, hicn_name_t *name);
-int hicn_interest_set_name (hicn_format_t format, hicn_header_t *interest,
- const hicn_name_t *name);
-int hicn_interest_get_locator (hicn_format_t format,
- const hicn_header_t *interest,
- ip_address_t *prefix);
-int hicn_interest_set_locator (hicn_format_t format, hicn_header_t *interest,
- const ip_address_t *prefix);
-int hicn_interest_compare (const hicn_header_t *interest_1,
- const hicn_header_t *interest_2);
-int hicn_interest_set_lifetime (hicn_header_t *interest, u32 lifetime);
-int hicn_interest_get_lifetime (const hicn_header_t *interest, u32 *lifetime);
-int hicn_interest_get_header_length (hicn_format_t format,
- const hicn_header_t *interest,
- size_t *header_length);
-int hicn_interest_get_payload_length (hicn_format_t format,
- const hicn_header_t *interest,
- size_t *payload_length);
-int hicn_interest_set_payload (hicn_format_t format, hicn_header_t *interest,
- const u8 *payload, size_t payload_length);
-int hicn_interest_get_payload (hicn_format_t format,
- const hicn_header_t *interest, u8 **payload,
- size_t *payload_size, bool hard_copy);
-int hicn_interest_reset_for_hash (hicn_format_t format, hicn_header_t *packet);
-
-/* Data */
-
-int hicn_data_get_name (hicn_format_t format, const hicn_header_t *data,
- hicn_name_t *name);
-int hicn_data_set_name (hicn_format_t format, hicn_header_t *data,
- const hicn_name_t *name);
-int hicn_data_get_locator (hicn_format_t format, const hicn_header_t *data,
- ip_address_t *prefix);
-int hicn_data_set_locator (hicn_format_t format, hicn_header_t *data,
- const ip_address_t *prefix);
-int hicn_data_compare (const hicn_header_t *data_1,
- const hicn_header_t *data_2);
-int hicn_data_get_expiry_time (const hicn_header_t *data, u32 *expiry_time);
-int hicn_data_set_expiry_time (hicn_header_t *data, u32 expiry_time);
-int hicn_data_get_header_length (hicn_format_t format, hicn_header_t *data,
- size_t *header_length);
-int hicn_data_get_payload_length (hicn_format_t format,
- const hicn_header_t *data,
- size_t *payload_length);
-int hicn_data_get_path_label (const hicn_header_t *data, u32 *path_label);
-int hicn_data_set_path_label (hicn_header_t *data, u32 path_label);
-int hicn_data_get_payload (hicn_format_t format, const hicn_header_t *data,
- u8 **payload, size_t *payload_size, bool hard_copy);
-int hicn_data_set_payload (hicn_format_t format, hicn_header_t *data,
- const u8 *payload, size_t payload_length);
-int hicn_data_get_payload_type (const hicn_header_t *data,
- hicn_payload_type_t *payload_type);
-int hicn_data_set_payload_type (hicn_header_t *data,
- hicn_payload_type_t payload_type);
-int hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t *packet);
-int hicn_packet_get_signature_gap (hicn_format_t format,
- const hicn_header_t *h, uint8_t *bytes);
-int hicn_packet_set_signature_gap (hicn_format_t format, hicn_header_t *h,
- uint8_t bytes);
-#endif /* HICN_COMPAT_H */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/lib/includes/hicn/error.h b/lib/includes/hicn/error.h
index 9303aeb7e..9926c9cd8 100644
--- a/lib/includes/hicn/error.h
+++ b/lib/includes/hicn/error.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -24,21 +24,22 @@
* Error definitions
******************************************************************************/
-#define foreach_libhicn_error \
-_(NONE, 0, "OK") \
-_(UNSPECIFIED, 128, "Unspecified Error") \
-_(NOT_IMPLEMENTED, 180, "Function not yet implemented") \
-_(NOT_HICN, 202, "Non hICN packet") \
-_(UNKNOWN_ADDRESS, 210, "Unknown address") \
-_(INVALID_PARAMETER, 220, "Invalid parameter") \
-_(INVALID_IP_ADDRESS, 221, "Invalid IP address") \
-_(CORRUPTED_PACKET, 222, "Corrupted packet ") \
-_(REWRITE_CKSUM_REQUIRED, 223, "Incremental csum calculation error: cksum required.") \
-_(UNEXPECTED, 298, "Unexpected error")
+#define foreach_libhicn_error \
+ _ (NONE, 0, "OK") \
+ _ (UNSPECIFIED, 128, "Unspecified Error") \
+ _ (NOT_IMPLEMENTED, 180, "Function not yet implemented") \
+ _ (NOT_HICN, 202, "Non hICN packet") \
+ _ (UNKNOWN_ADDRESS, 210, "Unknown address") \
+ _ (INVALID_PARAMETER, 220, "Invalid parameter") \
+ _ (INVALID_IP_ADDRESS, 221, "Invalid IP address") \
+ _ (CORRUPTED_PACKET, 222, "Corrupted packet ") \
+ _ (REWRITE_CKSUM_REQUIRED, 223, \
+ "Incremental csum calculation error: cksum required.") \
+ _ (UNEXPECTED, 298, "Unexpected error")
typedef enum
{
-#define _(a,b,c) HICN_LIB_ERROR_##a = (-b),
+#define _(a, b, c) HICN_LIB_ERROR_##a = (-b),
foreach_libhicn_error
#undef _
HICN_LIB_N_ERROR,
@@ -46,7 +47,9 @@ typedef enum
extern const char *HICN_LIB_ERROR_STRING[];
-#define hicn_strerror(errno) (char *)(HICN_LIB_ERROR_STRING[-errno])
+#define HICN_LIB_IS_ERROR(rc) (rc < 0)
+
+#define hicn_strerror(errno) (char *) (HICN_LIB_ERROR_STRING[-errno])
#endif /* HICN_ERROR_H */
diff --git a/lib/includes/hicn/face.h b/lib/includes/hicn/face.h
new file mode 100644
index 000000000..fbdacec5f
--- /dev/null
+++ b/lib/includes/hicn/face.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file face.h
+ * \brief Face abstraction
+ */
+#ifndef HICN_FACE_H
+#define HICN_FACE_H
+
+#ifndef SPACES
+#define SPACES(x) x
+#endif
+#ifndef SPACE
+#define SPACE 1
+#endif
+#ifndef NULLTERM
+#define NULLTERM 1
+#endif
+
+#include <hicn/policy.h>
+
+#include <hicn/util/ip_address.h>
+
+/* Netdevice type */
+
+#include <net/if.h> // IFNAMSIZ
+#include "base.h"
+
+#define foreach_netdevice_type \
+ _ (UNDEFINED) \
+ _ (LOOPBACK) \
+ _ (WIRED) \
+ _ (WIFI) \
+ _ (CELLULAR) \
+ _ (VPN) \
+ _ (MEMIF) \
+ _ (N)
+
+#define MAXSZ_NETDEVICE_TYPE_ 9
+#define MAXSZ_NETDEVICE_TYPE MAXSZ_NETDEVICE_TYPE_ + NULLTERM
+
+typedef enum
+{
+#define _(x) NETDEVICE_TYPE_##x,
+ foreach_netdevice_type
+#undef _
+} netdevice_type_t;
+
+typedef uint32_t netdevice_flags_t;
+#define NETDEVICE_FLAGS_EMPTY 0
+#define netdevice_flags_clear(F) (F = 0)
+#define netdevice_flags_add(F, T) ((F) |= 1 << (T))
+#define netdevice_flags_remove(F, T) ((F) &= ~(1 << (T)))
+#define netdevice_flags_has(F, T) ((F) & (1 << (T)))
+
+extern const char *_netdevice_type_str[];
+#define netdevice_type_str(x) _netdevice_type_str[x]
+
+#define INVALID_NETDEVICE_ID ~0
+
+/* Netdevice */
+
+/**
+ * \brief Netdevice type
+ *
+ * NOTE
+ * - This struct cannot be made opaque as it is currently part of face_t
+ * - We recommand using the API as to keep redundant attributes consistent
+ */
+
+typedef struct
+{
+ u32 index;
+ char name[IFNAMSIZ];
+} netdevice_t;
+
+#define NETDEVICE_EMPTY \
+ (netdevice_t) \
+ { \
+ .index = 0, .name = { 0 } \
+ }
+
+netdevice_t *netdevice_create_from_index (u32 index);
+netdevice_t *netdevice_create_from_name (const char *name);
+#define netdevice_initialize_from_index netdevice_set_index
+#define netdevice_initialize_from_name netdevice_set_name
+void netdevice_free (netdevice_t *netdevice);
+int netdevice_get_index (const netdevice_t *netdevice, u32 *index);
+int netdevice_set_index (netdevice_t *netdevice, u32 index);
+int netdevice_get_name (const netdevice_t *netdevice, const char **name);
+int netdevice_set_name (netdevice_t *netdevice, const char *name);
+int netdevice_update_index (netdevice_t *netdevice);
+int netdevice_update_name (netdevice_t *netdevice);
+int netdevice_cmp (const netdevice_t *nd1, const netdevice_t *nd2);
+bool netdevice_is_empty (const netdevice_t *netdevice);
+
+#define NETDEVICE_UNDEFINED_INDEX 0
+
+/* Face state */
+
+#define foreach_face_state \
+ _ (UNDEFINED) \
+ _ (DOWN) \
+ _ (UP) \
+ _ (N)
+
+#define MAXSZ_FACE_STATE_ 9
+#define MAXSZ_FACE_STATE MAXSZ_FACE_STATE_ + 1
+
+typedef enum
+{
+#define _(x) FACE_STATE_##x,
+ foreach_face_state
+#undef _
+} face_state_t;
+
+extern const char *_face_state_str[];
+
+#define face_state_str(x) _face_state_str[x]
+
+/* Face type */
+
+#define foreach_face_type \
+ _ (UNDEFINED) \
+ _ (HICN) \
+ _ (HICN_LISTENER) \
+ _ (TCP) \
+ _ (TCP_LISTENER) \
+ _ (UDP) \
+ _ (UDP_LISTENER) \
+ _ (N)
+
+#define MAXSZ_FACE_TYPE_ 13
+#define MAXSZ_FACE_TYPE MAXSZ_FACE_TYPE_ + 1
+
+typedef enum
+{
+#define _(x) FACE_TYPE_##x,
+ foreach_face_type
+#undef _
+} face_type_t;
+
+typedef enum
+{
+ FACE_PROTOCOL_HICN,
+ FACE_PROTOCOL_UDP,
+ FACE_PROTOCOL_TCP,
+ FACE_PROTOCOL_UNKNOWN,
+} face_protocol_t;
+
+#define face_type_is_valid(face_type) \
+ (((face_type) >= FACE_TYPE_UNDEFINED) && (face_type < FACE_TYPE_N))
+#define face_type_is_defined(face_type) \
+ (((face_type) > FACE_TYPE_UNDEFINED) && (face_type < FACE_TYPE_N))
+
+extern const char *_face_type_str[];
+#define face_type_str(x) _face_type_str[x]
+
+face_type_t face_type_from_str (const char *str);
+
+#ifdef WITH_POLICY
+#define MAXSZ_FACE_ \
+ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_URL_ + 2 * MAXSZ_FACE_STATE_ + \
+ MAXSZ_POLICY_TAGS_ + 7
+#else
+#define MAXSZ_FACE_ \
+ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_URL_ + 2 * MAXSZ_FACE_STATE_ + 4
+#endif /* WITH_POLICY */
+#define MAXSZ_FACE MAXSZ_FACE_ + 1
+
+/* Face */
+
+typedef u32 face_id_t;
+#define INVALID_FACE_ID ~0
+
+typedef struct
+{
+ face_id_t id;
+ char name[SYMBOLIC_NAME_LEN];
+ face_type_t type;
+ face_state_t admin_state;
+ face_state_t state;
+#ifdef WITH_POLICY
+ uint32_t priority;
+ policy_tags_t tags; /**< \see policy_tag_t */
+#endif /* WITH_POLICY */
+
+ /*
+ * Depending on the face type, some of the following fields will be unused
+ */
+ netdevice_t netdevice;
+ int family; /* To access family independently of face type */
+ hicn_ip_address_t local_addr;
+ hicn_ip_address_t remote_addr;
+ u16 local_port;
+ u16 remote_port;
+} face_t;
+
+int face_initialize (face_t *face);
+int face_initialize_udp (face_t *face, const char *interface_name,
+ const hicn_ip_address_t *local_addr, u16 local_port,
+ const hicn_ip_address_t *remote_addr, u16 remote_port,
+ int family);
+int face_initialize_udp_sa (face_t *face, const char *interface_name,
+ const struct sockaddr *local_addr,
+ const struct sockaddr *remote_addr);
+
+face_t *face_create ();
+face_t *face_create_udp (const char *interface_name,
+ const hicn_ip_address_t *local_addr, u16 local_port,
+ const hicn_ip_address_t *remote_addr, u16 remote_port,
+ int family);
+face_t *face_create_udp_sa (const char *interface_name,
+ const struct sockaddr *local_addr,
+ const struct sockaddr *remote_addr);
+
+int face_finalize (face_t *face);
+
+void face_free (face_t *face);
+
+typedef int (*face_cmp_t) (const face_t *f1, const face_t *f2);
+
+int face_cmp (const face_t *f1, const face_t *f2);
+
+size_t face_snprintf (char *s, size_t size, const face_t *face);
+
+policy_tags_t face_get_tags (const face_t *face);
+int face_set_tags (face_t *face, policy_tags_t tags);
+
+face_protocol_t get_protocol (face_type_t face_type);
+
+#endif /* HICN_FACE_H */
diff --git a/lib/includes/hicn/header.h b/lib/includes/hicn/header.h
deleted file mode 100644
index b21fe5c84..000000000
--- a/lib/includes/hicn/header.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2017-2019 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 header.h
- * @brief hICN header data structures.
- *
- * NOTE: These structures are used as convenient facade for accessing
- * the encapsulated headers. They are not written taking compiler padding
- * into account, then a sizeof() on these struct could not give the expected
- * result. For accessing the size of the hicn headers use the macros at the end of
- * this file.
- */
-
-#ifndef HICN_HEADER_H
-#define HICN_HEADER_H
-
-#include "common.h"
-#include "protocol.h"
-
-typedef struct
-{
- _ipv6_header_t ip;
- union
- {
- _tcp_header_t tcp;
- _icmp_header_t icmp;
- _icmp_wldr_header_t wldr;
- };
-} hicn_v6_hdr_t;
-
-typedef struct
-{
- _ipv6_header_t ip;
- union
- {
- struct
- {
- _tcp_header_t tcp;
- _ah_header_t ah;
- };
- struct
- {
- _icmp_header_t icmp;
- _ah_header_t icmp_ah;
- };
- };
-} hicn_v6ah_hdr_t;
-
-typedef struct
-{
- _ipv4_header_t ip;
- union
- {
- _tcp_header_t tcp;
- _icmp_header_t icmp;
- _icmp_wldr_header_t wldr;
- };
-} hicn_v4_hdr_t;
-
-typedef struct
-{
- _ipv4_header_t ip;
- union
- {
- struct
- {
- _tcp_header_t tcp;
- _ah_header_t ah;
- };
- struct
- {
- _icmp_header_t icmp;
- _ah_header_t icmp_ah;
- };
- };
-} hicn_v4ah_hdr_t;
-
-typedef union
-{
- /* To deprecate as redundant with hicn_type_t */
- hicn_v6_hdr_t v6;
- hicn_v6ah_hdr_t v6ah;
- hicn_v4_hdr_t v4;
- hicn_v4ah_hdr_t v4ah;
-
- hicn_protocol_t protocol;
-} hicn_header_t;
-
-
-#define HICN_V6_TCP_HDRLEN (IPV6_HDRLEN + TCP_HDRLEN)
-#define HICN_V6_ICMP_HDRLEN (IPV6_HDRLEN + ICMP_HDRLEN)
-#define HICN_V6_WLDR_HDRLEN (IPV6_HDRLEN + ICMPWLDR_HDRLEN)
-
-#define HICN_V6_TCP_AH_HDRLEN (HICN_V6_TCP_HDRLEN + AH_HDRLEN)
-#define HICN_V6_ICMP_AH_HDRLEN (HICN_V6_ICMP_HDRLEN + AH_HDRLEN)
-
-
-#define HICN_V4_TCP_HDRLEN (IPV4_HDRLEN + TCP_HDRLEN)
-#define HICN_V4_ICMP_HDRLEN (IPV4_HDRLEN + ICMP_HDRLEN)
-#define HICN_V4_WLDR_HDRLEN (IPV4_HDRLEN + ICMPWLDR_HDRLEN)
-
-#define HICN_V4_TCP_AH_HDRLEN (HICN_V4_TCP_HDRLEN + AH_HDRLEN)
-#define HICN_V4_ICMP_AH_HDRLEN (HICN_V4_ICMP_HDRLEN + AH_HDRLEN)
-
-
-
-
-#endif /* HICN_HEADER_H */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/lib/includes/hicn/hicn.h b/lib/includes/hicn/hicn.h
index 749fd4247..5e67d83a0 100644
--- a/lib/includes/hicn/hicn.h
+++ b/lib/includes/hicn/hicn.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -29,17 +29,27 @@
* Recovery (WLDR) [2], Anchorless Mobility Management (hICN-AMM) [3],
* including MAP-Me producer mobility mechanisms [4].
*
+ * Other hICN constructs such as faces, policies and stategies are not included
+ * in this header, but available separately in :
+ * - hicn/face.h
+ * - hicn/policy.h
+ * - hicn/strategy.h
+ *
+ * REFERENCES
+ *
* [1] Hybrid Information-Centric Networking
* L. Muscariello, G. Carofiglio, J. Augé, M. Papalini
- * IETF draft (intarea) @ https://tools.ietf.org/html/draft-muscariello-intarea-hicn
+ * IETF draft (intarea) @
+ * https://tools.ietf.org/html/draft-muscariello-intarea-hicn
*
- * [2] Leveraging ICN in-network control for loss detection and recovery in wireless mobile networks
- * G. Carofiglio, L. Muscariello, M. Papalini, N. Rozhnova, X. Zeng
- * In proc. ICN'2016, Kyoto, JP
+ * [2] Leveraging ICN in-network control for loss detection and recovery in
+ * wireless mobile networks G. Carofiglio, L. Muscariello, M. Papalini, N.
+ * Rozhnova, X. Zeng In proc. ICN'2016, Kyoto, JP
*
* [3] Anchorless mobility through hICN
* J. Augé, G. Carofiglio, L. Muscariello, M. Papalini
- * IETF draft (DMM) @ https://tools.ietf.org/html/draft-auge-dmm-hicn-mobility
+ * IETF draft (DMM) @
+ * https://tools.ietf.org/html/draft-auge-dmm-hicn-mobility
*
*
* [4] MAP-Me : Managing Anchorless Mobility in Content Centric Networking
@@ -50,22 +60,21 @@
#ifndef HICN__H
#define HICN__H
-#ifdef HICN_VPP_PLUGIN
+/* Base data structures */
+#include <hicn/base.h>
-#include <hicn/header.h>
+/* Names */
#include <hicn/name.h>
-#include <hicn/ops.h>
-#include <hicn/mapme.h>
-#else
+/* Packet operations */
+#include <hicn/packet.h>
-#include <hicn/error.h>
-#include <hicn/header.h>
-#include <hicn/name.h>
-#include <hicn/ops.h>
+/* MAP-Me : mobility management operations */
#include <hicn/mapme.h>
-#include <hicn/compat.h>
+/* Error management */
+#ifndef HICN_VPP_PLUGIN
+#include <hicn/error.h>
#endif
#endif /* HICN__H */
diff --git a/lib/includes/hicn/interest_manifest.h b/lib/includes/hicn/interest_manifest.h
new file mode 100644
index 000000000..b6122ce1c
--- /dev/null
+++ b/lib/includes/hicn/interest_manifest.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HICNLIGHT_INTEREST_MANIFEST_H
+#define HICNLIGHT_INTEREST_MANIFEST_H
+
+#include <string.h>
+#include <stdbool.h>
+
+#include <hicn/util/bitmap.h>
+#include <hicn/base.h>
+#include <hicn/name.h>
+#include <hicn/common.h>
+
+typedef enum
+{
+ INT_MANIFEST_SPLIT_STRATEGY_NONE,
+ INT_MANIFEST_SPLIT_STRATEGY_MAX_N_SUFFIXES,
+ INT_MANIFEST_SPLIT_N_STRATEGIES,
+} int_manifest_split_strategy_t;
+
+#define MAX_SUFFIXES_IN_MANIFEST 256
+
+#define DEFAULT_DISAGGREGATION_STRATEGY \
+ INT_MANIFEST_SPLIT_STRATEGY_MAX_N_SUFFIXES
+#define DEFAULT_N_SUFFIXES_PER_SPLIT MAX_SUFFIXES_IN_MANIFEST
+
+#define BITMAP_SIZE (MAX_SUFFIXES_IN_MANIFEST / WORD_WIDTH)
+
+typedef struct
+{
+ /* This can be 16 bits, but we use 32 bits for alignment */
+ uint32_t n_suffixes;
+
+ /* First suffix */
+ uint32_t padding;
+
+ hicn_uword request_bitmap[BITMAP_SIZE];
+
+ /* Followed by the list of prefixes to ask */
+ /* ... */
+} interest_manifest_header_t;
+
+static_assert (sizeof (interest_manifest_header_t) == 32 + 4 + 4,
+ "interest_manifest_header_t size must be exactly 40 bytes");
+
+#define _interest_manifest_serialize_deserialize(manifest, first, second, \
+ size, serialize) \
+ do \
+ { \
+ u32 n_suffixes = 0; \
+ if (serialize) \
+ n_suffixes = int_manifest_header->n_suffixes; \
+ \
+ int_manifest_header->n_suffixes = \
+ hicn_##first##_to_##second##_32 (int_manifest_header->n_suffixes); \
+ int_manifest_header->padding = \
+ hicn_##first##_to_##second##_32 (int_manifest_header->padding); \
+ \
+ for (unsigned i = 0; i < BITMAP_SIZE; i++) \
+ { \
+ int_manifest_header->request_bitmap[i] = \
+ hicn_##first##_to_##second##_##size ( \
+ int_manifest_header->request_bitmap[i]); \
+ } \
+ \
+ hicn_name_suffix_t *suffix = \
+ (hicn_name_suffix_t *) (int_manifest_header + 1); \
+ if (!serialize) \
+ n_suffixes = int_manifest_header->n_suffixes; \
+ for (unsigned i = 0; i < n_suffixes; i++) \
+ { \
+ *(suffix + i) = hicn_##first##_to_##second##_32 (*(suffix + i)); \
+ } \
+ } \
+ while (0)
+
+#define _interest_manifest_serialize(manifest, size) \
+ _interest_manifest_serialize_deserialize (manifest, host, net, size, 1)
+
+#define _interest_manifest_deserialize(manifest, size) \
+ _interest_manifest_serialize_deserialize (manifest, net, host, size, 0)
+
+static inline void
+interest_manifest_serialize (interest_manifest_header_t *int_manifest_header)
+{
+ _interest_manifest_serialize (int_manifest_header, hicn_uword_bits);
+}
+
+static inline void
+interest_manifest_deserialize (interest_manifest_header_t *int_manifest_header)
+{
+ u32 n_suffixes = 0;
+
+ int_manifest_header->n_suffixes =
+ hicn_net_to_host_32 (int_manifest_header->n_suffixes);
+ int_manifest_header->padding =
+ hicn_net_to_host_32 (int_manifest_header->padding);
+
+ for (unsigned i = 0; i < BITMAP_SIZE; i++)
+ {
+ int_manifest_header->request_bitmap[i] =
+ hicn_net_to_host_64 (int_manifest_header->request_bitmap[i]);
+ }
+
+ hicn_name_suffix_t *suffix =
+ (hicn_name_suffix_t *) (int_manifest_header + 1);
+
+ n_suffixes = int_manifest_header->n_suffixes;
+ for (unsigned i = 0; i < n_suffixes; i++)
+ {
+ *(suffix + i) = hicn_net_to_host_32 (*(suffix + i));
+ }
+}
+
+static inline bool
+interest_manifest_is_valid (interest_manifest_header_t *int_manifest_header,
+ size_t payload_length)
+{
+ if (int_manifest_header->n_suffixes == 0 ||
+ int_manifest_header->n_suffixes > MAX_SUFFIXES_IN_MANIFEST)
+ {
+ return false;
+ }
+
+ hicn_uword empty_bitmap[BITMAP_SIZE] = { 0 };
+ if (memcmp (empty_bitmap, int_manifest_header->request_bitmap,
+ sizeof (empty_bitmap)) == 0)
+ {
+ return false;
+ }
+
+ if (payload_length - sizeof (interest_manifest_header_t) !=
+ int_manifest_header->n_suffixes * sizeof (u32))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+static inline void
+interest_manifest_add_suffix (interest_manifest_header_t *int_manifest_header,
+ hicn_name_suffix_t suffix)
+{
+ hicn_name_suffix_t *start = (hicn_name_suffix_t *) (int_manifest_header + 1);
+ *(start + int_manifest_header->n_suffixes) = suffix;
+ hicn_uword *request_bitmap = int_manifest_header->request_bitmap;
+ bitmap_set_no_check (request_bitmap, int_manifest_header->n_suffixes);
+ int_manifest_header->n_suffixes++;
+}
+
+static inline void
+interest_manifest_init (interest_manifest_header_t *int_manifest_header,
+ u32 fist_suffix)
+{
+ int_manifest_header->n_suffixes = 0;
+ int_manifest_header->padding = 0;
+ memset (int_manifest_header->request_bitmap, 0,
+ sizeof (int_manifest_header->request_bitmap));
+
+ interest_manifest_add_suffix (int_manifest_header, fist_suffix);
+}
+
+static inline void
+interest_manifest_del_suffix (interest_manifest_header_t *int_manifest_header,
+ hicn_uword pos)
+{
+ bitmap_unset_no_check (int_manifest_header->request_bitmap, pos);
+}
+
+static inline size_t
+interest_manifest_update_bitmap (const hicn_uword *initial_bitmap,
+ hicn_uword *bitmap_to_update, size_t start,
+ size_t n, size_t max_suffixes)
+{
+ size_t i = start, n_ones = 0;
+ while (i < n)
+ {
+ if (bitmap_is_set_no_check (initial_bitmap, i))
+ {
+ bitmap_set_no_check (bitmap_to_update, i);
+ n_ones++;
+ }
+ i++;
+
+ if (n_ones == max_suffixes)
+ break;
+ }
+
+ return i;
+}
+
+#define _FIRST(h) (hicn_name_suffix_t *) (h + 1)
+
+#define interest_manifest_foreach_suffix(header, suffix, pos) \
+ for (suffix = _FIRST (header) + bitmap_first_set_no_check ( \
+ header->request_bitmap, BITMAP_SIZE), \
+ pos = 0; \
+ suffix - _FIRST (header) < header->n_suffixes; \
+ pos = suffix - _FIRST (header) + 1, \
+ suffix = _FIRST (header) + \
+ bitmap_next_set_no_check (header->request_bitmap, \
+ suffix - _FIRST (header) + 1, \
+ BITMAP_SIZE), \
+ pos = suffix - _FIRST (header))
+
+#endif /* HICNLIGHT_INTEREST_MANIFEST_H */
diff --git a/lib/includes/hicn/mapme.h b/lib/includes/hicn/mapme.h
index 8fae44530..b452a5dde 100644
--- a/lib/includes/hicn/mapme.h
+++ b/lib/includes/hicn/mapme.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -20,28 +20,28 @@
#ifndef HICN_MAPME_H
#define HICN_MAPME_H
-#include <stdint.h> // u32
+#include <stdint.h> // u32
#include <stdbool.h>
+#include <hicn/name.h>
+
#include "common.h"
-#include "protocol.h"
-#include "ops.h"
/**
* @brief MAP-Me configuration options
*/
typedef struct
{
- /** MAP-Me enabled flag (default: false) */
+ /** MAP-Me enabled flag (default: false) */
bool enabled;
- /** timescale (T_U parameter) in ms (default: 0 for no notifications) */
+ /** timescale (T_U parameter) in ms (default: 0 for no notifications) */
u32 timescale;
- /** retransmission timer in ms (default: 50) */
+ /** retransmission timer in ms (default: 50) */
u32 retx;
- /**
- * Discovery enabled flag (default: true, should be true if mandatory is
- * notifications are enabled)
- */
+ /**
+ * Discovery enabled flag (default: true, should be true if mandatory is
+ * notifications are enabled)
+ */
bool discovery;
} hicn_mapme_conf_t;
@@ -74,83 +74,51 @@ typedef struct
seq_t seq;
} mapme_params_t;
-
/* MAP-Me API */
-size_t hicn_mapme_create_packet (u8 * buf, const hicn_prefix_t * prefix,
- const mapme_params_t * params);
-size_t hicn_mapme_create_ack (u8 * buf, const mapme_params_t * params);
-int hicn_mapme_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
- mapme_params_t * params);
+size_t hicn_mapme_create_packet (u8 *buf, const hicn_prefix_t *prefix,
+ const mapme_params_t *params);
+size_t hicn_mapme_create_ack (u8 *buf, const mapme_params_t *params);
+int hicn_mapme_parse_packet (const u8 *packet, hicn_prefix_t *prefix,
+ mapme_params_t *params);
/* Implementation & parsing : ICMP Redirect */
#define HICN_MAPME_ACK_FLAG (0x20 | 0x60)
-#define HICN_MAPME_ICMP_TYPE_IPV4 5
-#define HICN_MAPME_ICMP_TYPE_IPV6 137
-#define HICN_MAPME_ICMP_TYPE_ACK_IPV4 (HICN_MAPME_ICMP_TYPE_IPV4 | HICN_MAPME_ACK_FLAG)
-#define HICN_MAPME_ICMP_TYPE_ACK_IPV6 (HICN_MAPME_ICMP_TYPE_IPV6 | HICN_MAPME_ACK_FLAG)
-#define HICN_MAPME_ICMP_CODE 0 /* Redirect Datagrams for the Network (or subnet) */
-
-#define HICN_MAPME_TYPE_IS_IU(type) ((type == HICN_MAPME_ICMP_TYPE_IPV4) || (type == HICN_MAPME_ICMP_TYPE_IPV6))
-#define HICN_MAPME_TYPE_IS_IU_ACK(type) ((type == HICN_MAPME_ICMP_TYPE_ACK_IPV4) || (type == HICN_MAPME_ICMP_TYPE_ACK_IPV6))
-
-#define HICN_MAPME_IS_IU(type, code) (HICN_MAPME_TYPE_IS_IU(type) && (code == HICN_MAPME_ICMP_CODE))
-#define HICN_MAPME_IS_ACK(type, code) (HICN_MAPME_TYPE_IS_IU_ACK(type) && (code == HICN_MAPME_ICMP_CODE))
-
-#define HICN_IS_MAPME(type, code) (HICN_MAPME_IS_IU(type, code) || HICN_MAPME_IS_ACK(type, code))
+#define HICN_MAPME_ICMP_TYPE_IPV4 5
+#define HICN_MAPME_ICMP_TYPE_IPV6 137
+#define HICN_MAPME_ICMP_TYPE_ACK_IPV4 \
+ (HICN_MAPME_ICMP_TYPE_IPV4 | HICN_MAPME_ACK_FLAG)
+#define HICN_MAPME_ICMP_TYPE_ACK_IPV6 \
+ (HICN_MAPME_ICMP_TYPE_IPV6 | HICN_MAPME_ACK_FLAG)
+#define HICN_MAPME_ICMP_CODE \
+ 0 /* Redirect Datagrams for the Network (or subnet) */
+
+#define HICN_MAPME_TYPE_IS_IU(type) \
+ ((type == HICN_MAPME_ICMP_TYPE_IPV4) || (type == HICN_MAPME_ICMP_TYPE_IPV6))
+#define HICN_MAPME_TYPE_IS_IU_ACK(type) \
+ ((type == HICN_MAPME_ICMP_TYPE_ACK_IPV4) || \
+ (type == HICN_MAPME_ICMP_TYPE_ACK_IPV6))
+
+#define HICN_MAPME_IS_IU(type, code) \
+ (HICN_MAPME_TYPE_IS_IU (type) && (code == HICN_MAPME_ICMP_CODE))
+#define HICN_MAPME_IS_ACK(type, code) \
+ (HICN_MAPME_TYPE_IS_IU_ACK (type) && (code == HICN_MAPME_ICMP_CODE))
+
+#define HICN_IS_MAPME(type, code) \
+ (HICN_MAPME_IS_IU (type, code) || HICN_MAPME_IS_ACK (type, code))
/* Fast check for ACK flag */
#define HICN_MAPME_IS_ACK_FAST(icmp_type) (icmp_type & HICN_MAPME_ACK_FLAG)
/* Default TTL */
-#define HICN_MAPME_TTL 255 // typical for redirect (ref?)
-
-/*
- * The length of the MAPME4 header struct must be 120 bytes.
- */
-#define EXPECTED_MAPME_V4_HDRLEN 120
+#define HICN_MAPME_TTL 255 // typical for redirect (ref?)
-/** @brief MAP-Me packet header for IPv4 */
-typedef struct
-{
- _ipv4_header_t ip;
- _icmprd4_header_t icmp_rd;
- seq_t seq;
- u8 len;
- u8 _pad[3];
-} hicn_mapme_v4_header_t;
+/* Should be moved to mapme.c, but header size still in use in VPP */
-/*
- * The length of the MAPME4 header struct must be bytes.
- */
+#define EXPECTED_MAPME_V4_HDRLEN 120
#define EXPECTED_MAPME_V6_HDRLEN 88
-/** @brief MAP-Me packet header for IPv6 */
-typedef struct
-{
- _ipv6_header_t ip;
- _icmprd_header_t icmp_rd;
- seq_t seq;
- u8 len;
- u8 _pad[3];
-} hicn_mapme_v6_header_t;
-
-/** @brief MAP-Me packet header (IP version agnostic) */
-typedef union
-{
- hicn_mapme_v4_header_t v4;
- hicn_mapme_v6_header_t v6;
-} hicn_mapme_header_t;
-
-#define HICN_MAPME_V4_HDRLEN sizeof(hicn_mapme_v4_header_t)
-#define HICN_MAPME_V6_HDRLEN sizeof(hicn_mapme_v6_header_t)
-
-static_assert (EXPECTED_MAPME_V4_HDRLEN == HICN_MAPME_V4_HDRLEN,
- "Size of MAPME_V4 struct does not match its expected size.");
-static_assert (EXPECTED_MAPME_V6_HDRLEN == HICN_MAPME_V6_HDRLEN,
- "Size of MAPME_V6 struct does not match its expected size.");
-
#endif /* HICN_MAPME_H */
/*
diff --git a/lib/includes/hicn/name.h b/lib/includes/hicn/name.h
index d5202068b..a4e8e02ad 100644
--- a/lib/includes/hicn/name.h
+++ b/lib/includes/hicn/name.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -24,119 +24,109 @@
#ifndef HICN_NAME_H
#define HICN_NAME_H
+#include <assert.h>
#include <stdbool.h>
+#include <stddef.h>
#ifndef _WIN32
-#include <netinet/in.h> // struct sockadd
+#include <netinet/in.h> // struct sockadd
#endif
+#include <hicn/common.h>
#include <hicn/util/ip_address.h>
-#include "common.h"
/******************************************************************************
* hICN names
******************************************************************************/
-#define TCP_SEQNO_LEN 4 /* bytes */
+#define TCP_SEQNO_LEN 4 /* bytes */
#define HICN_V4_PREFIX_LEN IPV4_ADDR_LEN
#define HICN_V6_PREFIX_LEN IPV6_ADDR_LEN
+
+#if 0
#define HICN_SEGMENT_LEN TCP_SEQNO_LEN
-#define HICN_V6_NAME_LEN (HICN_V6_PREFIX_LEN + HICN_SEGMENT_LEN) /* 20 bytes */
-#define HICN_V4_NAME_LEN (HICN_V4_PREFIX_LEN + HICN_SEGMENT_LEN) /* 8 bytes */
+
+#define HICN_V6_NAME_LEN \
+ (HICN_V6_PREFIX_LEN + HICN_SEGMENT_LEN) /* 20 bytes \
+ */
+#define HICN_V4_NAME_LEN \
+ (HICN_V4_PREFIX_LEN + HICN_SEGMENT_LEN) /* 8 bytes \
+ */
+#endif
+
+#define HICN_INVALID_SUFFIX ((uint32_t) (~0))
/* Prefix */
-typedef u32 hicn_name_suffix_t;
+#define HICN_PREFIX_MAX_LEN IP_ADDRESS_MAX_LEN
typedef struct
{
- ip46_address_t name;
+ hicn_ip_address_t name;
u8 len;
} hicn_prefix_t;
+#define HICN_PREFIX_EMPTY \
+ (hicn_prefix_t) { .name = IP_ADDRESS_EMPTY, .len = 0 }
+
+static inline const hicn_ip_address_t *
+hicn_prefix_get_ip_address (const hicn_prefix_t *prefix)
+{
+ return &prefix->name;
+}
+
+static inline u8
+hicn_prefix_get_len (const hicn_prefix_t *prefix)
+{
+ return prefix->len;
+}
+
+int hicn_prefix_get_ip_prefix (const hicn_prefix_t *prefix,
+ hicn_ip_prefix_t *ip_prefix);
/*
* Name
*
* A name is a prefix + a segment name (suffix)
*/
-typedef union
-{
- struct
- {
- union
- {
- u32 prefix;
- u8 prefix_as_u8[4];
- ip4_address_t prefix_as_ip4;
- };
- hicn_name_suffix_t suffix;
- };
- u8 buffer[HICN_V4_NAME_LEN];
-} hicn_v4_name_t;
-
-typedef union
-{
- struct
- {
- union
- {
- u64 prefix[2];
- u8 prefix_as_u8[16];
- ip6_address_t prefix_as_ip6;
- };
- hicn_name_suffix_t suffix;
- };
- u8 buffer[HICN_V6_NAME_LEN];
-} hicn_v6_name_t;
-
-#ifndef HICN_VPP_PLUGIN
-#define HICN_NAME_COMPONENT_SIZE 2
+typedef hicn_ip_address_t hicn_name_prefix_t;
+typedef uint32_t hicn_name_suffix_t;
+
+#define hicn_name_prefix_cmp hicn_ip_address_cmp
+#define hicn_name_prefix_equals hicn_ip_address_equals
+#define hicn_name_prefix_get_len_bits hicn_ip_address_get_len_bits
+#define hicn_name_prefix_get_hash hicn_ip_address_get_hash
+#define hicn_name_prefix_snprintf hicn_ip_address_snprintf
+#define HICN_NAME_PREFIX_EMPTY IP_ADDRESS_EMPTY
typedef struct
{
- struct iovec buffers[HICN_NAME_COMPONENT_SIZE];
-} hicn_iov_name_t;
+ hicn_name_prefix_t prefix;
+ hicn_name_suffix_t suffix;
+} hicn_name_t;
-#define UNSPEC 1 << 0
-#define HNT_CONTIGUOUS 1 << 1
-#define HNT_IOV 1 << 2
-#define HNT_INET 1 << 3
-#define HNT_INET6 1 << 4
+static_assert (offsetof (hicn_name_t, prefix) == 0, "");
+static_assert (offsetof (hicn_name_t, suffix) == 16, "");
+static_assert (sizeof (hicn_name_t) == 20, "");
-typedef enum
+#define HICN_NAME_EMPTY \
+ (hicn_name_t) { .prefix = HICN_NAME_PREFIX_EMPTY, .suffix = 0, }
+
+static inline const hicn_name_prefix_t *
+hicn_name_get_prefix (const hicn_name_t *name)
{
- HNT_UNSPEC = UNSPEC,
- HNT_CONTIGUOUS_V4 = HNT_CONTIGUOUS | HNT_INET,
- HNT_CONTIGUOUS_V6 = HNT_CONTIGUOUS | HNT_INET6,
- HNT_IOV_V4 = HNT_IOV | HNT_INET,
- HNT_IOV_V6 = HNT_IOV | HNT_INET6,
-} hicn_name_type_t;
-#endif /* HICN_VPP_PLUGIN */
+ return &name->prefix;
+}
-typedef struct
+static inline const hicn_name_suffix_t
+hicn_name_get_suffix (const hicn_name_t *name)
{
-#ifndef HICN_VPP_PLUGIN
- hicn_name_type_t type;
- u8 len;
-#endif /* HICN_VPP_PLUGIN */
- union
- {
- hicn_v4_name_t ip4;
- hicn_v6_name_t ip6;
- ip46_address_t ip46;
-#ifndef HICN_VPP_PLUGIN
- hicn_iov_name_t iov;
- u8 buffer[HICN_V6_NAME_LEN];
-#endif /* HICN_VPP_PLUGIN */
- };
-} hicn_name_t;
+ return name->suffix;
+}
-#ifndef HICN_VPP_PLUGIN
-#define _is_unspec(name) ((name->type & UNSPEC))
-#define _is_contiguous(name) ((name->type & HNT_CONTIGUOUS) >> 1)
-#define _is_iov(name) ((name->type & HNT_IOV) >> 2)
-#define _is_inet4(name) ((name->type & HNT_INET) >> 3)
-#define _is_inet6(name) ((name->type & HNT_INET6) >> 4)
-#endif /* HICN_VPP_PLUGIN */
+#define _is_unspec(name) \
+ (((name)->prefix.pad[0] | (name)->prefix.pad[1] | (name)->prefix.pad[2] | \
+ (name)->prefix.v4.as_u32) == 0)
+#define _is_inet4(name) (hicn_ip_address_is_v4 (&name->prefix))
+#define _is_inet6(name) (!_is_inet4 (name))
/**
* @brief Create an hICN name from IP address in presentation format
@@ -145,37 +135,40 @@ typedef struct
* @param [out] Resulting hICN name
* @return hICN error code
*/
-int hicn_name_create (const char *ip_address, u32 id, hicn_name_t * name);
+int hicn_name_create (const char *ip_address, u32 id, hicn_name_t *name);
/**
* @brief Create an hICN name from IP address
* @param [in] ip_address - IP address
- * @param [in] id Segment - identifier
+ * @param [in] suffix - Name suffix
* @param [out] Resulting - hICN name
* @return hICN error code
*/
-int hicn_name_create_from_ip_prefix (const ip_prefix_t * prefix, u32 id,
- hicn_name_t * name);
+int hicn_name_create_from_ip_address (const hicn_ip_address_t ip_address,
+ u32 suffix, hicn_name_t *name);
/**
- * @brief Returns the length of an hICN name
- * @param [in] name - hICN name
- * @return Name length
+ * @brief Create an hICN name from IP prefix
+ * @param [in] prefix - IP prefix
+ * @param [in] suffix - Name suffix
+ * @param [out] Resulting - hICN name
+ * @return hICN error code
*/
-u8 hicn_name_get_length (const hicn_name_t * name);
+int hicn_name_create_from_ip_prefix (const hicn_ip_prefix_t *prefix, u32 id,
+ hicn_name_t *name);
/**
* @brief Compare two hICN names
* @param [in] name_1 - First name to compare
* @param [in] name_2 - Second name to compare
- * @param [in] consider_segment - Flag indicating whether the segment part has to be
- * considered
+ * @param [in] consider_segment - Flag indicating whether the segment part has
+ * to be considered
* @return An integer less than, equal to, or greater than zero if name_1 is
* found, respectively, to be lest than, to match, or be greater than name_2
* based on numeric order.
*/
-int hicn_name_compare (const hicn_name_t * name_1, const hicn_name_t * name_2,
- bool consider_segment);
+int hicn_name_compare (const hicn_name_t *name_1, const hicn_name_t *name_2,
+ bool consider_segment);
/**
* @brief Provides a 32-bit hash of an hICN name
@@ -184,7 +177,10 @@ int hicn_name_compare (const hicn_name_t * name_1, const hicn_name_t * name_2,
* @param [in] consider_suffix - Consider the suffix in the hash computation
* @return hICN error code
*/
-int hicn_name_hash (const hicn_name_t * name, u32 * hash, bool consider_suffix);
+uint32_t _hicn_name_get_hash (const hicn_name_t *name, bool consider_suffix);
+
+#define hicn_name_get_hash(NAME) _hicn_name_get_hash (NAME, true)
+#define hicn_name_get_prefix_hash(NAME) _hicn_name_get_hash (NAME, false)
/**
* @brief Test whether an hICN name is empty
@@ -192,7 +188,7 @@ int hicn_name_hash (const hicn_name_t * name, u32 * hash, bool consider_suffix);
* @return 0 if the name is empty, any other value otherwise (implementation
* returns 1)
*/
-int hicn_name_empty (hicn_name_t * name);
+int hicn_name_empty (hicn_name_t *name);
/**
* @brief Copy an hICN name
@@ -200,7 +196,7 @@ int hicn_name_empty (hicn_name_t * name);
* @param [in] src - Source name to copy
* @return hICN error code
*/
-int hicn_name_copy (hicn_name_t * dst, const hicn_name_t * src);
+int hicn_name_copy (hicn_name_t *dst, const hicn_name_t *src);
/**
* @brief Copy an hICN name to a buffer
@@ -209,8 +205,7 @@ int hicn_name_copy (hicn_name_t * dst, const hicn_name_t * src);
* @param [in] copy_suffix - Flag indicating whether the suffix has to be
* considered
*/
-int hicn_name_copy_to_destination (u8 * dst, const hicn_name_t * src,
- bool copy_suffix);
+int hicn_name_copy_prefix_to_destination (u8 *dst, const hicn_name_t *src);
/**
* @brief Sets the segment part of an hICN name
@@ -218,7 +213,7 @@ int hicn_name_copy_to_destination (u8 * dst, const hicn_name_t * src,
* @param [in] seq_number - Segment identifier
* @return hICN error code
*/
-int hicn_name_set_seq_number (hicn_name_t * name, u32 seq_number);
+int hicn_name_set_suffix (hicn_name_t *name, hicn_name_suffix_t suffix);
/**
* @brief Retrieves the segment part of an hICN name
@@ -226,7 +221,7 @@ int hicn_name_set_seq_number (hicn_name_t * name, u32 seq_number);
* @param [in] seq_number - Segment identifier
* @return hICN error code
*/
-int hicn_name_get_seq_number (const hicn_name_t * name, u32 * seq_number);
+int hicn_name_get_seq_number (const hicn_name_t *name, u32 *seq_number);
/**
* @brief Convert an hICN name to a socket address
@@ -234,8 +229,8 @@ int hicn_name_get_seq_number (const hicn_name_t * name, u32 * seq_number);
* @param [out] ip_address - Resulting socket address
* @return hICN error code
*/
-int hicn_name_to_sockaddr_address (const hicn_name_t * name,
- struct sockaddr *ip_address);
+int hicn_name_to_sockaddr_address (const hicn_name_t *name,
+ struct sockaddr *ip_address);
/**
* @brief Convert an hICN name to an IP address
@@ -243,8 +238,8 @@ int hicn_name_to_sockaddr_address (const hicn_name_t * name,
* @param [out] ip_address - Resulting IP address
* @return hICN error code
*/
-int hicn_name_to_ip_prefix (const hicn_name_t * name,
- ip_prefix_t * ip_prefix);
+int hicn_name_to_hicn_ip_prefix (const hicn_name_t *name,
+ hicn_ip_prefix_t *hicn_ip_prefix);
/**
* @brief Convert an hICN name to presentation format
@@ -253,7 +248,7 @@ int hicn_name_to_ip_prefix (const hicn_name_t * name,
* @param [in] len - Number of bytes available in the buffer
* @return hICN error code
*/
-int hicn_name_ntop (const hicn_name_t * src, char *dst, size_t len);
+int hicn_name_ntop (const hicn_name_t *src, char *dst, size_t len);
/**
* @brief Convert an hICN name from presentation format
@@ -261,7 +256,7 @@ int hicn_name_ntop (const hicn_name_t * src, char *dst, size_t len);
* @param [out] dst - Resulting name
* @return hICN error code
*/
-int hicn_name_pton (const char *src, hicn_name_t * dst);
+int hicn_name_pton (const char *src, hicn_name_t *dst);
/**
* @brief Returns the IP address family of an hICN name
@@ -269,7 +264,19 @@ int hicn_name_pton (const char *src, hicn_name_t * dst);
* @param [out] family - Resulting IP address family (AF_INET or AF_INET6)
* @return hICN error code
*/
-int hicn_name_get_family (const hicn_name_t * name, int *family);
+int hicn_name_get_family (const hicn_name_t *name, int *family);
+
+bool hicn_name_is_v4 (const hicn_name_t *name);
+
+int hicn_name_snprintf (char *s, size_t size, const hicn_name_t *name);
+
+int hicn_name_no_suffix_snprintf (char *s, size_t size,
+ const hicn_name_t *name);
+
+int hicn_name_cmp (const hicn_name_t *n1, const hicn_name_t *n2);
+bool hicn_name_equals (const hicn_name_t *n1, const hicn_name_t *n2);
+
+#define MAXSZ_HICN_NAME MAXSZ_IP_ADDRESS
/**
* @brief Creates an hICN prefix from an IP address
@@ -277,8 +284,35 @@ int hicn_name_get_family (const hicn_name_t * name, int *family);
* @param [out] prefix - Resulting prefix
* @return hICN error code
*/
-int hicn_prefix_create_from_ip_prefix (const ip_prefix_t * ip_prefix,
- hicn_prefix_t * prefix);
+int hicn_prefix_create_from_ip_prefix (const hicn_ip_prefix_t *hicn_ip_prefix,
+ hicn_prefix_t *prefix);
+
+int
+hicn_prefix_create_from_ip_address_len (const hicn_ip_address_t *ip_address,
+ uint8_t len, hicn_prefix_t *prefix);
+
+hicn_prefix_t *hicn_prefix_dup (const hicn_prefix_t *prefix);
+
+int hicn_prefix_copy (hicn_prefix_t *dst, const hicn_prefix_t *src);
+
+bool hicn_prefix_is_v4 (const hicn_prefix_t *prefix);
+
+uint32_t hicn_prefix_lpm (const hicn_prefix_t *p1, const hicn_prefix_t *p2);
+
+void hicn_prefix_clear (hicn_prefix_t *prefix, uint8_t start_from);
+
+void hicn_prefix_truncate (hicn_prefix_t *prefix, uint8_t len);
+
+int hicn_prefix_cmp (const hicn_prefix_t *p1, const hicn_prefix_t *p2);
+
+bool hicn_prefix_equals (const hicn_prefix_t *p1, const hicn_prefix_t *p2);
+
+int hicn_prefix_snprintf (char *s, size_t size, const hicn_prefix_t *prefix);
+
+uint8_t _hicn_prefix_get_bit (const hicn_prefix_t *prefix, uint8_t pos);
+uint8_t hicn_prefix_get_bit (const hicn_prefix_t *prefix, uint8_t pos);
+
+#define MAXSZ_HICN_PREFIX MAXSZ_IP_PREFIX
#endif /* HICN_NAME_H */
diff --git a/lib/includes/hicn/ops.h b/lib/includes/hicn/ops.h
deleted file mode 100644
index e5b1c088c..000000000
--- a/lib/includes/hicn/ops.h
+++ /dev/null
@@ -1,871 +0,0 @@
-/*
- * Copyright (c) 2017-2019 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.h
- * @brief Protocol-independent packet operations
- */
-
-#ifndef HICN_OPS_H
-#define HICN_OPS_H
-
-#include <stdlib.h>
-
-#include "error.h"
-#include "header.h"
-#include "name.h"
-
-/*
- * hICN operations on packets
- *
- * All prototypes take an hicn_type_t parameter as their first argument, as
- * this decides the sequence of protocols that are being used by the different
- * operations.
- */
-
-typedef struct hicn_ops_s
-{
- /**
- * @brief Initialize the headers of the hicn packet
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the packet
- */
- int (*init_packet_header) (hicn_type_t type, hicn_protocol_t *h);
-
- /**
- * @brief Retrieves an Interest locator
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the Interest packet
- * @param [out] ip_address - Retrieved locator
- * @return hICN error code
- */
- int (*get_interest_locator) (hicn_type_t type, const hicn_protocol_t *h,
- ip46_address_t *ip_address);
-
- /**
- * @brief Sets an Interest locator
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest packet
- * @param [in] ip_address - Locator to set
- * @return hICN error code
- */
- int (*set_interest_locator) (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *ip_address);
-
- /**
- * @brief Retrieves an Interest name
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the Interest packet
- * @param [out] name - Retrieved name
- * @return hICN error code
- */
- int (*get_interest_name) (hicn_type_t type, const hicn_protocol_t *h,
- hicn_name_t *name);
-
- /**
- * @brief Sets an Interest name
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest packet
- * @param [in] name - Name to set
- * @return hICN error code
- */
- int (*set_interest_name) (hicn_type_t type, hicn_protocol_t *h,
- const hicn_name_t *name);
-
- /**
- * @brief Retrieves an Interest name suffix
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the Interest packet
- * @param [out] suffix - Retrieved name suffix
- * @return hICN error code
- */
- int (*get_interest_name_suffix) (hicn_type_t type, const hicn_protocol_t *h,
- hicn_name_suffix_t *suffix);
-
- /**
- * @brief Sets an Interest name suffix
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest packet
- * @param [in] suffix - Name suffix to set
- * @return hICN error code
- */
- int (*set_interest_name_suffix) (hicn_type_t type, hicn_protocol_t *h,
- const hicn_name_suffix_t *suffix);
-
- /**
- * @brief Set flag to mark current packet as interest
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest packet
- * @return hICN error code
- */
- int (*mark_packet_as_interest) (hicn_type_t type, hicn_protocol_t *h);
-
- /**
- * @brief Set flag to mark current packet as data
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest packet
- * @return hICN error code
- */
- int (*mark_packet_as_data) (hicn_type_t type, hicn_protocol_t *h);
-
- /**
- * @brief Clear the necessary Interest fields in order to hash it
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest packet
- * @return hICN error code
- */
- int (*reset_interest_for_hash) (hicn_type_t type, hicn_protocol_t *h);
-
- /**
- * @brief Retrieves a Data locator
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the Data packet
- * @param [out] ip_address - Retrieved locator
- * @return hICN error code
- */
- int (*get_data_locator) (hicn_type_t type, const hicn_protocol_t *h,
- ip46_address_t *ip_address);
-
- /**
- * @brief Sets a Data locator
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Data packet
- * @param [in] ip_address - Locator to set
- * @return hICN error code
- */
- int (*set_data_locator) (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *ip_address);
-
- /**
- * @brief Retrieves a Data name
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the Data packet
- * @param [out] name - Retrieved name
- * @return hICN error code
- */
- int (*get_data_name) (hicn_type_t type, const hicn_protocol_t *h,
- hicn_name_t *name);
-
- /**
- * @brief Sets a Data name
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Data packet
- * @param [in] name - Name to set
- * @return hICN error code
- */
- int (*set_data_name) (hicn_type_t type, hicn_protocol_t *h,
- const hicn_name_t *name);
-
- /**
- * @brief Retrieves a Data name suffix
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the Data packet
- * @param [out] suffix - Retrieved name suffix
- * @return hICN error code
- */
- int (*get_data_name_suffix) (hicn_type_t type, const hicn_protocol_t *h,
- hicn_name_suffix_t *suffix);
-
- /**
- * @brief Sets a Data name suffix
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Data packet
- * @param [in] suffix - Name suffix to set
- * @return hICN error code
- */
- int (*set_data_name_suffix) (hicn_type_t type, hicn_protocol_t *h,
- const hicn_name_suffix_t *suffix);
-
- /**
- * @brief Retrieves a Data pathlabel
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the Data packet
- * @param [out] pathlabel - Retrieved pathlabel
- * @return hICN error code
- */
- int (*get_data_pathlabel) (hicn_type_t type, const hicn_protocol_t *h,
- u32 *pathlabel);
-
- /**
- * @brief Sets a Data pathlabel
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Data packet
- * @param [in] pathlabel - Pathlabel to set
- * @return hICN error code
- */
- int (*set_data_pathlabel) (hicn_type_t type, hicn_protocol_t *h,
- const u32 pathlabel);
-
- /**
- * @brief Update a Data pathlabel with a new face identifier
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Data packet
- * @param [in] pathlabel - Face identifier used to update pathlabel
- * @return hICN error code
- */
- int (*update_data_pathlabel) (hicn_type_t type, hicn_protocol_t *h,
- const hicn_faceid_t face_id);
-
- /**
- * @brief Clear the necessary Data fields in order to hash it
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Data packet
- * @return hICN error code
- */
- int (*reset_data_for_hash) (hicn_type_t type, hicn_protocol_t *h);
-
- /**
- * @brief Retrieves an Interest or Data lifetime
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the Interest or Data packet
- * @param [out] pathlabel - Retrieved lifetime
- * @return hICN error code
- */
- int (*get_lifetime) (hicn_type_t type, const hicn_protocol_t *h,
- hicn_lifetime_t *lifetime);
-
- /**
- * @brief Sets an Interest or Data lifetime
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [in] pathlabel - Lifetime to set
- * @return hICN error code
- */
- int (*set_lifetime) (hicn_type_t type, hicn_protocol_t *h,
- const hicn_lifetime_t lifetime);
-
- /**
- * @brief Update all checksums in packet headers
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the packet
- * @param [in] partial_csum - Partial checksum (set to 0, used internally to
- * carry intermediate values from IP pseudo-header)
- * @param [in] payload_length - Payload length (can be set to ~0, retrieved
- * and used internally to carry payload length across protocol headers)
- * @return hICN error code
- */
- int (*update_checksums) (hicn_type_t type, hicn_protocol_t *h,
- u16 partial_csum, size_t payload_length);
-
- /**
- * @brief Validate all checksums in packet headers
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the packet
- * @param [in] partial_csum - Partial checksum, or zero if no partial
- * checksum available
- * @param [in] payload_length - Payload length (can be set to ~0, retrieved
- * and used internally to carry payload length across protocol headers)
- * @return hICN error code
- */
- int (*verify_checksums) (hicn_type_t type, hicn_protocol_t *h,
- u16 partial_csum, size_t payload_length);
-
- /**
- * @brief Rewrite an Interest packet header (locator)
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the Interest packet
- * @param [in] addr_new - New locator
- * @param [in] addr_old - Old locator (set to NULL, used internally to
- * compute incremental checksums)
- * @return hICN error code
- */
- int (*rewrite_interest) (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new,
- ip46_address_t *addr_old);
-
- /**
- * @brief Rewrite a Data packet header (locator + pathlabel)
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the Data packet
- * @param [in] addr_new - New locator
- * @param [in] addr_old - Old locator (set to NULL, used internally to
- * compute incremental checksums)
- * @param [in] face_id - Face identifier used to update pathlabel
- * @param [in] reset_pl - If not zero, reset the current pathlabel
- * before update it
- * @return hICN error code
- */
- int (*rewrite_data) (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new,
- ip46_address_t *addr_old, const hicn_faceid_t face_id,
- u8 reset_pl);
-
- /**
- * @brief Return the packet length
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the packet
- * @parma [out] length - Returned packet length
- * @return hICN error code
- */
- int (*get_length) (hicn_type_t type, const hicn_protocol_t *h,
- size_t *length);
-
- /**
- * @brief Return the current packet header length
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the packet
- * @parma [out] header_length - Returned packet current header length
- * @return hICN error code
- */
- int (*get_current_header_length) (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length);
-
- /**
- * @brief Return the packet header length
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the packet
- * @parma [out] header_length - Returned packet header length
- * @return hICN error code
- */
- int (*get_header_length) (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length);
-
- /**
- * @brief Return the packet payload length
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the packet
- * @parma [out] payload_length - Returned packet payload length
- * @return hICN error code
- */
- int (*get_payload_length) (hicn_type_t type, const hicn_protocol_t *h,
- size_t *payload_length);
-
- /**
- * @brief Sets the packet paylaod length
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the packet
- * @parma [out] payload_length - Payload length to set
- * @return hICN error code
- */
- int (*set_payload_length) (hicn_type_t type, hicn_protocol_t *h,
- size_t payload_length);
-
- /**
- * @brief Retrieves an Interest or Data signature size
- * @param [in] type - hICN packet type
- * @param [in] h - Buffer holding the Interest or Data packet
- * @param [out] signature_size - Retrieved signature size
- * @return hICN error code
- */
- int (*get_signature_size) (hicn_type_t type, const hicn_protocol_t *h,
- size_t *signature_size);
-
- /**
- * @brief Sets an Interest or Data signature size
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [in] signature_size - Signature size to set
- * @return hICN error code
- */
- int (*set_signature_size) (hicn_type_t type, hicn_protocol_t *h,
- size_t signature_size);
-
- /**
- * @brief Sets an Interest or Data signature gap between maximum size and
- * real size
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [in] signature_size - Signature size to set
- * @return hICN error code
- */
- int (*set_signature_gap) (hicn_type_t type, hicn_protocol_t *h,
- uint8_t signature_gap);
-
- /**
- * @brief gets an Interest or Data signature gap between maximum size and
- * real size
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [in] signature_size - retrieve the gap between maximum size and
- * real size
- * @return hICN error code
- */
- int (*get_signature_gap) (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *signature_gap);
-
- /**
- * @brief Gets the signature timestamp
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [out] signature_timestamp - Retrieved signature timestamp
- * @return hICN error code
- */
- int (*get_signature_timestamp) (hicn_type_t type, const hicn_protocol_t *h,
- uint64_t *signature_timestamp);
-
- /**
- * @brief Sets the signature timestamp
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [in] signature_timestamp - Signature timestamp to set
- * @return hICN error code
- */
- int (*set_signature_timestamp) (hicn_type_t type, hicn_protocol_t *h,
- uint64_t signature_timestamp);
-
- /**
- * @brief Gets the signature validation algorithm
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [out] validation_algorithm - Retrieved validation_algorithm
- * @return hICN error code
- */
- int (*get_validation_algorithm) (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *validation_algorithm);
-
- /**
- * @brief Sets the signature validation algorithm
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [in] validation_algorithm - Validation algorithm enumeration
- * @return hICN error code
- */
- int (*set_validation_algorithm) (hicn_type_t type, hicn_protocol_t *h,
- uint8_t validation_algorithm);
-
- /**
- * @brief Gets the key id
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [out] key_id - Retrieved key id first byte address
- * @return hICN error code
- */
- int (*get_key_id) (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
- uint8_t *key_id_size);
-
- /**
- * @brief Sets the key id
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [in] key_id - Key id first byte address
- * @return hICN error code
- */
- int (*set_key_id) (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id);
-
- /**
- * @brief Get a pointer to the signature field in the packet
- * @param [in] type - hICN packet type
- * @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [out] signature - Pointer to the memory region holding the
- * signature
- * @return hICN error code
- */
- int (*get_signature) (hicn_type_t type, hicn_protocol_t *h,
- uint8_t **signature);
-} hicn_ops_t;
-
-#define DECLARE_HICN_OPS(protocol) \
- const hicn_ops_t hicn_ops_##protocol = { \
- ATTR_INIT (init_packet_header, protocol##_init_packet_header), \
- ATTR_INIT (get_interest_locator, protocol##_get_interest_locator), \
- ATTR_INIT (set_interest_locator, protocol##_set_interest_locator), \
- ATTR_INIT (get_interest_name, protocol##_get_interest_name), \
- ATTR_INIT (set_interest_name, protocol##_set_interest_name), \
- ATTR_INIT (get_interest_name_suffix, \
- protocol##_get_interest_name_suffix), \
- ATTR_INIT (set_interest_name_suffix, \
- protocol##_set_interest_name_suffix), \
- ATTR_INIT (mark_packet_as_interest, protocol##_mark_packet_as_interest), \
- ATTR_INIT (mark_packet_as_data, protocol##_mark_packet_as_data), \
- ATTR_INIT (reset_interest_for_hash, protocol##_reset_interest_for_hash), \
- ATTR_INIT (get_data_locator, protocol##_get_data_locator), \
- ATTR_INIT (set_data_locator, protocol##_set_data_locator), \
- ATTR_INIT (get_data_name, protocol##_get_data_name), \
- ATTR_INIT (set_data_name, protocol##_set_data_name), \
- ATTR_INIT (get_data_name_suffix, protocol##_get_data_name_suffix), \
- ATTR_INIT (set_data_name_suffix, protocol##_set_data_name_suffix), \
- ATTR_INIT (get_data_pathlabel, protocol##_get_data_pathlabel), \
- ATTR_INIT (set_data_pathlabel, protocol##_set_data_pathlabel), \
- ATTR_INIT (update_data_pathlabel, protocol##_update_data_pathlabel), \
- ATTR_INIT (reset_data_for_hash, protocol##_reset_data_for_hash), \
- ATTR_INIT (get_lifetime, protocol##_get_lifetime), \
- ATTR_INIT (set_lifetime, protocol##_set_lifetime), \
- ATTR_INIT (update_checksums, protocol##_update_checksums), \
- ATTR_INIT (verify_checksums, protocol##_verify_checksums), \
- ATTR_INIT (rewrite_interest, protocol##_rewrite_interest), \
- ATTR_INIT (rewrite_data, protocol##_rewrite_data), \
- ATTR_INIT (get_length, protocol##_get_length), \
- ATTR_INIT (get_current_header_length, \
- protocol##_get_current_header_length), \
- ATTR_INIT (get_header_length, protocol##_get_header_length), \
- ATTR_INIT (get_payload_length, protocol##_get_payload_length), \
- ATTR_INIT (set_payload_length, protocol##_set_payload_length), \
- ATTR_INIT (get_signature_size, protocol##_get_signature_size), \
- ATTR_INIT (get_signature_timestamp, protocol##_get_signature_timestamp), \
- ATTR_INIT (set_signature_timestamp, protocol##_set_signature_timestamp), \
- ATTR_INIT (get_validation_algorithm, \
- protocol##_get_validation_algorithm), \
- ATTR_INIT (set_validation_algorithm, \
- protocol##_set_validation_algorithm), \
- ATTR_INIT (get_key_id, protocol##_get_key_id), \
- ATTR_INIT (set_key_id, protocol##_set_key_id), \
- ATTR_INIT (get_signature, protocol##_get_signature), \
- ATTR_INIT (set_signature_gap, protocol##_set_signature_gap), \
- ATTR_INIT (set_signature_size, protocol##_set_signature_size), \
- ATTR_INIT (get_signature_gap, protocol##_get_signature_gap), \
- }
-
-/**
- * @brief Protocol-independent packet operations VFT
- * NOTE: The following declarations should be kept in order
- */
-extern const hicn_ops_t *const hicn_ops_vft[];
-
-/*
- * Helpers for writing recursive protocol operations on packet headers
- *
- * NOTE : we cannot use a shift operation as IPPROTO_NONE != 0 (and 0 is
- * IPv4...)
- */
-always_inline hicn_type_t
-TYPE_POP (hicn_type_t type)
-{
-#ifndef _WIN32
- return HICN_TYPE (type.l2, type.l3, type.l4, IPPROTO_NONE);
-#else
- hicn_type_t new_type;
- new_type.l1 = type.l2;
- new_type.l2 = type.l3;
- new_type.l3 = type.l4;
- new_type.l4 = IPPROTO_NONE;
- return new_type;
-#endif
-}
-
-always_inline hicn_protocol_t *
-PAYLOAD (hicn_type_t type, const hicn_protocol_t *h)
-{
- size_t header_length;
- int rc =
- hicn_ops_vft[type.l1]->get_current_header_length (type, h, &header_length);
- if (rc < 0)
- return NULL;
- return (hicn_protocol_t *) ((u8 *) h + header_length);
-}
-
-#define CHILD_OPS(f, type, h, ...) \
- (hicn_ops_vft[type.l2]->f (TYPE_POP (type), PAYLOAD (type, h), \
- ##__VA_ARGS__))
-
-/** Shortcuts to entry points in VFT */
-#define HICN_OPS4 hicn_ops_vft[IPPROTO_IP]
-#define HICN_OPS6 hicn_ops_vft[IPPROTO_IPV6]
-
-/* Helpers for simple declarations */
-
-#define DECLARE_init_packet_header(protocol, error) \
- int protocol##_init_packet_header (hicn_type_t type, hicn_protocol_t *h) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_interest_locator(protocol, error) \
- int protocol##_get_interest_locator ( \
- hicn_type_t type, const hicn_protocol_t *h, ip46_address_t *ip_address) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_interest_locator(protocol, error) \
- int protocol##_set_interest_locator (hicn_type_t type, hicn_protocol_t *h, \
- const ip46_address_t *ip_address) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_interest_name(protocol, error) \
- int protocol##_get_interest_name ( \
- hicn_type_t type, const hicn_protocol_t *h, hicn_name_t *name) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_interest_name(protocol, error) \
- int protocol##_set_interest_name (hicn_type_t type, hicn_protocol_t *h, \
- const hicn_name_t *name) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_interest_name_suffix(protocol, error) \
- int protocol##_get_interest_name_suffix ( \
- hicn_type_t type, const hicn_protocol_t *h, hicn_name_suffix_t *suffix) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_interest_name_suffix(protocol, error) \
- int protocol##_set_interest_name_suffix ( \
- hicn_type_t type, hicn_protocol_t *h, const hicn_name_suffix_t *suffix) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_mark_packet_as_interest(protocol, error) \
- int protocol##_mark_packet_as_interest (hicn_type_t type, \
- hicn_protocol_t *h) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_mark_packet_as_data(protocol, error) \
- int protocol##_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_reset_interest_for_hash(protocol, error) \
- int protocol##_reset_interest_for_hash (hicn_type_t type, \
- hicn_protocol_t *h) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_data_locator(protocol, error) \
- int protocol##_get_data_locator ( \
- hicn_type_t type, const hicn_protocol_t *h, ip46_address_t *ip_address) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_data_locator(protocol, error) \
- int protocol##_set_data_locator (hicn_type_t type, hicn_protocol_t *h, \
- const ip46_address_t *ip_address) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_data_name(protocol, error) \
- int protocol##_get_data_name (hicn_type_t type, const hicn_protocol_t *h, \
- hicn_name_t *name) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_data_name(protocol, error) \
- int protocol##_set_data_name (hicn_type_t type, hicn_protocol_t *h, \
- const hicn_name_t *name) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_data_name_suffix(protocol, error) \
- int protocol##_get_data_name_suffix ( \
- hicn_type_t type, const hicn_protocol_t *h, hicn_name_suffix_t *suffix) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_data_name_suffix(protocol, error) \
- int protocol##_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h, \
- const hicn_name_suffix_t *suffix) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_data_pathlabel(protocol, error) \
- int protocol##_get_data_pathlabel ( \
- hicn_type_t type, const hicn_protocol_t *h, u32 *pathlabel) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_data_pathlabel(protocol, error) \
- int protocol##_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, \
- const u32 pathlabel) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_update_data_pathlabel(protocol, error) \
- int protocol##_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, \
- const hicn_faceid_t face_id) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_reset_data_for_hash(protocol, error) \
- int protocol##_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_lifetime(protocol, error) \
- int protocol##_get_lifetime (hicn_type_t type, const hicn_protocol_t *h, \
- hicn_lifetime_t *lifetime) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_lifetime(protocol, error) \
- int protocol##_set_lifetime (hicn_type_t type, hicn_protocol_t *h, \
- const hicn_lifetime_t lifetime) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_update_checksums(protocol, error) \
- int protocol##_update_checksums (hicn_type_t type, hicn_protocol_t *h, \
- u16 partial_csum, size_t payload_length) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_verify_checksums(protocol, error) \
- int protocol##_verify_checksums (hicn_type_t type, hicn_protocol_t *h, \
- u16 partial_csum, size_t payload_length) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_rewrite_interest(protocol, error) \
- int protocol##_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, \
- const ip46_address_t *addr_new, \
- ip46_address_t *addr_old) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_rewrite_data(protocol, error) \
- int protocol##_rewrite_data ( \
- hicn_type_t type, hicn_protocol_t *h, const ip46_address_t *addr_new, \
- ip46_address_t *addr_old, const hicn_faceid_t face_id, u8 reset_pl) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_length(protocol, error) \
- int protocol##_get_length (hicn_type_t type, const hicn_protocol_t *h, \
- size_t *length) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_current_header_length(protocol, error) \
- int protocol##_get_current_header_length ( \
- hicn_type_t type, const hicn_protocol_t *h, size_t *header_length) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_header_length(protocol, error) \
- int protocol##_get_header_length ( \
- hicn_type_t type, const hicn_protocol_t *h, size_t *header_length) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_payload_length(protocol, error) \
- int protocol##_get_payload_length ( \
- hicn_type_t type, const hicn_protocol_t *h, size_t *payload_length) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_payload_length(protocol, error) \
- int protocol##_set_payload_length (hicn_type_t type, hicn_protocol_t *h, \
- size_t payload_length) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_signature_size(protocol, error) \
- int protocol##_get_signature_size ( \
- hicn_type_t type, const hicn_protocol_t *h, size_t *signature_size) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_signature_size(protocol, error) \
- int protocol##_set_signature_size (hicn_type_t type, hicn_protocol_t *h, \
- size_t signature_size) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_signature_gap(protocol, error) \
- int protocol##_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, \
- uint8_t signature_size) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_signature_gap(protocol, error) \
- int protocol##_get_signature_gap ( \
- hicn_type_t type, const hicn_protocol_t *h, uint8_t *signature_size) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_signature_timestamp(protocol, error) \
- int protocol##_set_signature_timestamp ( \
- hicn_type_t type, hicn_protocol_t *h, uint64_t signature_timestamp) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_signature_timestamp(protocol, error) \
- int protocol##_get_signature_timestamp (hicn_type_t type, \
- const hicn_protocol_t *h, \
- uint64_t *signature_timestamp) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_validation_algorithm(protocol, error) \
- int protocol##_set_validation_algorithm ( \
- hicn_type_t type, hicn_protocol_t *h, uint8_t validation_algorithm) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_validation_algorithm(protocol, error) \
- int protocol##_get_validation_algorithm (hicn_type_t type, \
- const hicn_protocol_t *h, \
- uint8_t *validation_algorithm) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_set_key_id(protocol, error) \
- int protocol##_set_key_id (hicn_type_t type, hicn_protocol_t *h, \
- uint8_t *key_id) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_key_id(protocol, error) \
- int protocol##_get_key_id (hicn_type_t type, hicn_protocol_t *h, \
- uint8_t **key_id, uint8_t *key_id_size) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#define DECLARE_get_signature(protocol, error) \
- int protocol##_get_signature (hicn_type_t type, hicn_protocol_t *h, \
- uint8_t **signature) \
- { \
- return HICN_LIB_ERROR_##error; \
- }
-
-#endif /* HICN_OPS_H */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/lib/includes/hicn/packet.h b/lib/includes/hicn/packet.h
new file mode 100644
index 000000000..c4a0dd80e
--- /dev/null
+++ b/lib/includes/hicn/packet.h
@@ -0,0 +1,668 @@
+/*
+ * Copyright (c) 2017-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file compat.h
+ * @brief Implementation of the compatibility layer.
+ *
+ * The structure of the core API has evolved to support operations of a variety
+ * of packet formats in addition to IPv4/TCP and IPv6/TCP, namely with the use
+ * of ICMP for signalization and AH headers for integrity. The new API format
+ * has been designed to scale better with the multiplicity of packet formats,
+ * and provide a unified interface on top. We maintain an interface for the
+ * former API in this file, which mainly acts as a wrapper on top of new calls.
+ *
+ */
+#ifndef HICN_PACKET_H
+#define HICN_PACKET_H
+
+#include <limits.h>
+
+#include <hicn/base.h>
+#include <hicn/common.h>
+#include <hicn/name.h>
+
+/* Packet buffer definition */
+
+typedef struct __attribute__ ((packed))
+{
+ /*
+ * We store an offset to the packet header.
+ *
+ * NOTE: This is a signed value.
+ *
+ * In most implementations, the buffer located closeby to the current packet
+ * buffer (eg msgbuf in hicn-light, and vlib buffer in VPP), and an int16_t
+ * would be sufficient. This is not the case in transport though and we have
+ * to use a full integer.
+ */
+ int64_t header;
+
+ /*
+ * Packet format [4]
+ */
+ hicn_packet_format_t format;
+
+ /*
+ * Packet type [2]
+ */
+ uint16_t type;
+
+ /*
+ * Buffer size [2]
+ */
+ uint16_t buffer_size;
+
+ /*
+ * Packet len [2]
+ */
+ uint16_t len;
+
+#ifdef OPAQUE_IP
+ /* Interest or data packet */
+ union
+ {
+ uint16_t ipv4;
+ uint16_t ipv6;
+ };
+#endif /* OPAQUE_IP */
+ /*
+ * L4 offset [1]
+ */
+ union
+ {
+ uint8_t tcp;
+ uint8_t udp;
+ uint8_t icmp;
+ };
+ /*
+ * New header offset [1]
+ */
+ uint8_t newhdr;
+
+ /*
+ * AH offset [2]
+ */
+ uint16_t ah;
+
+ /*
+ * Payload offset [2]
+ */
+ uint16_t payload;
+} hicn_packet_buffer_t;
+
+static_assert (sizeof (hicn_packet_buffer_t) == 24, "");
+
+static inline uint8_t *
+_pkbuf_get_ipv4 (const hicn_packet_buffer_t *pkbuf)
+{
+#ifdef OPAQUE_IP
+ uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->ipv4;
+#else
+ uint8_t *header = (uint8_t *) pkbuf + pkbuf->header;
+#endif
+ _ASSERT (header);
+ return header;
+}
+#define pkbuf_get_ipv4(pkbuf) ((_ipv4_header_t *) (_pkbuf_get_ipv4 (pkbuf)))
+
+static inline uint8_t *
+_pkbuf_get_ipv6 (const hicn_packet_buffer_t *pkbuf)
+{
+#ifdef OPAQUE_IP
+ uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->ipv6;
+#else
+ uint8_t *header = (uint8_t *) pkbuf + pkbuf->header;
+#endif
+ assert (header);
+ return header;
+}
+#define pkbuf_get_ipv6(pkbuf) ((_ipv6_header_t *) (_pkbuf_get_ipv6 (pkbuf)))
+
+static inline uint8_t *
+_pkbuf_get_tcp (const hicn_packet_buffer_t *pkbuf)
+{
+ uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->tcp;
+ assert (header);
+ return header;
+}
+#define pkbuf_get_tcp(pkbuf) ((_tcp_header_t *) (_pkbuf_get_tcp (pkbuf)))
+
+static inline uint8_t *
+_pkbuf_get_udp (const hicn_packet_buffer_t *pkbuf)
+{
+ uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->udp;
+ assert (header);
+ return header;
+}
+#define pkbuf_get_udp(pkbuf) ((_udp_header_t *) (_pkbuf_get_udp (pkbuf)))
+
+static inline uint8_t *
+_pkbuf_get_icmp (const hicn_packet_buffer_t *pkbuf)
+{
+ uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->icmp;
+ assert (header);
+ return header;
+}
+#define pkbuf_get_icmp(pkbuf) ((_icmp_header_t *) (_pkbuf_get_icmp (pkbuf)))
+
+static inline uint8_t *
+_pkbuf_get_ah (const hicn_packet_buffer_t *pkbuf)
+{
+ uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->ah;
+ assert (header);
+ return header;
+}
+#define pkbuf_get_ah(pkbuf) ((_ah_header_t *) (_pkbuf_get_ah (pkbuf)))
+
+static inline uint8_t *
+_pkbuf_get_new (const hicn_packet_buffer_t *pkbuf)
+{
+ uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->newhdr;
+ assert (header);
+ return header;
+}
+#define pkbuf_get_new(pkbuf) ((_new_header_t *) (_pkbuf_get_new (pkbuf)))
+
+static inline uint8_t *
+pkbuf_get_header (const hicn_packet_buffer_t *pkbuf)
+{
+ uint8_t *header = (uint8_t *) pkbuf + pkbuf->header;
+ assert (header);
+ return header;
+}
+
+static inline void
+pkbuf_set_header (hicn_packet_buffer_t *pkbuf, uint8_t *header)
+{
+ ssize_t offset = header - (uint8_t *) pkbuf;
+ assert (offset < INT64_MAX);
+ assert (offset > INT64_MIN);
+ pkbuf->header = (int64_t) offset;
+}
+
+/*
+ * Packet buffer operations
+ *
+ * A packet buffer can either be initialized either:
+ *
+ * 1) from an empty buffer (packet crafting).
+ *
+ * #define MTU 1500
+ * size_t size = MTU;
+ * u8 buffer[MTU];
+ *
+ * hicn_packet_t pkbuf;
+ * hicn_packet_set_format(&pkbuf, HICN_PACKET_FORMAT_NEW);
+ * hicn_packet_set_buffer(&pkbuf, &buffer, size);
+ * hicn_packet_init_header(&pkbuf, 0);
+ *
+ * An empty (but correct) packet is not available in the buffer, ready to be
+ * modified and/or sent.
+ *
+ * 2) from an existing buffer (packet reception):
+ *
+ * hicn_packet_t pkbuf;
+ * hicn_packet_set_buffer(&pkbuf, &buffer, size);
+ * hicn_packet_analyze(&pkbuf);
+ *
+ * It is then possible to retrieve properties of the packet such as format and
+ * type (interest, data, etc.).
+ *
+ * hicn_packet_get_format(&pkbuf);
+ * hicn_packet_get_type(&pkbuf);
+ *
+ * */
+
+hicn_packet_format_t
+hicn_packet_get_format (const hicn_packet_buffer_t *pkbuf);
+
+void hicn_packet_set_format (hicn_packet_buffer_t *pkbuf,
+ hicn_packet_format_t format);
+
+hicn_packet_type_t hicn_packet_get_type (const hicn_packet_buffer_t *pkbuf);
+
+void hicn_packet_initialize_type (hicn_packet_buffer_t *pkbuf,
+ hicn_packet_type_t type);
+
+void hicn_packet_set_type (hicn_packet_buffer_t *pkbuf,
+ hicn_packet_type_t type);
+
+bool hicn_packet_is_interest (const hicn_packet_buffer_t *pkbuf);
+
+bool hicn_packet_is_data (const hicn_packet_buffer_t *pkbuf);
+
+bool hicn_packet_is_undefined (const hicn_packet_buffer_t *pkbuf);
+
+/**
+ * @brief Initialize the buffer from packet buffer metadata (builds a valid
+ * packet).
+ * @param [in] pkbuf - hICN packet buffer
+ * @return hICN error code
+ *
+ * Packet type, format, and a buffer are required.
+ */
+int hicn_packet_init_header (hicn_packet_buffer_t *pkbuf,
+ size_t additional_header_size);
+
+/**
+ * @brief Reset information stored in the packet header.
+ * @param [in] pkbuf - hICN packet buffer
+ * @return hICN error code
+ */
+int hicn_packet_reset (hicn_packet_buffer_t *pkbuf);
+
+/**
+ * @brief Analyze buffer to populate metadata in packet buffer.
+ * @param [in] pkbuf - hICN packet buffer
+ * @return hICN error code
+ */
+int hicn_packet_analyze (hicn_packet_buffer_t *pkbuf);
+
+/**
+ * @brief Initialize hicn packet storage space with a buffer
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] buffer - Packet storage buffer
+ * @param [in] analyze - Flag indicating whether to analyze the buffer
+ * content to populate packet format, header's offsets, etc.
+ * @return hICN error code
+ */
+int hicn_packet_set_buffer (hicn_packet_buffer_t *pkbuf, u8 *buffer,
+ uint16_t buffer_size, uint16_t len);
+
+/**
+ * @brief Retrieve the storage buffer.
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [out] buffer - Packet buffer
+ * @param [out] buffer_size - Packet buffer size
+ * @return Pointer to storage buffer (this only returns the pointer; no copy is
+ * made)
+ */
+int hicn_packet_get_buffer (const hicn_packet_buffer_t *pkbuf, u8 **buffer,
+ uint16_t *buffer_size, uint16_t *len);
+
+/**
+ * @brief Retrieve the packet length
+ * @param [in] pkbuf - hICN packet buffer
+ * @return Length of the stored packet
+ */
+size_t hicn_packet_get_len (const hicn_packet_buffer_t *pkbuf);
+
+/**
+ * @brief Set the packet length
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] len - hICN packet length
+ * @return None
+ */
+int hicn_packet_set_len (hicn_packet_buffer_t *pkbuf, size_t len);
+
+/**
+ * @brief Return total length of hicn headers (before payload)
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [out] len - Total headers length
+ * @return Headers' len
+ */
+int hicn_packet_get_header_len (const hicn_packet_buffer_t *pkbuf,
+ size_t *len);
+
+/**
+ * @brief Return the length of hICN payload in the packet.
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [out] len - hICN payload length
+ * @return Payload len
+ */
+int hicn_packet_get_payload_len (const hicn_packet_buffer_t *pkbuf,
+ size_t *len);
+
+/**
+ * @brief Sets the payload of a packet
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] packet - packet header
+ * @param [in] payload - payload to set
+ * @param [in] payload_length - size of the payload to set
+ * @return hICN error code
+ *
+ * NOTE:
+ * - The buffer holding payload is assumed sufficiently large
+ * - This function updates header fields with the new length, but no checksum.
+ */
+int hicn_packet_set_payload (const hicn_packet_buffer_t *pkbuf,
+ const u8 *payload, u16 payload_length);
+
+/**
+ * @brief Retrieves the payload of a packet
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] packet - packet header
+ * @param [out] payload - pointer to buffer for storing the result
+ * @param [out] payload_length - size of the retreived payload
+ * @param [in] hard_copy - Flag : if true (eg. 1), a copy of the payload is
+ * made into the payload buffer, otherwise (0) the pointer is changed to point
+ * to the payload offset in the packet.
+ * @return hICN error code
+ *
+ * NOTE:
+ * - The buffer holding payload is assumed sufficiently large
+ */
+int hicn_packet_get_payload (const hicn_packet_buffer_t *pkbuf, u8 **payload,
+ size_t *payload_size, bool hard_copy);
+
+/* Header fields manipulation */
+
+/**
+ * @brief Return total length of hicn headers (but signature payload)
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [out] header_length - Total length of headers
+ * @return hICN error code
+ */
+int hicn_packet_get_header_length_from_format (hicn_packet_format_t format,
+ size_t *header_length);
+
+/**
+ * @brief Sets payload length
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] packet - packet header
+ * @param [in] payload_length - payload length
+ * @return hICN error code
+ */
+int hicn_packet_set_payload_length (const hicn_packet_buffer_t *pkbuf,
+ const size_t payload_length);
+
+/**
+ * @brief Compare two hICN packets
+ * @param [in] packet_1 - First packet
+ * @param [in] packet_2 - Second packet
+ * @return 0 if both packets are considered equal, any other value otherwise.
+ */
+int hicn_packet_compare (const hicn_packet_buffer_t *pkbuf11,
+ const hicn_packet_buffer_t *pkbuf22);
+
+/**
+ * @brief Retrieve the name of an interest/data packet
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] packet - packet header
+ * @param [out] name - name holding the result
+ * @return hICN error code
+ */
+int hicn_packet_get_name (const hicn_packet_buffer_t *pkbuf,
+ hicn_name_t *name);
+
+/**
+ * @brief Sets the name of an interest/data packet
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] packet - packet header
+ * @param [in] name - name to set into packet
+ * @return hICN error code
+ */
+int hicn_packet_set_name (const hicn_packet_buffer_t *pkbuf,
+ const hicn_name_t *name);
+
+/**
+ * @brief Retrieve the locator of an interest / data packet
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] packet - packet header
+ * @param [out] ip_address - retrieved locator
+ * @return hICN error code
+ */
+int hicn_packet_get_locator (const hicn_packet_buffer_t *pkbuf,
+ hicn_ip_address_t *prefix);
+
+/**
+ * @brief Sets the locator of an interest / data packet
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] packet - packet header
+ * @param [out] ip_address - retrieved locator
+ * @return hICN error code
+ */
+int hicn_packet_set_locator (const hicn_packet_buffer_t *pkbuf,
+ const hicn_ip_address_t *prefix);
+
+int hicn_packet_save_header (const hicn_packet_buffer_t *pkbuf, u8 *header,
+ size_t *header_len, bool copy_ah);
+
+int hicn_packet_load_header (const hicn_packet_buffer_t *pkbuf,
+ const u8 *header, size_t header_len);
+
+int hicn_packet_get_lifetime (const hicn_packet_buffer_t *pkbuf,
+ u32 *lifetime);
+int hicn_packet_set_lifetime (const hicn_packet_buffer_t *pkbuf, u32 lifetime);
+
+/* Interest */
+int hicn_interest_get_name (const hicn_packet_buffer_t *pkbuf,
+ hicn_name_t *name);
+int hicn_interest_set_name (const hicn_packet_buffer_t *pkbuf,
+ const hicn_name_t *name);
+int hicn_interest_get_locator (const hicn_packet_buffer_t *pkbuf,
+ hicn_ip_address_t *prefix);
+int hicn_interest_set_locator (const hicn_packet_buffer_t *pkbuf,
+ const hicn_ip_address_t *prefix);
+int hicn_interest_compare (const hicn_packet_buffer_t *pkbuf11,
+ const hicn_packet_buffer_t *pkbuf2);
+int hicn_interest_set_lifetime (const hicn_packet_buffer_t *pkbuf,
+ u32 lifetime);
+int hicn_interest_get_lifetime (const hicn_packet_buffer_t *pkbuf,
+ u32 *lifetime);
+int hicn_interest_get_header_length (const hicn_packet_buffer_t *pkbuf,
+ size_t *header_length);
+int hicn_interest_get_payload_length (const hicn_packet_buffer_t *pkbuf,
+ size_t *payload_length);
+int hicn_interest_set_payload (const hicn_packet_buffer_t *pkbuf,
+ const u8 *payload, size_t payload_length);
+int hicn_interest_get_payload (const hicn_packet_buffer_t *pkbuf, u8 **payload,
+ size_t *payload_size, bool hard_copy);
+int hicn_interest_reset_for_hash (hicn_packet_buffer_t *pkbuf);
+
+/* Data */
+
+int hicn_data_get_name (const hicn_packet_buffer_t *pkbuf, hicn_name_t *name);
+int hicn_data_set_name (const hicn_packet_buffer_t *pkbuf,
+ const hicn_name_t *name);
+int hicn_data_get_locator (const hicn_packet_buffer_t *pkbuf,
+ hicn_ip_address_t *prefix);
+int hicn_data_set_locator (const hicn_packet_buffer_t *pkbuf,
+ const hicn_ip_address_t *prefix);
+int hicn_data_compare (const hicn_packet_buffer_t *pkbuf11,
+ const hicn_packet_buffer_t *pkbuf22);
+int hicn_data_get_expiry_time (const hicn_packet_buffer_t *pkbuf,
+ u32 *expiry_time);
+int hicn_data_set_expiry_time (const hicn_packet_buffer_t *pkbuf,
+ u32 expiry_time);
+int hicn_data_get_header_length (const hicn_packet_buffer_t *pkbuf,
+ size_t *header_length);
+int hicn_data_get_payload_length (const hicn_packet_buffer_t *pkbuf,
+ size_t *payload_length);
+
+/* Path label */
+
+/**
+ * @brief Returns the path label from a data packet
+ * @param [in] pkbuf - packet buffer
+ * @param [in] hdr - packet header
+ * @param [in] path_label - pointer in which to store the path label value
+ * @return hICN error code
+ */
+int hicn_data_get_path_label (const hicn_packet_buffer_t *pkbufdr,
+ hicn_path_label_t *path_label);
+
+/**
+ * @brief Returns the path label from a packet
+ * @param [in] pkbuf - packet buffer
+ * @param [in] hdr - packet header
+ * @param [in] path_label - pointer in which to store the path label value
+ * @return hICN error code
+ */
+int hicn_get_path_label (const hicn_packet_buffer_t *pkbufdr,
+ hicn_path_label_t *path_label);
+
+int hicn_data_set_path_label (const hicn_packet_buffer_t *pkbuf,
+ hicn_path_label_t path_label);
+
+/* Data specific flags */
+
+int hicn_packet_get_payload_type (const hicn_packet_buffer_t *pkbuf,
+
+ hicn_payload_type_t *payload_type);
+int hicn_packet_set_payload_type (const hicn_packet_buffer_t *pkbuf,
+
+ const hicn_payload_type_t payload_type);
+
+int hicn_data_get_payload (const hicn_packet_buffer_t *pkbuf, u8 **payload,
+ size_t *payload_size, bool hard_copy);
+int hicn_data_set_payload (const hicn_packet_buffer_t *pkbuf,
+ const u8 *payload, size_t payload_length);
+int hicn_data_get_payload_type (hicn_payload_type_t *payload_type);
+int hicn_data_set_payload_type (hicn_payload_type_t payload_type);
+int hicn_data_reset_for_hash (hicn_packet_buffer_t *pkbuf);
+int hicn_data_is_last (const hicn_packet_buffer_t *pkbuf, int *is_last);
+int hicn_data_set_last (const hicn_packet_buffer_t *pkbuf);
+
+/* Security */
+
+/**
+ * @brief Retrieves the signature size
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] packet - packet header
+ * @param [out] bytes - Retrieved signature size
+ * @return hICN error code
+ */
+int hicn_packet_get_signature_size (const hicn_packet_buffer_t *pkbuf,
+ size_t *bytes);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] packet - packet header
+ * @param [in] bytes - Retrieved signature size
+ * @return hICN error code
+ */
+int hicn_packet_set_signature_size (const hicn_packet_buffer_t *pkbuf,
+ size_t bytes);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] packet - packet header
+ * @param [in] signature_timestamp - Signature timestamp to set
+ * @return hICN error code
+ */
+int hicn_packet_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf,
+ uint64_t signature_timestamp);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] packet - packet header
+ * @param [out] signature_timestamp - Retrieved signature timestamp
+ * @return hICN error code
+ */
+int hicn_packet_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf,
+ uint64_t *signature_timestamp);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] packet - packet header
+ * @param [in] validation_algorithm - Validation algorithm to set
+ * @return hICN error code
+ */
+int hicn_packet_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf,
+ uint8_t validation_algorithm);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] packet - packet header
+ * @param [out] validation_algorithm - Retrieved validation algorithm
+ * @return hICN error code
+ */
+int hicn_packet_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf,
+ uint8_t *validation_algorithm);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] packet - packet header
+ * @param [in] key_id - Key id to set
+ * @param [in] key_len - Key length
+ * @return hICN error code
+ */
+int hicn_packet_set_key_id (const hicn_packet_buffer_t *pkbuf, uint8_t *key_id,
+ size_t key_len);
+
+/**
+ * @brief Sets the signature size
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] packet - packet header
+ * @param [out] key_id - Retrieved key id
+ * @return hICN error code
+ */
+int hicn_packet_get_key_id (const hicn_packet_buffer_t *pkbuf,
+ uint8_t **key_id, uint8_t *key_id_length);
+
+int hicn_packet_get_signature (const hicn_packet_buffer_t *pkbuf,
+ uint8_t **sign_buf);
+
+int hicn_packet_get_signature_padding (const hicn_packet_buffer_t *pkbuf,
+ size_t *bytes);
+int hicn_packet_set_signature_padding (const hicn_packet_buffer_t *pkbuf,
+ size_t bytes);
+
+/* Checksums */
+
+/**
+ * @brief Update checksums in packet headers
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] packet - packet header
+ * @return hICN error code
+ */
+int hicn_packet_compute_checksum (const hicn_packet_buffer_t *pkbuf);
+
+/**
+ * @brief compute the checksum of the packet header, adding init_sum to the
+ * final value
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] packet - packet header
+ * @param [in] init_sum - value to add to the final checksum
+ * @return hICN error code
+ */
+int hicn_packet_compute_header_checksum (const hicn_packet_buffer_t *pkbuf,
+ u16 init_sum);
+
+/**
+ * @brief Verify checksums in packet headers
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] packet - packet header
+ * @return hICN error code
+ */
+int hicn_packet_check_integrity_no_payload (const hicn_packet_buffer_t *pkbuf,
+ u16 init_sum);
+
+int hicn_interest_rewrite (const hicn_packet_buffer_t *pkbuf,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old);
+
+int hicn_data_rewrite (const hicn_packet_buffer_t *pkbuf,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old,
+ const hicn_faceid_t face_id, u8 reset_pl);
+
+#endif /* HICN_PACKET_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/includes/hicn/policy.h b/lib/includes/hicn/policy.h
index e29888bd2..50b771537 100644
--- a/lib/includes/hicn/policy.h
+++ b/lib/includes/hicn/policy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -30,37 +30,44 @@
/* POLICY TAG */
-#define foreach_policy_tag \
- /* Interface type */ \
- _(WIRED, 'E') \
- _(WIFI, 'W') \
- _(CELLULAR, 'C') \
- /* QoS */ \
- _(BEST_EFFORT, 'b') \
- _(REALTIME, 'r') \
- _(MULTIPATH, 'M') \
- /* Security */ \
- _(TRUSTED, 'T')
-
-typedef enum {
-#define _(x, y) POLICY_TAG_ ## x,
-foreach_policy_tag
+#define foreach_policy_tag \
+ /* Interface type */ \
+ _ (WIRED, 'E') \
+ _ (WIFI, 'W') \
+ _ (CELLULAR, 'C') \
+ /* QoS */ \
+ _ (BEST_EFFORT, 'b') \
+ _ (REALTIME, 'r') \
+ _ (MULTIPATH, 'M') \
+ /* Security */ \
+ _ (TRUSTED, 'T')
+
+typedef enum
+{
+#define _(x, y) POLICY_TAG_##x,
+ foreach_policy_tag
#undef _
POLICY_TAG_N
} policy_tag_t;
+#define IS_VALID_POLICY_TAG(x) (x != POLICY_TAG_N)
+
#define MAXSZ_POLICY_TAG_ 11
-#define MAXSZ_POLICY_TAG MAXSZ_POLICY_TAG_ + 1
+#define MAXSZ_POLICY_TAG MAXSZ_POLICY_TAG_ + 1
-extern const char * policy_tag_str[];
+extern const char *policy_tag_str[];
extern const char policy_tag_short_str[];
-static inline
-policy_tag_t
-policy_tag_from_str(const char * str)
+static inline policy_tag_t
+policy_tag_from_str (const char *str)
{
-#define _(x, y) if (strcasecmp(str, policy_tag_str[POLICY_TAG_ ## x] ) == 0) { return POLICY_TAG_ ## x; } else
-foreach_policy_tag
+#define _(x, y) \
+ if (strcasecmp (str, policy_tag_str[POLICY_TAG_##x]) == 0) \
+ { \
+ return POLICY_TAG_##x; \
+ } \
+ else
+ foreach_policy_tag
#undef _
return POLICY_TAG_N;
}
@@ -69,182 +76,188 @@ foreach_policy_tag
typedef int policy_tags_t;
-static inline
-void policy_tags_add(policy_tags_t * tags, policy_tag_t tag)
+static inline void
+policy_tags_add (policy_tags_t *tags, policy_tag_t tag)
{
- *tags |= (1 << tag);
+ *tags |= (1 << tag);
}
-static inline
-void policy_tags_remove(policy_tags_t * tags, policy_tag_t tag)
+static inline void
+policy_tags_remove (policy_tags_t *tags, policy_tag_t tag)
{
- *tags &= ~(1 << tag);
+ *tags &= ~(1 << tag);
}
-static inline
-int policy_tags_has(policy_tags_t tags, policy_tag_t tag)
+static inline int
+policy_tags_has (policy_tags_t tags, policy_tag_t tag)
{
- return tags & (1 << tag);
+ return tags & (1 << tag);
}
-static inline
-void policy_tags_union(policy_tags_t * tags, policy_tags_t * tags_to_union)
+static inline void
+policy_tags_union (policy_tags_t *tags, policy_tags_t *tags_to_union)
{
-#define _(x, y) *tags |= policy_tags_has(*tags_to_union, POLICY_TAG_ ## x) ? (1 << POLICY_TAG_ ## x) : 0;
-foreach_policy_tag
+#define _(x, y) \
+ *tags |= policy_tags_has (*tags_to_union, POLICY_TAG_##x) ? \
+ (1 << POLICY_TAG_##x) : \
+ 0;
+ foreach_policy_tag
#undef _
}
#define POLICY_TAGS_EMPTY 0
-static inline
-int
-policy_tags_snprintf(char * s, size_t size, policy_tags_t tags)
+static inline int
+policy_tags_snprintf (char *s, size_t size, policy_tags_t tags)
{
-#define _(x, y) s[POLICY_TAG_ ## x] = policy_tags_has(tags, POLICY_TAG_ ## x) ? y : '.';
-foreach_policy_tag
+#define _(x, y) \
+ s[POLICY_TAG_##x] = policy_tags_has (tags, POLICY_TAG_##x) ? y : '.';
+ foreach_policy_tag
#undef _
s[POLICY_TAG_N] = '\0';
- return POLICY_TAG_N + 1;
+ return POLICY_TAG_N + 1;
}
#define MAXSZ_POLICY_TAGS_ POLICY_TAG_N + 1
-#define MAXSZ_POLICY_TAGS MAXSZ_POLICY_TAGS_ + 1
+#define MAXSZ_POLICY_TAGS MAXSZ_POLICY_TAGS_ + 1
/* POLICY STATE */
/* TODO vs. weight */
-#define foreach_policy_state \
- _(NEUTRAL) \
- _(REQUIRE) \
- _(PREFER) \
- _(AVOID) \
- _(PROHIBIT) \
- _(N)
-
-typedef enum {
-#define _(x) POLICY_STATE_ ## x,
-foreach_policy_state
+#define foreach_policy_state \
+ _ (NEUTRAL) \
+ _ (REQUIRE) \
+ _ (PREFER) \
+ _ (AVOID) \
+ _ (PROHIBIT) \
+ _ (N)
+
+typedef enum
+{
+#define _(x) POLICY_STATE_##x,
+ foreach_policy_state
#undef _
} policy_state_t;
#define MAXSZ_POLICY_STATE_ 8
-#define MAXSZ_POLICY_STATE MAXSZ_POLICY_STATE_ + 1
+#define MAXSZ_POLICY_STATE MAXSZ_POLICY_STATE_ + 1
+
+extern const char *policy_state_str[];
-extern const char * policy_state_str[];
+#define policy_state_str(x) policy_state_str[x]
+policy_state_t policy_state_from_str (const char *str);
/* POLICY TAG STATE */
-typedef struct {
- policy_state_t state;
- uint8_t disabled;
+typedef struct __attribute__ ((packed, aligned (1)))
+{
+ policy_state_t state;
+ uint8_t disabled;
} policy_tag_state_t;
#define MAXSZ_POLICY_TAG_STATE_ 8
-#define MAXSZ_POLICY_TAG_STATE MAXSZ_POLICY_TAG_STATE_ + 1
-
-int policy_tag_state_snprintf(char * s, size_t size, const policy_tag_state_t * tag_state);
+#define MAXSZ_POLICY_TAG_STATE MAXSZ_POLICY_TAG_STATE_ + 1
+int policy_tag_state_snprintf (char *s, size_t size,
+ const policy_tag_state_t *tag_state);
/* INTERFACE STATS */
-typedef struct {
- float throughput;
- float latency;
- float loss_rate;
+typedef struct
+{
+ float throughput;
+ float latency;
+ float loss_rate;
} interface_stats_t;
-#define INTERFACE_STATS_NONE { \
- .throughput = 0, \
- .latency = 0, \
- .loss_rate = 0, \
-}
-
+#define INTERFACE_STATS_EMPTY \
+ { \
+ .throughput = 0, .latency = 0, .loss_rate = 0, \
+ }
/* POLICY STATS */
-typedef struct {
- interface_stats_t wired;
- interface_stats_t wifi;
- interface_stats_t cellular;
- interface_stats_t all;
+typedef struct
+{
+ interface_stats_t wired;
+ interface_stats_t wifi;
+ interface_stats_t cellular;
+ interface_stats_t all;
} policy_stats_t;
-#define POLICY_STATS_NONE { \
- .wired = INTERFACE_STATS_NONE, \
- .wifi = INTERFACE_STATS_NONE, \
- .cellular = INTERFACE_STATS_NONE, \
- .all = INTERFACE_STATS_NONE, \
-}
+#define POLICY_STATS_EMPTY \
+ (policy_stats_t) \
+ { \
+ .wired = INTERFACE_STATS_EMPTY, .wifi = INTERFACE_STATS_EMPTY, \
+ .cellular = INTERFACE_STATS_EMPTY, .all = INTERFACE_STATS_EMPTY, \
+ }
-typedef struct {
- uint32_t num_packets;
- uint32_t num_bytes;
- uint32_t num_losses;
- uint32_t latency_idle;
+typedef struct
+{
+ uint32_t num_packets;
+ uint32_t num_bytes;
+ uint32_t num_losses;
+ uint32_t latency_idle;
} interface_counters_t;
-#define INTERFACE_COUNTERS_NONE { \
- .num_packets = 0, \
- .num_bytes = 0, \
- .num_losses = 0, \
- .latency_idle = 0, \
-}
+#define INTERFACE_COUNTERS_EMPTY \
+ { \
+ .num_packets = 0, .num_bytes = 0, .num_losses = 0, .latency_idle = 0, \
+ }
-typedef struct {
- interface_counters_t wired;
- interface_counters_t wifi;
- interface_counters_t cellular;
- interface_counters_t all;
- uint64_t last_update;
+typedef struct
+{
+ interface_counters_t wired;
+ interface_counters_t wifi;
+ interface_counters_t cellular;
+ interface_counters_t all;
+ uint64_t last_update;
} policy_counters_t;
-#define POLICY_COUNTERS_NONE (policy_counters_t) { \
- .wired = INTERFACE_COUNTERS_NONE, \
- .wifi = INTERFACE_COUNTERS_NONE, \
- .cellular = INTERFACE_COUNTERS_NONE, \
- .all = INTERFACE_COUNTERS_NONE, \
- .last_update = 0, \
-}
+#define POLICY_COUNTERS_EMPTY \
+ (policy_counters_t) \
+ { \
+ .wired = INTERFACE_COUNTERS_EMPTY, .wifi = INTERFACE_COUNTERS_EMPTY, \
+ .cellular = INTERFACE_COUNTERS_EMPTY, .all = INTERFACE_COUNTERS_EMPTY, \
+ .last_update = 0, \
+ }
/* POLICY */
#define APP_NAME_LEN 128
-typedef struct {
- char app_name[APP_NAME_LEN];
- policy_tag_state_t tags[POLICY_TAG_N];
- policy_stats_t stats;
+typedef struct
+{
+ char app_name[APP_NAME_LEN];
+ policy_tag_state_t tags[POLICY_TAG_N];
+ policy_stats_t stats;
} hicn_policy_t;
-static const hicn_policy_t POLICY_NONE = {
+static const hicn_policy_t POLICY_EMPTY = {
.app_name = { 0 },
.tags = {
-#ifdef __ANDROID__
#define _(x, y) { POLICY_STATE_NEUTRAL, 0 },
-#else
-#define _(x, y) [POLICY_TAG_ ## x] = { POLICY_STATE_NEUTRAL, 0 },
-#endif
foreach_policy_tag
#undef _
},
- .stats = POLICY_STATS_NONE,
+ .stats = POLICY_STATS_EMPTY,
};
-
/* POLICY DESCRIPTION */
#define PFX_STRLEN 4 /* eg. /128 */
-typedef struct {
- int family;
- union {
- char ipv4_prefix[INET_ADDRSTRLEN + PFX_STRLEN];
- char ipv6_prefix[INET6_ADDRSTRLEN + PFX_STRLEN];
- };
- hicn_policy_t policy;
+typedef struct
+{
+ int family;
+ union
+ {
+ char ipv4_prefix[INET_ADDRSTRLEN + PFX_STRLEN];
+ char ipv6_prefix[INET6_ADDRSTRLEN + PFX_STRLEN];
+ };
+ hicn_policy_t policy;
} policy_description_t;
#endif /* HICN_POLICY_H */
diff --git a/lib/includes/hicn/protocol/ah.h b/lib/includes/hicn/protocol/ah.h
index 575da80d7..36fd7d509 100644
--- a/lib/includes/hicn/protocol/ah.h
+++ b/lib/includes/hicn/protocol/ah.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -35,19 +35,19 @@
typedef struct
{
- u8 nh; // (to match with reserved in IPSEC AH)
- u8 payloadlen; // Len of signature/HMAC in 4-bytes words (maximum size)
+ u8 nh; // To match with reserved in IPSEC AH
+ // Length of the signature field. Note that the signature might be smaller
+ // than the field: the actual size is computed from the field size and
+ // signaturePadding.
+ u8 payloadlen;
union
{
u16 reserved;
struct
{
- u8 validationAlgorithm; // As defined in parc_SignerAlgorithm.h
- u8 signatureGap; // used to match IPSEC specification and to
- // have the real size of the signature(without
- // padding). It is the result of Maximum
- // signature size - real size
+ u8 validationAlgorithm;
+ u8 signaturePadding;
};
};
union
diff --git a/lib/includes/hicn/protocol/icmp.h b/lib/includes/hicn/protocol/icmp.h
index 36954bb6d..9315e1e56 100644
--- a/lib/includes/hicn/protocol/icmp.h
+++ b/lib/includes/hicn/protocol/icmp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -34,7 +34,7 @@ typedef struct
u16 csum;
} _icmp_header_t;
-#define ICMP_HDRLEN sizeof(_icmp_header_t)
+#define ICMP_HDRLEN sizeof (_icmp_header_t)
static_assert (EXPECTED_ICMP_HDRLEN == ICMP_HDRLEN,
"Size of ICMP struct does not match its expected size.");
@@ -54,13 +54,13 @@ typedef struct
{
u16 id;
u16 sequence;
- } echo; /* echo datagram */
- u32 gateway; /* gateway address */
+ } echo; /* echo datagram */
+ u32 gateway; /* gateway address */
struct
{
u16 _unused;
u16 mtu;
- } frag; /* path mtu discovery */
+ } frag; /* path mtu discovery */
struct
{
u16 expected_lbl;
@@ -69,7 +69,7 @@ typedef struct
};
} _icmp_wldr_header_t;
-#define ICMPWLDR_HDRLEN sizeof(_icmp_wldr_header_t)
+#define ICMPWLDR_HDRLEN sizeof (_icmp_wldr_header_t)
static_assert (EXPECTED_ICMPWLDR_HDRLEN == ICMPWLDR_HDRLEN,
"Size of ICMPWLDR struct does not match its expected size.");
diff --git a/lib/includes/hicn/protocol/icmprd.h b/lib/includes/hicn/protocol/icmprd.h
index aa1fa01ae..17088c22a 100644
--- a/lib/includes/hicn/protocol/icmprd.h
+++ b/lib/includes/hicn/protocol/icmprd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -33,12 +33,12 @@ typedef struct
u8 type;
u8 code;
u16 csum;
- ip4_address_t ip;
+ ipv4_address_t ip;
_ipv4_header_t iph;
u8 data[64];
} _icmprd4_header_t;
-#define ICMPRD4_HDRLEN sizeof(_icmprd4_header_t)
+#define ICMPRD4_HDRLEN sizeof (_icmprd4_header_t)
static_assert (EXPECTED_ICMPRD4_HDRLEN == ICMPRD4_HDRLEN,
"Size of ICMPWLDR struct does not match its expected size.");
@@ -53,11 +53,11 @@ typedef struct
u8 code;
u16 csum;
u32 res;
- ip6_address_t tgt;
- ip6_address_t dst;
+ ipv6_address_t tgt;
+ ipv6_address_t dst;
} _icmprd_header_t;
-#define ICMPRD_HDRLEN sizeof(_icmprd_header_t)
+#define ICMPRD_HDRLEN sizeof (_icmprd_header_t)
static_assert (EXPECTED_ICMPRD_HDRLEN == ICMPRD_HDRLEN,
"Size of ICMPWLDR struct does not match its expected size.");
diff --git a/lib/includes/hicn/protocol/ipv4.h b/lib/includes/hicn/protocol/ipv4.h
index 8a5b6683b..89435b516 100644
--- a/lib/includes/hicn/protocol/ipv4.h
+++ b/lib/includes/hicn/protocol/ipv4.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -16,9 +16,10 @@
#ifndef HICN_PROTOCOL_IPV4
#define HICN_PROTOCOL_IPV4
+#include <hicn/util/ip_address.h>
+
#include "../base.h"
#include "../common.h"
-#include "../protocol.h"
/* Headers were adapted from linux' definitions in netinet/ip.h */
@@ -34,11 +35,11 @@ typedef struct
struct
{
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- u8 ihl:4;
- u8 version:4;
+ u8 ihl : 4;
+ u8 version : 4;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
- u8 version:4;
- u8 ihl:4;
+ u8 version : 4;
+ u8 ihl : 4;
#else
#error "Unsupported endianness"
#endif
@@ -53,13 +54,14 @@ typedef struct
u8 ttl;
u8 protocol;
u16 csum;
- ip4_address_t saddr;
- ip4_address_t daddr;
+ ipv4_address_t saddr;
+ ipv4_address_t daddr;
} _ipv4_header_t;
-#define ipv4_header_bytes(ipv4_header) (sizeof(u32) * (ipv4_header->version_ihl & 0xf))
+#define ipv4_header_bytes(ipv4_header) \
+ (sizeof (u32) * (ipv4_header->version_ihl & 0xf))
-#define IPV4_HDRLEN sizeof(_ipv4_header_t)
+#define IPV4_HDRLEN sizeof (_ipv4_header_t)
static_assert (EXPECTED_IPV4_HDRLEN == IPV4_HDRLEN,
"Size of IPV4 struct does not match its expected size.");
@@ -70,29 +72,28 @@ static_assert (EXPECTED_IPV4_HDRLEN == IPV4_HDRLEN,
typedef struct
{
- ip4_address_t ip_src;
- ip4_address_t ip_dst;
+ ipv4_address_t ip_src;
+ ipv4_address_t ip_dst;
u8 zero;
u8 protocol;
u16 size;
} ipv4_pseudo_header_t;
-#define IPV4_PSHDRLEN sizeof(ipv4_pseudo_header_t)
+#define IPV4_PSHDRLEN sizeof (ipv4_pseudo_header_t)
static_assert (EXPECTED_IPV4_PSHDRLEN == IPV4_PSHDRLEN,
"Size of IPV4_PSHDR struct does not match its expected size.");
/* Default field values */
-#define IPV4_DEFAULT_VERSION 4
-#define IPV4_DEFAULT_IHL 5
-#define IPV4_DEFAULT_TOS 0
-#define IPV4_DEFAULT_PAYLOAD_LENGTH 0
-#define IPV4_DEFAULT_ID 300
-#define IPV4_DEFAULT_FRAG_OFF 0x000
-#define IPV4_DEFAULT_TTL 64
-#define IPV4_DEFAULT_PROTOCOL IPPROTO_TCP
-#define IPV4_DEFAULT_SRC_IP 0, 0, 0, 0
-#define IPV4_DEFAULT_DST_IP 0, 0, 0, 0
-
+#define IPV4_DEFAULT_VERSION 4
+#define IPV4_DEFAULT_IHL 5
+#define IPV4_DEFAULT_TOS 0
+#define IPV4_DEFAULT_PAYLOAD_LENGTH 0
+#define IPV4_DEFAULT_ID 300
+#define IPV4_DEFAULT_FRAG_OFF 0x000
+#define IPV4_DEFAULT_TTL 64
+#define IPV4_DEFAULT_PROTOCOL IPPROTO_TCP
+#define IPV4_DEFAULT_SRC_IP 0, 0, 0, 0
+#define IPV4_DEFAULT_DST_IP 0, 0, 0, 0
#endif /* HICN_PROTOCOL_IPV4 */
diff --git a/lib/includes/hicn/protocol/ipv6.h b/lib/includes/hicn/protocol/ipv6.h
index 5a83abcae..6e8e30af3 100644
--- a/lib/includes/hicn/protocol/ipv6.h
+++ b/lib/includes/hicn/protocol/ipv6.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -16,6 +16,8 @@
#ifndef HICN_PROTOCOL_IPV6_H
#define HICN_PROTOCOL_IPV6_H
+#include <hicn/util/ip_address.h>
+
#include "../common.h"
/*
@@ -25,22 +27,26 @@
typedef struct
{
+#if 0 // TEMPORARY FIX
union
{
struct
{
- u32 version_class_flow; /* version, traffic class and 20 bits of flow-ID */
- u16 len; /* payload length */
- u8 nxt; /* next header */
- u8 hlim; /* hop limit */
+#endif
+ u32 version_class_flow; /* version, traffic class and 20 bits of flow-ID */
+ u16 len; /* payload length */
+ u8 nxt; /* next header */
+ u8 hlim; /* hop limit */
+#if 0
};
u8 vfc; /* 4 bits version, top 4 bits class */
};
- ip6_address_t saddr; /* source address */
- ip6_address_t daddr; /* destination address */
+#endif
+ ipv6_address_t saddr; /* source address */
+ ipv6_address_t daddr; /* destination address */
} _ipv6_header_t;
-#define IPV6_HDRLEN sizeof(_ipv6_header_t)
+#define IPV6_HDRLEN sizeof (_ipv6_header_t)
static_assert (EXPECTED_IPV6_HDRLEN == IPV6_HDRLEN,
"Size of IPV6 struct does not match its expected size.");
@@ -51,23 +57,23 @@ static_assert (EXPECTED_IPV6_HDRLEN == IPV6_HDRLEN,
typedef struct
{
- ip6_address_t ip_src;
- ip6_address_t ip_dst;
+ ipv6_address_t ip_src;
+ ipv6_address_t ip_dst;
u32 size;
u16 zeros;
u8 zero;
u8 protocol;
} ipv6_pseudo_header_t;
-#define IPV6_PSHDRLEN sizeof(ipv6_pseudo_header_t)
+#define IPV6_PSHDRLEN sizeof (ipv6_pseudo_header_t)
static_assert (EXPECTED_IPV6_PSHDRLEN == IPV6_PSHDRLEN,
"Size of IPV6_PSHDR struct does not match its expected size.");
/* Default field values */
-#define IPV6_DEFAULT_VERSION 6
-#define IPV6_DEFAULT_TRAFFIC_CLASS 0
-#define IPV6_DEFAULT_FLOW_LABEL 0
-#define IPV6_DEFAULT_PAYLOAD_LENGTH 0
+#define IPV6_DEFAULT_VERSION 6
+#define IPV6_DEFAULT_TRAFFIC_CLASS 0
+#define IPV6_DEFAULT_FLOW_LABEL 0
+#define IPV6_DEFAULT_PAYLOAD_LENGTH 0
#endif
diff --git a/lib/includes/hicn/protocol/new.h b/lib/includes/hicn/protocol/new.h
new file mode 100644
index 000000000..e688bef21
--- /dev/null
+++ b/lib/includes/hicn/protocol/new.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file protocol/ah.h
+ * @brief AH packet header
+ */
+#ifndef HICN_PROTOCOL_NEW_H
+#define HICN_PROTOCOL_NEW_H
+
+#include "../common.h"
+#include "../name.h"
+
+/*
+ * The length of the new header struct must be 28 bytes.
+ */
+#define EXPECTED_NEW_HDRLEN 32
+
+typedef struct
+{
+ u8 version_reserved;
+ u8 flags;
+ u16 payload_length;
+ u32 lifetime;
+ hicn_ip_address_t prefix;
+ u32 suffix;
+ u32 path_label;
+} _new_header_t;
+
+#define NEW_HDRLEN sizeof (_new_header_t)
+static_assert (EXPECTED_NEW_HDRLEN == NEW_HDRLEN,
+ "Size of new_header Struct does not match its expected size.");
+
+/* TCP flags bit 0 first. */
+#define foreach_hicn_new_flag \
+ _ (SIG) /**< Signature header after. */ \
+ _ (MAN) /**< Payload type is manifest. */ \
+ _ (INT) /**< Packet is interest. */ \
+ _ (LST) /**< Last data. */
+
+enum
+{
+#define _(f) HICN_NEW_FLAG_BIT_##f,
+ foreach_hicn_new_flag
+#undef _
+ HICN_NEW_N_FLAG_BITS,
+};
+
+enum
+{
+#define _(f) HICN_NEW_FLAG_##f = 1 << HICN_NEW_FLAG_BIT_##f,
+ foreach_hicn_new_flag
+#undef _
+};
+
+static inline int
+_get_new_header_version (const _new_header_t *new_hdr)
+{
+ return ((new_hdr->version_reserved >> 4) & 0x0F);
+}
+
+static inline void
+_set_new_header_version (_new_header_t *new_hdr)
+{
+ new_hdr->version_reserved = (0x9 << 4) & 0xF0;
+}
+
+#endif /* HICN_PROTOCOL_NEW_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/includes/hicn/protocol/tcp.h b/lib/includes/hicn/protocol/tcp.h
index 347682299..1731f0c24 100644
--- a/lib/includes/hicn/protocol/tcp.h
+++ b/lib/includes/hicn/protocol/tcp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -59,55 +59,55 @@ typedef struct
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
struct
{
- u16 reserved:4;
- u16 doff:4;
- u16 fin:1;
- u16 syn:1;
- u16 rst:1;
- u16 psh:1;
- u16 ack:1;
- u16 urg:1;
- u16 ece:1;
- u16 cwr:1;
+ u16 reserved : 4;
+ u16 doff : 4;
+ u16 fin : 1;
+ u16 syn : 1;
+ u16 rst : 1;
+ u16 psh : 1;
+ u16 ack : 1;
+ u16 urg : 1;
+ u16 ece : 1;
+ u16 cwr : 1;
};
struct
- { /* __ denotes unchanged bitfields */
- u16 timescale:4;
- u16 __doff:4;
- u16 __fin:1;
- u16 __syn:1;
- u16 __rst:1;
- u16 sig:1;
- u16 __ack:1;
- u16 man:1;
- u16 id:1;
- u16 __cwr:1;
+ { /* __ denotes unchanged bitfields */
+ u16 timescale : 4;
+ u16 __doff : 4;
+ u16 __fin : 1;
+ u16 __syn : 1;
+ u16 __rst : 1;
+ u16 sig : 1;
+ u16 __ack : 1;
+ u16 man : 1;
+ u16 id : 1;
+ u16 __cwr : 1;
};
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
struct
{
- u16 doff:4;
- u16 reserved:4;
- u16 cwr:1;
- u16 ece:1;
- u16 urg:1;
- u16 ack:1;
- u16 psh:1;
- u16 rst:1;
- u16 syn:1;
- u16 fin:1;
+ u16 doff : 4;
+ u16 reserved : 4;
+ u16 cwr : 1;
+ u16 ece : 1;
+ u16 urg : 1;
+ u16 ack : 1;
+ u16 psh : 1;
+ u16 rst : 1;
+ u16 syn : 1;
+ u16 fin : 1;
};
struct
{
- u16 __doff:4;
- u16 timescale:4;
- u16 __cwr:1;
- u16 id:1 u16 man:1;
- u16 __ack:1;
- u16 sig:1;
- u16 __rst:1;
- u16 __syn:1;
- u16 __fin:1;
+ u16 __doff : 4;
+ u16 timescale : 4;
+ u16 __cwr : 1;
+ u16 id : 1 u16 man : 1;
+ u16 __ack : 1;
+ u16 sig : 1;
+ u16 __rst : 1;
+ u16 __syn : 1;
+ u16 __fin : 1;
};
#endif
};
@@ -124,20 +124,20 @@ typedef struct
};
} _tcp_header_t;
-#define TCP_HDRLEN sizeof(_tcp_header_t)
+#define TCP_HDRLEN sizeof (_tcp_header_t)
static_assert (EXPECTED_TCP_HDRLEN == TCP_HDRLEN,
"Size of TCP struct does not match its expected size.");
/* TCP flags bit 0 first. */
-#define foreach_tcp_flag \
- _ (FIN) /**< No more data from sender. */ \
- _ (SYN) /**< Synchronize sequence numbers. */ \
- _ (RST) /**< Reset the connection. */ \
- _ (PSH) /**< Push function. */ \
- _ (ACK) /**< Ack field significant. */ \
- _ (URG) /**< Urgent pointer field significant. */ \
- _ (ECE) /**< ECN-echo. Receiver got CE packet */ \
- _ (CWR) /**< Sender reduced congestion window */
+#define foreach_tcp_flag \
+ _ (FIN) /**< No more data from sender. */ \
+ _ (SYN) /**< Synchronize sequence numbers. */ \
+ _ (RST) /**< Reset the connection. */ \
+ _ (PSH) /**< Push function. */ \
+ _ (ACK) /**< Ack field significant. */ \
+ _ (URG) /**< Urgent pointer field significant. */ \
+ _ (ECE) /**< ECN-echo. Receiver got CE packet */ \
+ _ (CWR) /**< Sender reduced congestion window */
enum
{
diff --git a/lib/includes/hicn/protocol/udp.h b/lib/includes/hicn/protocol/udp.h
index 75d1ea98c..0e0dddd2c 100644
--- a/lib/includes/hicn/protocol/udp.h
+++ b/lib/includes/hicn/protocol/udp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -29,7 +29,7 @@ typedef struct
u16 checksum;
} _udp_header_t;
-#define UDP_HDRLEN sizeof(_udp_header_t)
+#define UDP_HDRLEN sizeof (_udp_header_t)
static_assert (EXPECTED_UDP_HDRLEN == UDP_HDRLEN,
"Size of UDP struct does not match its expected size.");
diff --git a/lib/includes/hicn/strategy.h b/lib/includes/hicn/strategy.h
new file mode 100644
index 000000000..196d59efa
--- /dev/null
+++ b/lib/includes/hicn/strategy.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file strategy.h
+ * \brief hICN forwarding strategy
+ */
+#ifndef HICN_STRATEGY_H
+#define HICN_STRATEGY_H
+
+#include <string.h>
+
+#define foreach_strategy_type \
+ _ (UNDEFINED) \
+ _ (LOADBALANCER) \
+ _ (LOW_LATENCY) \
+ _ (RANDOM) \
+ _ (REPLICATION) \
+ _ (BESTPATH) \
+ _ (LOCAL_REMOTE) \
+ _ (N)
+
+typedef enum
+{
+#define _(x) STRATEGY_TYPE_##x,
+ foreach_strategy_type
+#undef _
+} strategy_type_t;
+
+extern const char *strategy_str[];
+#define strategy_str(x) strategy_str[x]
+
+#define IS_VALID_STRATEGY_TYPE(x) IS_VALID_ENUM_TYPE (STRATEGY_TYPE, x)
+
+static inline strategy_type_t
+strategy_type_from_str (const char *strategy_str)
+{
+#define _(x) \
+ if (strcasecmp (strategy_str, #x) == 0) \
+ return STRATEGY_TYPE_##x; \
+ else
+ foreach_strategy_type
+#undef _
+ return STRATEGY_TYPE_UNDEFINED;
+}
+
+#define STRATEGY_TYPE_VALID(type) \
+ ((type != STRATEGY_TYPE_UNDEFINED) && (type != STRATEGY_TYPE_N))
+
+#define MAX_FWD_STRATEGY_RELATED_PREFIXES 10
+
+#endif /* HICN_STRATEGY_H */
diff --git a/lib/includes/hicn/util/array.h b/lib/includes/hicn/util/array.h
index 56cfcad8b..f56c13140 100644
--- a/lib/includes/hicn/util/array.h
+++ b/lib/includes/hicn/util/array.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -23,178 +23,167 @@
#include <assert.h>
#include <hicn/util/log.h>
-#include <math.h> // log2
+#include <math.h> // log2
#include <string.h> // memmove
#define BUFSIZE 1024
-typedef int(*cmp_t)(const void * x, const void * y);
-
-#define TYPEDEF_ARRAY_H(NAME, T) \
- \
-typedef struct { \
- size_t size; \
- size_t max_size_log; \
- T * elements; \
-} NAME ## _t; \
- \
-int NAME ## _initialize(NAME ## _t * array); \
- \
-int NAME ## _finalize(NAME ## _t * array); \
- \
-NAME ## _t * NAME ## _create(); \
- \
-void NAME ## _free(NAME ## _t * array); \
- \
-int NAME ## _add(NAME ## _t * array, T element); \
- \
-int NAME ## _remove_index(NAME ## _t * array, int index, T * element); \
- \
-int NAME ## _remove(NAME ## _t * array, const T search, T * element); \
- \
-int NAME ## _get(const NAME ## _t * array, const T search, T * element); \
- \
-int NAME ## _get_index(const NAME ## _t * array, int index, T * element); \
- \
-int NAME ## _get_elements(const NAME ## _t * array, T ** elements); \
- \
-size_t NAME ## _len(const NAME ## _t * array);
-
+#define TYPEDEF_ARRAY_H(NAME, T) \
+ \
+ typedef struct \
+ { \
+ size_t size; \
+ size_t max_size_log; \
+ T *elements; \
+ } NAME##_t; \
+ \
+ int NAME##_initialize (NAME##_t *array); \
+ \
+ int NAME##_finalize (NAME##_t *array); \
+ \
+ NAME##_t *NAME##_create (); \
+ \
+ void NAME##_free (NAME##_t *array); \
+ \
+ int NAME##_add (NAME##_t *array, T element); \
+ \
+ int NAME##_remove_index (NAME##_t *array, int index, T *element); \
+ \
+ int NAME##_remove (NAME##_t *array, const T search, T *element); \
+ \
+ int NAME##_get (const NAME##_t *array, const T search, T *element); \
+ \
+ int NAME##_get_index (const NAME##_t *array, int index, T *element); \
+ \
+ int NAME##_get_elements (const NAME##_t *array, T **elements); \
+ \
+ size_t NAME##_len (const NAME##_t *array);
#define ARRAY_MAX_SIZE_LOG_INIT 0
-#define TYPEDEF_ARRAY(NAME, T, CMP, SNPRINTF) \
-int \
-NAME ## _initialize(NAME ## _t * array) \
-{ \
- array->max_size_log = ARRAY_MAX_SIZE_LOG_INIT; \
- array->size = 0; \
- if (array->max_size_log == 0) { \
- array->elements = NULL; \
- return 0; \
- } \
- array->elements = malloc((1 << array->max_size_log) * sizeof(T)); \
- if (!array->elements) \
- return -1; \
- return 0; \
-} \
- \
-int \
-NAME ## _finalize(NAME ## _t * array) \
-{ \
- for (unsigned i = 0; i < array->size; i++) { \
- NAME ## _remove_index(array, i, NULL); \
- } \
- return 0; \
-} \
- \
-NAME ## _t * \
-NAME ## _create() \
-{ \
- NAME ## _t * array = malloc(sizeof(NAME ## _t)); \
- if (!array) \
- goto ERR_MALLOC; \
- \
- if (NAME ## _initialize(array) < 0) \
- goto ERR_INITIALIZE; \
- \
- return array; \
- \
-ERR_INITIALIZE: \
- free(array); \
-ERR_MALLOC: \
- return NULL; \
-} \
- \
-void \
-NAME ## _free(NAME ## _t * array) \
-{ \
- NAME ## _finalize(array); \
- free(array->elements); \
- free(array); \
-} \
- \
-int \
-NAME ## _add(NAME ## _t * array, T element) \
-{ \
- /* Ensure sufficient space for next addition */ \
- size_t new_size_log = (array->size > 0) ? log2(array->size)+1 : 1; \
- if (new_size_log > array->max_size_log) { \
- array->max_size_log = new_size_log; \
- array->elements = realloc(array->elements, \
- (1 << new_size_log) * sizeof(T)); \
- } \
- \
- if (!array->elements) \
- goto ERR_REALLOC; \
- \
- array->elements[array->size++] = element; \
- return 0; \
- \
-ERR_REALLOC: \
- return -1; \
-} \
- \
-int \
-NAME ## _remove_index(NAME ## _t * array, int index, T * element) \
-{ \
- if (index > NAME ## _len(array)) \
- return -1; \
- if (element) \
- *element = array->elements[index]; \
- if (index < array->size) \
- memmove(array->elements + index, array->elements + index + 1, \
- array->size - index); \
- array->size--; \
- return 0; \
-} \
- \
-int \
-NAME ## _remove(NAME ## _t * array, const T search, T * element) \
-{ \
- for (unsigned i = 0; i < array->size; i++) { \
- if (CMP(search, array->elements[i]) == 0) \
- return facelet_array_remove_index(array, i, element); \
- } \
- /* Not found */ \
- if (element) \
- *element = NULL; \
- return 0; \
-} \
- \
-int \
-NAME ## _get(const NAME ## _t * array, const T search, T * element) \
-{ \
- assert(element); \
- for (unsigned i = 0; i < array->size; i++) \
- if (CMP(search, array->elements[i]) == 0) { \
- *element = array->elements[i]; \
- return 0; \
- } \
- /* Not found */ \
- *element = NULL; \
- return 0; \
-} \
- \
-int \
-NAME ## _get_index(const NAME ## _t * array, int index, T * element) \
-{ \
- assert(element); \
- *element = array->elements[index]; \
- return 0; \
-} \
- \
-int \
-NAME ## _get_elements(const NAME ## _t * array, T ** elements) \
-{ \
- *elements = array->elements; \
- return 0; \
-} \
- \
-size_t \
-NAME ## _len(const NAME ## _t * array) \
-{ \
- return array->size; \
-}
+#define TYPEDEF_ARRAY(NAME, T, CMP, SNPRINTF) \
+ int NAME##_initialize (NAME##_t *array) \
+ { \
+ array->max_size_log = ARRAY_MAX_SIZE_LOG_INIT; \
+ array->size = 0; \
+ if (array->max_size_log == 0) \
+ { \
+ array->elements = NULL; \
+ return 0; \
+ } \
+ array->elements = malloc ((1 << array->max_size_log) * sizeof (T)); \
+ if (!array->elements) \
+ return -1; \
+ return 0; \
+ } \
+ \
+ int NAME##_finalize (NAME##_t *array) \
+ { \
+ for (unsigned i = 0; i < array->size; i++) \
+ { \
+ NAME##_remove_index (array, i, NULL); \
+ } \
+ return 0; \
+ } \
+ \
+ NAME##_t *NAME##_create () \
+ { \
+ NAME##_t *array = malloc (sizeof (NAME##_t)); \
+ if (!array) \
+ goto ERR_MALLOC; \
+ \
+ if (NAME##_initialize (array) < 0) \
+ goto ERR_INITIALIZE; \
+ \
+ return array; \
+ \
+ ERR_INITIALIZE: \
+ free (array); \
+ ERR_MALLOC: \
+ return NULL; \
+ } \
+ \
+ void NAME##_free (NAME##_t *array) \
+ { \
+ NAME##_finalize (array); \
+ free (array->elements); \
+ free (array); \
+ } \
+ \
+ int NAME##_add (NAME##_t *array, T element) \
+ { \
+ /* Ensure sufficient space for next addition */ \
+ size_t new_size_log = (array->size > 0) ? log2 (array->size) + 1 : 1; \
+ if (new_size_log > array->max_size_log) \
+ { \
+ array->max_size_log = new_size_log; \
+ array->elements = \
+ realloc (array->elements, (1 << new_size_log) * sizeof (T)); \
+ } \
+ \
+ if (!array->elements) \
+ goto ERR_REALLOC; \
+ \
+ array->elements[array->size++] = element; \
+ return 0; \
+ \
+ ERR_REALLOC: \
+ return -1; \
+ } \
+ \
+ int NAME##_remove_index (NAME##_t *array, int index, T *element) \
+ { \
+ if (index > NAME##_len (array)) \
+ return -1; \
+ if (element) \
+ *element = array->elements[index]; \
+ if (index < array->size) \
+ memmove (array->elements + index, array->elements + index + 1, \
+ array->size - index); \
+ array->size--; \
+ return 0; \
+ } \
+ \
+ int NAME##_remove (NAME##_t *array, const T search, T *element) \
+ { \
+ for (unsigned i = 0; i < array->size; i++) \
+ { \
+ if (CMP (search, array->elements[i]) == 0) \
+ return NAME##_remove_index (array, i, element); \
+ } \
+ /* Not found */ \
+ if (element) \
+ *element = NULL; \
+ return 0; \
+ } \
+ \
+ int NAME##_get (const NAME##_t *array, const T search, T *element) \
+ { \
+ assert (element); \
+ for (unsigned i = 0; i < array->size; i++) \
+ if (CMP (search, array->elements[i]) == 0) \
+ { \
+ *element = array->elements[i]; \
+ return 0; \
+ } \
+ /* Not found */ \
+ *element = NULL; \
+ return 0; \
+ } \
+ \
+ int NAME##_get_index (const NAME##_t *array, int index, T *element) \
+ { \
+ assert (element); \
+ *element = array->elements[index]; \
+ return 0; \
+ } \
+ \
+ int NAME##_get_elements (const NAME##_t *array, T **elements) \
+ { \
+ *elements = array->elements; \
+ return 0; \
+ } \
+ \
+ size_t NAME##_len (const NAME##_t *array) { return array->size; }
#endif /* UTIL_ARRAY_H */
diff --git a/lib/includes/hicn/util/bitmap.h b/lib/includes/hicn/util/bitmap.h
new file mode 100644
index 000000000..d83c838b7
--- /dev/null
+++ b/lib/includes/hicn/util/bitmap.h
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file bitmap.h
+ * \brief Bitmap
+ *
+ * A bitmap is implemented as a wrapper over a vector made of bit elements
+ */
+
+#ifndef UTIL_BITMAP_H
+#define UTIL_BITMAP_H
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h> // MIN, MAX
+
+#include <hicn/common.h>
+#include <hicn/util/vector.h>
+
+typedef hicn_uword bitmap_t;
+
+#define WORD_WIDTH (sizeof (bitmap_t) * 8)
+
+#define WORD_WIDTH (sizeof (bitmap_t) * 8)
+#define BITMAP_WIDTH(bitmap) (sizeof ((bitmap)[0]) * 8)
+#define BITMAP_INVALID_INDEX ((uint32_t) (~0))
+
+static inline int
+hicn_get_lowest_set_bit_index (hicn_uword w)
+{
+ return hicn_uword_bits > 32 ? __builtin_ctzll (w) : __builtin_ctz (w);
+}
+
+/**
+ * @brief Allocate and initialize a bitmap
+ *
+ * @param[in,out] bitmap Bitmap to allocate and initialize
+ * @param[in] max_size Bitmap max_size
+ */
+#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
+ * given position.
+ *
+ * @param[in] bitmap The bitmap for which to validate the position.
+ * @param[in] pos The position to validate.
+ *
+ * NOTE:
+ * - This function should always be called before writing to a bitmap element
+ * to eventually make room for it (the bitmap will eventually be resized).
+ */
+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 Returns the allocated size of a bitmap.
+ *
+ * @see listener_table_get_by_id
+ */
+#define bitmap_get_alloc_size(bitmap) vector_get_alloc_size (bitmap)
+
+/**
+ * @brief Retrieve the state of the i-th bit in the bitmap.
+ *
+ * @param[in] bitmap The bitmap to access.
+ * @param[in] i The bit position.
+ */
+static inline int
+_bitmap_get (const bitmap_t *bitmap, off_t i)
+{
+ size_t offset = i / BITMAP_WIDTH (bitmap);
+ assert (offset < bitmap_get_alloc_size (bitmap));
+ size_t pos = i % BITMAP_WIDTH (bitmap);
+ return (bitmap[offset] >> pos) & 1;
+}
+
+/**
+ * @brief Retrieve the state of the i-th bit in the bitmap.
+ * Does not sanity check the position.
+ *
+ * @param[in] bitmap The bitmap to access.
+ * @param[in] i The bit position.
+ */
+static inline int
+_bitmap_get_no_check (const bitmap_t *bitmap, off_t i)
+{
+ size_t offset = i / BITMAP_WIDTH (bitmap);
+ size_t pos = i % BITMAP_WIDTH (bitmap);
+ return (bitmap[offset] >> pos) & 1;
+}
+
+/*
+ * @brief Returns whether the i-th bit is set (equal to 1) in a bitmap.
+ *
+ * @param[in] bitmap The bitmap to access.
+ * @param[in] i The bit position.
+ *
+ * @return bool
+ */
+#define bitmap_is_set(bitmap, i) (_bitmap_get ((bitmap), (i)) == 1)
+#define bitmap_is_unset(bitmap, i) (_bitmap_get ((bitmap), (i)) == 0)
+
+#define bitmap_is_set_no_check(bitmap, i) \
+ (_bitmap_get_no_check ((bitmap), (i)) == 1)
+#define bitmap_is_unset_no_check(bitmap, i) \
+ (_bitmap_get_no_check ((bitmap), (i)) == 0)
+
+static inline int
+_bitmap_set_no_check (bitmap_t *bitmap, off_t i)
+{
+ size_t offset = i / BITMAP_WIDTH (bitmap);
+ size_t pos = i % BITMAP_WIDTH (bitmap);
+ bitmap[offset] |= (hicn_uword) (1) << pos;
+ return 0;
+}
+
+static inline int
+_bitmap_set (bitmap_t **bitmap_ptr, off_t i)
+{
+ if (bitmap_ensure_pos (bitmap_ptr, i) < 0)
+ return -1;
+
+ bitmap_t *bitmap = *bitmap_ptr;
+ return _bitmap_set_no_check (bitmap, i);
+}
+
+/*
+ * @brief Set i-th bit to 1 in a bitmap. Reallocate the vector if the bit
+ * position is greater than the vector length.
+ *
+ * @param[in] bitmap The bitmap to access.
+ * @param[in] i The bit position.
+ *
+ * @return bool
+ */
+#define bitmap_set(bitmap, i) _bitmap_set ((bitmap_t **) &bitmap, i)
+
+/*
+ * @brief Set i-th bit to 1 in a bitmap. Unsafe version, does not check
+ * boundaries.
+ *
+ * @param[in] bitmap The bitmap to access.
+ * @param[in] i The bit position.
+ *
+ * @return bool
+ */
+#define bitmap_set_no_check(bitmap, i) _bitmap_set_no_check (bitmap, i)
+
+#define bitmap_unset(bitmap, i) _bitmap_unset (bitmap, i, 1)
+#define bitmap_unset_no_check(bitmap, i) _bitmap_unset (bitmap, i, 0)
+
+static inline int
+_bitmap_unset (bitmap_t *bitmap, off_t i, int check)
+{
+ if (check && bitmap_ensure_pos (&bitmap, i) < 0)
+ return -1;
+ size_t offset = i / BITMAP_WIDTH (bitmap);
+ size_t pos = i % BITMAP_WIDTH (bitmap);
+ bitmap[offset] &= ~((hicn_uword) (1) << pos);
+ 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 < (size_t) 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:
+ return -1;
+}
+
+#define bitmap_set_to(bitmap, to) bitmap_set_range ((bitmap), 0, (to))
+
+#define bitmap_free(bitmap) vector_free (bitmap)
+
+static inline hicn_uword
+bitmap_next_set_no_check (const bitmap_t *bitmap, hicn_uword i, size_t length)
+{
+ hicn_uword pos = i / WORD_WIDTH;
+ hicn_uword offset = i % WORD_WIDTH;
+ hicn_uword tmp;
+ hicn_uword mask = ~((1ULL << offset) - 1);
+
+ if (pos < length)
+ {
+ // This will zeroes all bits < i
+ tmp = bitmap[pos] & mask;
+ if (tmp)
+ return hicn_get_lowest_set_bit_index (tmp) + pos * WORD_WIDTH;
+
+ for (pos += 1; pos < length; pos++)
+ {
+ tmp = bitmap[pos];
+ if (tmp)
+ return hicn_get_lowest_set_bit_index (tmp) + pos * WORD_WIDTH;
+ }
+ }
+
+ return BITMAP_INVALID_INDEX;
+}
+
+static inline hicn_uword
+bitmap_next_set (const bitmap_t *bitmap, hicn_uword i)
+{
+ return bitmap_next_set_no_check (bitmap, i, vector_get_alloc_size (bitmap));
+}
+
+static inline hicn_uword
+bitmap_next_unset_no_check (const bitmap_t *bitmap, hicn_uword i,
+ size_t length)
+{
+ hicn_uword pos = i / WORD_WIDTH;
+ hicn_uword offset = i % WORD_WIDTH;
+ hicn_uword tmp;
+ hicn_uword mask = ~((1ULL << offset) - 1);
+
+ if (pos < length)
+ {
+ // This will zeroes all bits < i
+ tmp = ~bitmap[pos] & mask;
+ if (tmp)
+ return hicn_get_lowest_set_bit_index (tmp) + pos * WORD_WIDTH;
+
+ for (pos += 1; pos < length; pos++)
+ {
+ tmp = ~bitmap[pos];
+ if (tmp)
+ return hicn_get_lowest_set_bit_index (tmp) + pos * WORD_WIDTH;
+ }
+ }
+ return BITMAP_INVALID_INDEX;
+}
+
+static inline hicn_uword
+bitmap_next_unset (const bitmap_t *bitmap, hicn_uword i)
+{
+ return bitmap_next_unset_no_check (bitmap, i,
+ vector_get_alloc_size (bitmap));
+}
+
+#define bitmap_first_set(bitmap) bitmap_next_set (bitmap, 0)
+#define bitmap_first_set_no_check(bitmap, size) \
+ bitmap_next_set_no_check (bitmap, 0, size)
+
+#define bitmap_first_unset(bitmap) bitmap_next_unset (bitmap, 0)
+#define bitmap_first_unset_no_check(bitmap, size) \
+ bitmap_next_unset_no_check (bitmap, 0, size)
+
+static inline void
+bitmap_print (const bitmap_t *bitmap, size_t n_words)
+{
+ for (size_t word = 0; word < n_words; word++)
+ {
+ for (int bit = sizeof (hicn_uword) - 1; bit >= 0; bit--)
+ (bitmap_is_set_no_check (&bitmap[word], bit)) ? printf ("1") :
+ printf ("0");
+ }
+}
+
+#endif /* UTIL_BITMAP_H */
diff --git a/lib/includes/hicn/util/hash.h b/lib/includes/hicn/util/hash.h
new file mode 100644
index 000000000..8dbe0d680
--- /dev/null
+++ b/lib/includes/hicn/util/hash.h
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * \file hash.h
+ * \brief Simple non-cryptographic hash implementation.
+ *
+ * Two helpers are provided :
+ * hash(buf, len) : hash a buffer <buf> of length <len>
+ * hash_struct(buf) : hash a buffer corresponding to an allocated struct
+ *
+ * This file consists in excerpts from Jenkins hash (public domain).
+ * http://www.burtleburtle.net/bob/c/lookup3.c
+ */
+#ifndef UTIL_HASH_H
+#define UTIL_HASH_H
+
+#include <stdint.h>
+#include <stddef.h> // size_t
+
+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
+ __BYTE_ORDER == __LITTLE_ENDIAN) || \
+ (defined(i386) || defined(__i386__) || defined(__i486__) || \
+ defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
+#define HASH_LITTLE_ENDIAN 1
+#define HASH_BIG_ENDIAN 0
+#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
+ __BYTE_ORDER == __BIG_ENDIAN) || \
+ (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
+#define HASH_LITTLE_ENDIAN 0
+#define HASH_BIG_ENDIAN 1
+#else
+#define HASH_LITTLE_ENDIAN 0
+#define HASH_BIG_ENDIAN 0
+#endif
+
+#define hashsize(n) ((uint32_t) 1 << (n))
+#define hashmask(n) (hashsize (n) - 1)
+#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
+
+#define mix(a, b, c) \
+ { \
+ a -= c; \
+ a ^= rot (c, 4); \
+ c += b; \
+ b -= a; \
+ b ^= rot (a, 6); \
+ a += c; \
+ c -= b; \
+ c ^= rot (b, 8); \
+ b += a; \
+ a -= c; \
+ a ^= rot (c, 16); \
+ c += b; \
+ b -= a; \
+ b ^= rot (a, 19); \
+ a += c; \
+ c -= b; \
+ c ^= rot (b, 4); \
+ b += a; \
+ }
+
+#define final(a, b, c) \
+ { \
+ c ^= b; \
+ c -= rot (b, 14); \
+ a ^= c; \
+ a -= rot (c, 11); \
+ b ^= a; \
+ b -= rot (a, 25); \
+ c ^= b; \
+ c -= rot (b, 16); \
+ a ^= c; \
+ a -= rot (c, 4); \
+ b ^= a; \
+ b -= rot (a, 14); \
+ c ^= b; \
+ c -= rot (b, 24); \
+ }
+
+static inline uint32_t
+hashlittle (const void *key, size_t length, uint32_t initval)
+{
+ uint32_t a, b, c; /* internal state */
+ union
+ {
+ const void *ptr;
+ size_t i;
+ } u; /* needed for Mac Powerbook G4 */
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t) length) + initval;
+
+ u.ptr = key;
+ if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0))
+ {
+ const uint32_t *k = (const uint32_t *) key; /* read 32-bit chunks */
+
+ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c)
+ */
+ while (length > 12)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix (a, b, c);
+ length -= 12;
+ k += 3;
+ }
+
+ /*----------------------------- handle the last (probably partial)
+ * block */
+ /*
+ * "k[2]&0xffffff" actually reads beyond the end of the string, but
+ * then masks off the part it's not allowed to read. Because the
+ * string is aligned, the masked-off tail is in the same word as the
+ * rest of the string. Every machine with memory protection I've seen
+ * does it on word boundaries, so is OK with this. But VALGRIND will
+ * still catch it and complain. The masking trick does make the hash
+ * noticably faster for short strings (like English words).
+ */
+#ifndef VALGRIND
+
+ switch (length)
+ {
+ case 12:
+ c += k[2];
+ b += k[1];
+ a += k[0];
+ break;
+ case 11:
+ c += k[2] & 0xffffff;
+ b += k[1];
+ a += k[0];
+ break;
+ case 10:
+ c += k[2] & 0xffff;
+ b += k[1];
+ a += k[0];
+ break;
+ case 9:
+ c += k[2] & 0xff;
+ b += k[1];
+ a += k[0];
+ break;
+ case 8:
+ b += k[1];
+ a += k[0];
+ break;
+ case 7:
+ b += k[1] & 0xffffff;
+ a += k[0];
+ break;
+ case 6:
+ b += k[1] & 0xffff;
+ a += k[0];
+ break;
+ case 5:
+ b += k[1] & 0xff;
+ a += k[0];
+ break;
+ case 4:
+ a += k[0];
+ break;
+ case 3:
+ a += k[0] & 0xffffff;
+ break;
+ case 2:
+ a += k[0] & 0xffff;
+ break;
+ case 1:
+ a += k[0] & 0xff;
+ break;
+ case 0:
+ return c; /* zero length strings require no mixing */
+ }
+
+#else /* make valgrind happy */
+
+ k8 = (const uint8_t *) k;
+ switch (length)
+ {
+ case 12:
+ c += k[2];
+ b += k[1];
+ a += k[0];
+ break;
+ case 11:
+ c += ((uint32_t) k8[10]) << 16; /* fall through */
+ case 10:
+ c += ((uint32_t) k8[9]) << 8; /* fall through */
+ case 9:
+ c += k8[8]; /* fall through */
+ case 8:
+ b += k[1];
+ a += k[0];
+ break;
+ case 7:
+ b += ((uint32_t) k8[6]) << 16; /* fall through */
+ case 6:
+ b += ((uint32_t) k8[5]) << 8; /* fall through */
+ case 5:
+ b += k8[4]; /* fall through */
+ case 4:
+ a += k[0];
+ break;
+ case 3:
+ a += ((uint32_t) k8[2]) << 16; /* fall through */
+ case 2:
+ a += ((uint32_t) k8[1]) << 8; /* fall through */
+ case 1:
+ a += k8[0];
+ break;
+ case 0:
+ return c;
+ }
+
+#endif /* !valgrind */
+ }
+ else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0))
+ {
+ const uint16_t *k = (const uint16_t *) key; /* read 16-bit chunks */
+ const uint8_t *k8;
+
+ /*--------------- all but last block: aligned reads and different mixing
+ */
+ while (length > 12)
+ {
+ a += k[0] + (((uint32_t) k[1]) << 16);
+ b += k[2] + (((uint32_t) k[3]) << 16);
+ c += k[4] + (((uint32_t) k[5]) << 16);
+ mix (a, b, c);
+ length -= 12;
+ k += 6;
+ }
+
+ /*----------------------------- handle the last (probably partial) block
+ */
+ k8 = (const uint8_t *) k;
+ switch (length)
+ {
+ case 12:
+ c += k[4] + (((uint32_t) k[5]) << 16);
+ b += k[2] + (((uint32_t) k[3]) << 16);
+ a += k[0] + (((uint32_t) k[1]) << 16);
+ break;
+ case 11:
+ c += ((uint32_t) k8[10]) << 16; /* fall through */
+ case 10:
+ c += k[4];
+ b += k[2] + (((uint32_t) k[3]) << 16);
+ a += k[0] + (((uint32_t) k[1]) << 16);
+ break;
+ case 9:
+ c += k8[8]; /* fall through */
+ case 8:
+ b += k[2] + (((uint32_t) k[3]) << 16);
+ a += k[0] + (((uint32_t) k[1]) << 16);
+ break;
+ case 7:
+ b += ((uint32_t) k8[6]) << 16; /* fall through */
+ case 6:
+ b += k[2];
+ a += k[0] + (((uint32_t) k[1]) << 16);
+ break;
+ case 5:
+ b += k8[4]; /* fall through */
+ case 4:
+ a += k[0] + (((uint32_t) k[1]) << 16);
+ break;
+ case 3:
+ a += ((uint32_t) k8[2]) << 16; /* fall through */
+ case 2:
+ a += k[0];
+ break;
+ case 1:
+ a += k8[0];
+ break;
+ case 0:
+ return c; /* zero length requires no mixing */
+ }
+ }
+ else
+ { /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *) key;
+
+ /*--------------- all but the last block: affect some 32 bits of (a,b,c)
+ */
+ while (length > 12)
+ {
+ a += k[0];
+ a += ((uint32_t) k[1]) << 8;
+ a += ((uint32_t) k[2]) << 16;
+ a += ((uint32_t) k[3]) << 24;
+ b += k[4];
+ b += ((uint32_t) k[5]) << 8;
+ b += ((uint32_t) k[6]) << 16;
+ b += ((uint32_t) k[7]) << 24;
+ c += k[8];
+ c += ((uint32_t) k[9]) << 8;
+ c += ((uint32_t) k[10]) << 16;
+ c += ((uint32_t) k[11]) << 24;
+ mix (a, b, c);
+ length -= 12;
+ k += 12;
+ }
+
+ /*-------------------------------- last block: affect all 32 bits of (c)
+ */
+ switch (length) /* all the case statements fall through */
+ {
+ case 12:
+ c += ((uint32_t) k[11]) << 24;
+ case 11:
+ c += ((uint32_t) k[10]) << 16;
+ case 10:
+ c += ((uint32_t) k[9]) << 8;
+ case 9:
+ c += k[8];
+ case 8:
+ b += ((uint32_t) k[7]) << 24;
+ case 7:
+ b += ((uint32_t) k[6]) << 16;
+ case 6:
+ b += ((uint32_t) k[5]) << 8;
+ case 5:
+ b += k[4];
+ case 4:
+ a += ((uint32_t) k[3]) << 24;
+ case 3:
+ a += ((uint32_t) k[2]) << 16;
+ case 2:
+ a += ((uint32_t) k[1]) << 8;
+ case 1:
+ a += k[0];
+ break;
+ case 0:
+ return c;
+ }
+ }
+
+ final (a, b, c);
+ return c;
+}
+
+/* Helpers */
+
+#define HASH_INITVAL 1
+//#define hash(buf, len) (hash_t)hashlittle(buf, len, HASH_INITVAL)
+#define hash(buf, len) hashlittle (buf, len, HASH_INITVAL)
+#define hash_struct(buf) hash (buf, sizeof (*buf))
+
+#define str_hash(str) (hash (str, strlen (str)))
+#define str_hash_eq(a, b) (str_hash (b) - str_hash (a))
+
+#endif /* UTIL_JENKINS_HASH_H */
diff --git a/lib/includes/hicn/util/ip_address.h b/lib/includes/hicn/util/ip_address.h
index 4facd9ad0..979efaa40 100644
--- a/lib/includes/hicn/util/ip_address.h
+++ b/lib/includes/hicn/util/ip_address.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -20,10 +20,9 @@
#ifndef UTIL_IP_ADDRESS_H
#define UTIL_IP_ADDRESS_H
-
#ifdef __APPLE__
#include <libkern/OSByteOrder.h>
-#define __bswap_constant_32(x) OSSwapInt32(x)
+#define __bswap_constant_32(x) OSSwapInt32 (x)
#include <machine/endian.h>
#else
#ifdef __ANDROID__
@@ -33,10 +32,11 @@
#endif
#include <errno.h>
+#include <assert.h>
#ifndef _WIN32
-#include <netinet/in.h> // struct sockadd
-#include <arpa/inet.h> // inet_ntop
-#include <netdb.h> // struct addrinfo
+#include <netinet/in.h> // struct sockadd
+#include <arpa/inet.h> // inet_ntop
+#include <netdb.h> // struct addrinfo
#endif
#include <stdbool.h>
#include <stdlib.h>
@@ -45,11 +45,12 @@
#include "types.h"
-#define bytes_to_bits(x) (x * 8)
-#define IPV6_ADDR_LEN 16 /* bytes */
-#define IPV4_ADDR_LEN 4 /* bytes */
-#define IPV6_ADDR_LEN_BITS bytes_to_bits(IPV6_ADDR_LEN)
-#define IPV4_ADDR_LEN_BITS bytes_to_bits(IPV4_ADDR_LEN)
+#define bytes_to_bits(x) (x * 8)
+#define IPV6_ADDR_LEN 16 /* bytes */
+#define IPV4_ADDR_LEN 4 /* bytes */
+#define IPV6_ADDR_LEN_BITS bytes_to_bits (IPV6_ADDR_LEN)
+#define IPV4_ADDR_LEN_BITS bytes_to_bits (IPV4_ADDR_LEN)
+#define MAX_IPV6_PREFIX_LEN 128
/* Presentation format */
#ifndef INET_ADDRSTRLEN
@@ -61,29 +62,47 @@
#endif
//#define INET_MAX_ADDRSTRLEN INET6_ADDRSTRLEN
-#define IP_MAX_ADDR_LEN IPV6_ADDR_LEN
+#define IP_ADDRESS_MAX_LEN IPV6_ADDR_LEN
#define DUMMY_PORT 1234
-typedef union {
- struct {
- u32 pad[3];
- union {
- struct in_addr as_inaddr;
- u8 buffer[4];
- u8 as_u8[4];
- u16 as_u16[2];
- u32 as_u32;
- } v4;
- };
- union {
- struct in6_addr as_in6addr;
- u8 buffer[16];
- u8 as_u8[16];
- u16 as_u16[8];
- u32 as_u32[4];
- u64 as_u64[2];
- } v6;
+typedef union
+{
+ struct in_addr as_inaddr;
+ u8 buffer[4];
+ u8 as_u8[4];
+ u16 as_u16[2];
+ u32 as_u32;
+} ipv4_address_t;
+
+static_assert (sizeof (ipv4_address_t) == 4, "");
+
+typedef union __attribute__ ((__packed__))
+{
+ struct in6_addr as_in6addr;
+ u8 buffer[16];
+ u8 as_u8[16];
+ u16 as_u16[8];
+ u32 as_u32[4];
+ u64 as_u64[2];
+} ipv6_address_t;
+
+static_assert (sizeof (ipv6_address_t) == 16, "");
+
+#ifdef HICN_VPP_PLUGIN
+#include <vnet/ip/ip46_address.h>
+static_assert (sizeof (ipv4_address_t) == sizeof (ip4_address_t), "");
+static_assert (sizeof (ipv6_address_t) == sizeof (ip6_address_t), "");
+#endif
+
+typedef union
+{
+ struct
+ {
+ u32 pad[3];
+ ipv4_address_t v4;
+ };
+ ipv6_address_t v6;
#if 0 /* removed as prone to error due to IPv4 padding */
u8 buffer[IP_MAX_ADDR_LEN];
u8 as_u8[IP_MAX_ADDR_LEN];
@@ -91,79 +110,117 @@ typedef union {
u32 as_u32[IP_MAX_ADDR_LEN >> 2];
u64 as_u64[IP_MAX_ADDR_LEN >> 3];
#endif
-} ip_address_t;
+#ifdef HICN_VPP_PLUGIN
+ ip46_address_t as_ip46;
+#endif /* HICN_VPP_PLUGIN */
+} hicn_ip_address_t;
+
+static_assert (sizeof (hicn_ip_address_t) == 16, "");
+
+#define hicn_ip_address_is_v4(ip) \
+ (((ip)->pad[0] | (ip)->pad[1] | (ip)->pad[2]) == 0)
#define MAXSZ_IP4_ADDRESS_ INET_ADDRSTRLEN - 1
#define MAXSZ_IP6_ADDRESS_ INET6_ADDRSTRLEN - 1
-#define MAXSZ_IP_ADDRESS_ MAXSZ_IP6_ADDRESS_
-#define MAXSZ_IP4_ADDRESS MAXSZ_IP4_ADDRESS_ + 1
-#define MAXSZ_IP6_ADDRESS MAXSZ_IP6_ADDRESS_ + 1
-#define MAXSZ_IP_ADDRESS MAXSZ_IP_ADDRESS_ + 1
+#define MAXSZ_IP_ADDRESS_ MAXSZ_IP6_ADDRESS_
+#define MAXSZ_IP4_ADDRESS MAXSZ_IP4_ADDRESS_ + 1
+#define MAXSZ_IP6_ADDRESS MAXSZ_IP6_ADDRESS_ + 1
+#define MAXSZ_IP_ADDRESS MAXSZ_IP_ADDRESS_ + 1
-typedef struct {
+#define IP_ADDRESS_V4_OFFSET_LEN 12
+
+typedef struct
+{
int family;
- ip_address_t address;
+ hicn_ip_address_t address;
u8 len;
-} ip_prefix_t;
+} hicn_ip_prefix_t;
-#define MAXSZ_PREFIX_ MAXSZ_IP_ADDRESS_ + 1 + 3
-#define MAXSZ_PREFIX MAXSZ_PREFIX_ + 1
+#define MAXSZ_IP_PREFIX_ MAXSZ_IP_ADDRESS_ + 1 + 3
+#define MAXSZ_IP_PREFIX MAXSZ_IP_PREFIX_ + 1
-extern const ip_address_t IPV4_LOOPBACK;
-extern const ip_address_t IPV6_LOOPBACK;
-extern const ip_address_t IPV4_ANY;
-extern const ip_address_t IPV6_ANY;
-extern const ip_address_t IP_ADDRESS_EMPTY;
+extern const hicn_ip_address_t IPV4_LOOPBACK;
+extern const hicn_ip_address_t IPV6_LOOPBACK;
+extern const hicn_ip_address_t IPV4_ANY;
+extern const hicn_ip_address_t IPV6_ANY;
-#define IP_ANY(family) (family == AF_INET) ? IPV4_ANY : IPV6_ANY
+extern const ipv4_address_t IP4_ADDRESS_EMPTY;
+extern const ipv6_address_t IP6_ADDRESS_EMPTY;
+extern const hicn_ip_address_t IP_ADDRESS_EMPTY;
+#define IP_ANY(family) (family == AF_INET) ? IPV4_ANY : IPV6_ANY
-#define MAX_PORT 1 << (8 * sizeof(u16))
-#define IS_VALID_PORT(x) ((x > 0) && ((int)x < MAX_PORT))
+#define MAX_PORT 1 << (8 * sizeof (u16))
+#define IS_VALID_PORT(x) ((x > 0) && ((int) x < MAX_PORT))
#define MAXSZ_PORT_ 5
-#define MAXSZ_PORT MAXSZ_PORT_ + 1
+#define MAXSZ_PORT MAXSZ_PORT_ + 1
#define IS_VALID_FAMILY(x) ((x == AF_INET) || (x == AF_INET6))
/* IP address */
-
-int ip_address_get_family (const char * ip_address);
-int ip_address_len (int family);
-const u8 * ip_address_get_buffer(const ip_address_t * ip_address, int family);
-int ip_address_ntop (const ip_address_t * ip_address, char *dst,
- const size_t len, int family);
-int ip_address_pton (const char *ip_address_str, ip_address_t * ip_address);
-int ip_address_snprintf(char * s, size_t size, const ip_address_t * ip_address,
- int family);
-int ip_address_to_sockaddr(const ip_address_t * ip_address, struct sockaddr *sa,
- int family);
-int ip_address_cmp(const ip_address_t * ip1, const ip_address_t * ip2, int family);
-int ip_address_empty(const ip_address_t * ip);
+int hicn_ip_address_get_family (const hicn_ip_address_t *address);
+int hicn_ip_address_str_get_family (const char *ip_address);
+int hicn_ip_address_len (int family);
+int hicn_ip_address_get_len (const hicn_ip_address_t *ip_address);
+
+int hicn_ip_address_get_len_bits (const hicn_ip_address_t *ip_address);
+const u8 *hicn_ip_address_get_buffer (const hicn_ip_address_t *ip_address,
+ int family);
+int hicn_ip_address_ntop (const hicn_ip_address_t *ip_address, char *dst,
+ const size_t len, int family);
+int hicn_ip_address_pton (const char *ip_address_str,
+ hicn_ip_address_t *ip_address);
+int hicn_ip_address_snprintf (char *s, size_t size,
+ const hicn_ip_address_t *ip_address);
+int hicn_ip_address_to_sockaddr (const hicn_ip_address_t *ip_address,
+ struct sockaddr *sa, int family);
+int hicn_ip_address_cmp (const hicn_ip_address_t *ip1,
+ const hicn_ip_address_t *ip2);
+bool hicn_ip_address_equals (const hicn_ip_address_t *ip1,
+ const hicn_ip_address_t *ip2);
+int hicn_ip_address_empty (const hicn_ip_address_t *ip);
+
+uint8_t hicn_ip_address_get_bit (const hicn_ip_address_t *address,
+ uint8_t pos);
+
+bool hicn_ip_address_match_family (const hicn_ip_address_t *address,
+ int family);
+
+uint32_t hicn_ip_address_get_hash (const hicn_ip_address_t *address);
+
+void hicn_ip_address_clear (hicn_ip_address_t *address);
/* Prefix */
-int ip_prefix_pton (const char *ip_address_str, ip_prefix_t * ip_prefix);
-int ip_prefix_ntop_short (const ip_prefix_t * ip_prefix, char *dst, size_t size);
-int ip_prefix_ntop (const ip_prefix_t * ip_prefix, char *dst, size_t size);
-int ip_prefix_len (const ip_prefix_t * prefix);
-bool ip_prefix_empty (const ip_prefix_t * prefix);
-int ip_prefix_to_sockaddr(const ip_prefix_t * prefix, struct sockaddr *sa);
-int ip_prefix_cmp(const ip_prefix_t * prefix1, const ip_prefix_t * prefix2);
+int hicn_ip_prefix_pton (const char *ip_address_str,
+ hicn_ip_prefix_t *hicn_ip_prefix);
+int hicn_ip_prefix_ntop_short (const hicn_ip_prefix_t *hicn_ip_prefix,
+ char *dst, size_t size);
+int hicn_ip_prefix_ntop (const hicn_ip_prefix_t *hicn_ip_prefix, char *dst,
+ size_t size);
+int hicn_ip_prefix_snprintf (char *s, size_t size,
+ const hicn_ip_prefix_t *prefix);
+int hicn_ip_prefix_len (const hicn_ip_prefix_t *prefix);
+bool hicn_ip_prefix_empty (const hicn_ip_prefix_t *prefix);
+int hicn_ip_prefix_to_sockaddr (const hicn_ip_prefix_t *prefix,
+ struct sockaddr *sa);
+int hicn_ip_prefix_cmp (const hicn_ip_prefix_t *prefix1,
+ const hicn_ip_prefix_t *prefix2);
/* URL */
#define MAXSZ_PROTO_ 8 /* inetX:// */
-#define MAXSZ_PROTO MAXSZ_PROTO_ + NULLTERM
+#define MAXSZ_PROTO MAXSZ_PROTO_ + NULLTERM
#define MAXSZ_URL4_ MAXSZ_PROTO_ + MAXSZ_IP4_ADDRESS_ + MAXSZ_PORT_
#define MAXSZ_URL6_ MAXSZ_PROTO_ + MAXSZ_IP6_ADDRESS_ + MAXSZ_PORT_
-#define MAXSZ_URL_ MAXSZ_URL6_
-#define MAXSZ_URL4 MAXSZ_URL4_ + NULLTERM
-#define MAXSZ_URL6 MAXSZ_URL6_ + NULLTERM
-#define MAXSZ_URL MAXSZ_URL_ + NULLTERM
+#define MAXSZ_URL_ MAXSZ_URL6_
+#define MAXSZ_URL4 MAXSZ_URL4_ + NULLTERM
+#define MAXSZ_URL6 MAXSZ_URL6_ + NULLTERM
+#define MAXSZ_URL MAXSZ_URL_ + NULLTERM
-int url_snprintf(char * s, size_t size, int family,
- const ip_address_t * ip_address, u16 port);
+int url_snprintf (char *s, size_t size, const hicn_ip_address_t *ip_address,
+ u16 port);
#endif /* UTIL_IP_ADDRESS_H */
diff --git a/lib/includes/hicn/util/khash.h b/lib/includes/hicn/util/khash.h
new file mode 100644
index 000000000..17401091f
--- /dev/null
+++ b/lib/includes/hicn/util/khash.h
@@ -0,0 +1,826 @@
+/* The MIT License
+
+ Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+/*
+ An example:
+
+#include "khash.h"
+KHASH_MAP_INIT_INT(32, char)
+int main() {
+ int ret, is_missing;
+ khiter_t k;
+ khash_t(32) *h = kh_init(32);
+ k = kh_put(32, h, 5, &ret);
+ kh_value(h, k) = 10;
+ k = kh_get(32, h, 10);
+ is_missing = (k == kh_end(h));
+ k = kh_get(32, h, 5);
+ kh_del(32, h, k);
+ for (k = kh_begin(h); k != kh_end(h); ++k)
+ if (kh_exist(h, k)) kh_value(h, k) = 1;
+ kh_destroy(32, h);
+ return 0;
+}
+*/
+
+/*
+ 2013-05-02 (0.2.8):
+
+ * Use quadratic probing. When the capacity is power of 2, stepping
+ function i*(i+1)/2 guarantees to traverse each bucket. It is better than
+ double hashing on cache performance and is more robust than linear probing.
+
+ In theory, double hashing should be more robust than quadratic
+ probing. However, my implementation is probably not for large hash tables,
+ because the second hash function is closely tied to the first hash function,
+ which reduce the effectiveness of double hashing.
+
+ Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php
+
+ 2011-12-29 (0.2.7):
+
+ * Minor code clean up; no actual effect.
+
+ 2011-09-16 (0.2.6):
+
+ * The capacity is a power of 2. This seems to dramatically improve the
+ speed for simple keys. Thank Zilong Tan for the suggestion.
+ Reference:
+
+ - http://code.google.com/p/ulib/
+ - http://nothings.org/computer/judy/
+
+ * Allow to optionally use linear probing which usually has better
+ performance for random input. Double hashing is still the default as
+ it is more robust to certain non-random input.
+
+ * Added Wang's integer hash function (not used by default). This hash
+ function is more robust to certain non-random input.
+
+ 2011-02-14 (0.2.5):
+
+ * Allow to declare global functions.
+
+ 2009-09-26 (0.2.4):
+
+ * Improve portability
+
+ 2008-09-19 (0.2.3):
+
+ * Corrected the example
+ * Improved interfaces
+
+ 2008-09-11 (0.2.2):
+
+ * Improved speed a little in kh_put()
+
+ 2008-09-10 (0.2.1):
+
+ * Added kh_clear()
+ * Fixed a compiling error
+
+ 2008-09-02 (0.2.0):
+
+ * Changed to token concatenation which increases flexibility.
+
+ 2008-08-31 (0.1.2):
+
+ * Fixed a bug in kh_get(), which has not been tested previously.
+
+ 2008-08-31 (0.1.1):
+
+ * Added destructor
+*/
+
+#ifndef __AC_KHASH_H
+#define __AC_KHASH_H
+
+/*!
+ @header
+
+ Generic hash table library.
+ */
+
+#define AC_VERSION_KHASH_H "0.2.8"
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+/* compiler specific configuration */
+
+#if UINT_MAX == 0xffffffffu
+typedef unsigned int khint32_t;
+#elif ULONG_MAX == 0xffffffffu
+typedef unsigned long khint32_t;
+#endif
+
+#if ULONG_MAX == ULLONG_MAX
+typedef unsigned long khint64_t;
+#else
+typedef unsigned long long khint64_t;
+#endif
+
+#ifndef kh_inline
+#ifdef _MSC_VER
+#define kh_inline __inline
+#else
+#define kh_inline inline
+#endif
+#endif /* kh_inline */
+
+#ifndef klib_unused
+#if (defined __clang__ && __clang_major__ >= 3) || \
+ (defined __GNUC__ && __GNUC__ >= 3)
+#define klib_unused __attribute__ ((__unused__))
+#else
+#define klib_unused
+#endif
+#endif /* klib_unused */
+
+typedef khint32_t khint_t;
+typedef khint_t khiter_t;
+
+#define __ac_isempty(flag, i) ((flag[i >> 4] >> ((i & 0xfU) << 1)) & 2)
+#define __ac_isdel(flag, i) ((flag[i >> 4] >> ((i & 0xfU) << 1)) & 1)
+#define __ac_iseither(flag, i) ((flag[i >> 4] >> ((i & 0xfU) << 1)) & 3)
+#define __ac_set_isdel_false(flag, i) \
+ (flag[i >> 4] &= ~(1ul << ((i & 0xfU) << 1)))
+#define __ac_set_isempty_false(flag, i) \
+ (flag[i >> 4] &= ~(2ul << ((i & 0xfU) << 1)))
+#define __ac_set_isboth_false(flag, i) \
+ (flag[i >> 4] &= ~(3ul << ((i & 0xfU) << 1)))
+#define __ac_set_isdel_true(flag, i) (flag[i >> 4] |= 1ul << ((i & 0xfU) << 1))
+
+#define __ac_fsize(m) ((m) < 16 ? 1 : (m) >> 4)
+
+#ifndef kroundup32
+#define kroundup32(x) \
+ (--(x), (x) |= (x) >> 1, (x) |= (x) >> 2, (x) |= (x) >> 4, (x) |= (x) >> 8, \
+ (x) |= (x) >> 16, ++(x))
+#endif
+
+#ifndef kcalloc
+#define kcalloc(N, Z) calloc (N, Z)
+#endif
+#ifndef kmalloc
+#define kmalloc(Z) malloc (Z)
+#endif
+#ifndef krealloc
+#define krealloc(P, Z) realloc (P, Z)
+#endif
+#ifndef kfree
+#define kfree(P) free (P)
+#endif
+
+static const double __ac_HASH_UPPER = 0.77;
+
+#define __KHASH_TYPE(name, khkey_t, khval_t) \
+ typedef struct kh_##name##_s \
+ { \
+ khint_t n_buckets, size, n_occupied, upper_bound; \
+ khint32_t *flags; \
+ khkey_t *keys; \
+ khval_t *vals; \
+ } kh_##name##_t;
+
+#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
+ extern kh_##name##_t *kh_init_##name (void); \
+ extern void kh_destroy_##name (kh_##name##_t *h); \
+ extern void kh_clear_##name (kh_##name##_t *h); \
+ extern khint_t kh_get_##name (const kh_##name##_t *h, khkey_t key); \
+ extern int kh_resize_##name (kh_##name##_t *h, khint_t new_n_buckets); \
+ extern khint_t kh_put_##name (kh_##name##_t *h, khkey_t key, int *ret); \
+ extern void kh_del_##name (kh_##name##_t *h, khint_t x);
+
+#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \
+ __hash_equal) \
+ SCOPE kh_##name##_t *kh_init_##name (void) \
+ { \
+ return (kh_##name##_t *) kcalloc (1, sizeof (kh_##name##_t)); \
+ } \
+ SCOPE void kh_destroy_##name (kh_##name##_t *h) \
+ { \
+ if (h) \
+ { \
+ kfree ((void *) h->keys); \
+ kfree (h->flags); \
+ kfree ((void *) h->vals); \
+ kfree (h); \
+ } \
+ } \
+ SCOPE void kh_clear_##name (kh_##name##_t *h) \
+ { \
+ if (h && h->flags) \
+ { \
+ memset (h->flags, 0xaa, \
+ __ac_fsize (h->n_buckets) * sizeof (khint32_t)); \
+ h->size = h->n_occupied = 0; \
+ } \
+ } \
+ SCOPE khint_t kh_get_##name (const kh_##name##_t *h, khkey_t key) \
+ { \
+ if (h->n_buckets) \
+ { \
+ khint_t k, i, last, mask, step = 0; \
+ mask = h->n_buckets - 1; \
+ k = __hash_func (key); \
+ i = k & mask; \
+ last = i; \
+ while (!__ac_isempty (h->flags, i) && \
+ (__ac_isdel (h->flags, i) || !__hash_equal (h->keys[i], key))) \
+ { \
+ i = (i + (++step)) & mask; \
+ if (i == last) \
+ return h->n_buckets; \
+ } \
+ return __ac_iseither (h->flags, i) ? h->n_buckets : i; \
+ } \
+ else \
+ return 0; \
+ } \
+ SCOPE int kh_resize_##name (kh_##name##_t *h, khint_t new_n_buckets) \
+ { /* This function uses 0.25*n_buckets bytes of \
+ working space instead of \
+ [sizeof(key_t+val_t)+.25]*n_buckets. */ \
+ khint32_t *new_flags = 0; \
+ khint_t j = 1; \
+ { \
+ kroundup32 (new_n_buckets); \
+ if (new_n_buckets < 4) \
+ new_n_buckets = 4; \
+ if (h->size >= (khint_t) (new_n_buckets * __ac_HASH_UPPER + 0.5)) \
+ j = 0; /* requested size is too small */ \
+ else \
+ { /* hash table size to be changed (shrink or expand); rehash */ \
+ new_flags = (khint32_t *) kmalloc (__ac_fsize (new_n_buckets) * \
+ sizeof (khint32_t)); \
+ if (!new_flags) \
+ return -1; \
+ memset (new_flags, 0xaa, \
+ __ac_fsize (new_n_buckets) * sizeof (khint32_t)); \
+ if (h->n_buckets < new_n_buckets) \
+ { /* expand */ \
+ khkey_t *new_keys = (khkey_t *) krealloc ( \
+ (void *) h->keys, new_n_buckets * sizeof (khkey_t)); \
+ if (!new_keys) \
+ { \
+ kfree (new_flags); \
+ return -1; \
+ } \
+ h->keys = new_keys; \
+ if (kh_is_map) \
+ { \
+ khval_t *new_vals = (khval_t *) krealloc ( \
+ (void *) h->vals, new_n_buckets * sizeof (khval_t)); \
+ if (!new_vals) \
+ { \
+ kfree (new_flags); \
+ return -1; \
+ } \
+ h->vals = new_vals; \
+ } \
+ } /* otherwise shrink */ \
+ } \
+ } \
+ if (j) \
+ { /* rehashing is needed */ \
+ for (j = 0; j != h->n_buckets; ++j) \
+ { \
+ if (__ac_iseither (h->flags, j) == 0) \
+ { \
+ khkey_t key = h->keys[j]; \
+ khval_t val; \
+ khint_t new_mask; \
+ new_mask = new_n_buckets - 1; \
+ if (kh_is_map) \
+ val = h->vals[j]; \
+ __ac_set_isdel_true (h->flags, j); \
+ while (1) \
+ { /* kick-out process; sort of like in Cuckoo hashing */ \
+ khint_t k, i, step = 0; \
+ k = __hash_func (key); \
+ i = k & new_mask; \
+ while (!__ac_isempty (new_flags, i)) \
+ i = (i + (++step)) & new_mask; \
+ __ac_set_isempty_false (new_flags, i); \
+ if (i < h->n_buckets && __ac_iseither (h->flags, i) == 0) \
+ { /* kick out the existing element */ \
+ { \
+ khkey_t tmp = h->keys[i]; \
+ h->keys[i] = key; \
+ key = tmp; \
+ } \
+ if (kh_is_map) \
+ { \
+ khval_t tmp = h->vals[i]; \
+ h->vals[i] = val; \
+ val = tmp; \
+ } \
+ __ac_set_isdel_true ( \
+ h->flags, \
+ i); /* mark it as deleted in the old hash table */ \
+ } \
+ else \
+ { /* write the element and jump out of the loop */ \
+ h->keys[i] = key; \
+ if (kh_is_map) \
+ h->vals[i] = val; \
+ break; \
+ } \
+ } \
+ } \
+ } \
+ if (h->n_buckets > new_n_buckets) \
+ { /* shrink the hash table */ \
+ h->keys = (khkey_t *) krealloc ( \
+ (void *) h->keys, new_n_buckets * sizeof (khkey_t)); \
+ if (kh_is_map) \
+ h->vals = (khval_t *) krealloc ( \
+ (void *) h->vals, new_n_buckets * sizeof (khval_t)); \
+ } \
+ kfree (h->flags); /* free the working space */ \
+ h->flags = new_flags; \
+ h->n_buckets = new_n_buckets; \
+ h->n_occupied = h->size; \
+ h->upper_bound = (khint_t) (h->n_buckets * __ac_HASH_UPPER + 0.5); \
+ } \
+ return 0; \
+ } \
+ SCOPE khint_t kh_put_##name (kh_##name##_t *h, khkey_t key, int *ret) \
+ { \
+ khint_t x; \
+ if (h->n_occupied >= h->upper_bound) \
+ { /* update the hash table */ \
+ if (h->n_buckets > (h->size << 1)) \
+ { \
+ if (kh_resize_##name (h, h->n_buckets - 1) < 0) \
+ { /* clear "deleted" elements */ \
+ *ret = -1; \
+ return h->n_buckets; \
+ } \
+ } \
+ else if (kh_resize_##name (h, h->n_buckets + 1) < 0) \
+ { /* expand the hash table */ \
+ *ret = -1; \
+ return h->n_buckets; \
+ } \
+ } /* TODO: to implement automatically shrinking; resize() already \
+ support shrinking */ \
+ { \
+ khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \
+ x = site = h->n_buckets; \
+ k = __hash_func (key); \
+ i = k & mask; \
+ if (__ac_isempty (h->flags, i)) \
+ x = i; /* for speed up */ \
+ else \
+ { \
+ last = i; \
+ while ( \
+ !__ac_isempty (h->flags, i) && \
+ (__ac_isdel (h->flags, i) || !__hash_equal (h->keys[i], key))) \
+ { \
+ if (__ac_isdel (h->flags, i)) \
+ site = i; \
+ i = (i + (++step)) & mask; \
+ if (i == last) \
+ { \
+ x = site; \
+ break; \
+ } \
+ } \
+ if (x == h->n_buckets) \
+ { \
+ if (__ac_isempty (h->flags, i) && site != h->n_buckets) \
+ x = site; \
+ else \
+ x = i; \
+ } \
+ } \
+ } \
+ if (__ac_isempty (h->flags, x)) \
+ { /* not present at all */ \
+ h->keys[x] = key; \
+ __ac_set_isboth_false (h->flags, x); \
+ ++h->size; \
+ ++h->n_occupied; \
+ *ret = 1; \
+ } \
+ else if (__ac_isdel (h->flags, x)) \
+ { /* deleted */ \
+ h->keys[x] = key; \
+ __ac_set_isboth_false (h->flags, x); \
+ ++h->size; \
+ *ret = 2; \
+ } \
+ else \
+ *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \
+ return x; \
+ } \
+ SCOPE void kh_del_##name (kh_##name##_t *h, khint_t x) \
+ { \
+ if (x != h->n_buckets && !__ac_iseither (h->flags, x)) \
+ { \
+ __ac_set_isdel_true (h->flags, x); \
+ --h->size; \
+ } \
+ }
+
+#define KHASH_DECLARE(name, khkey_t, khval_t) \
+ __KHASH_TYPE (name, khkey_t, khval_t) \
+ __KHASH_PROTOTYPES (name, khkey_t, khval_t)
+
+#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \
+ __hash_equal) \
+ __KHASH_TYPE (name, khkey_t, khval_t) \
+ __KHASH_IMPL (name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \
+ __hash_equal)
+
+#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, \
+ __hash_equal) \
+ KHASH_INIT2 (name, static kh_inline klib_unused, khkey_t, khval_t, \
+ kh_is_map, __hash_func, __hash_equal)
+
+/* --- BEGIN OF HASH FUNCTIONS --- */
+
+/*! @function
+ @abstract Integer hash function
+ @param key The integer [khint32_t]
+ @return The hash value [khint_t]
+ */
+#define kh_int_hash_func(key) (khint32_t) (key)
+/*! @function
+ @abstract Integer comparison function
+ */
+#define kh_int_hash_equal(a, b) ((a) == (b))
+/*! @function
+ @abstract 64-bit integer hash function
+ @param key The integer [khint64_t]
+ @return The hash value [khint_t]
+ */
+#define kh_int64_hash_func(key) (khint32_t) ((key) >> 33 ^ (key) ^ (key) << 11)
+/*! @function
+ @abstract 64-bit integer comparison function
+ */
+#define kh_int64_hash_equal(a, b) ((a) == (b))
+/*! @function
+ @abstract const char* hash function
+ @param s Pointer to a null terminated string
+ @return The hash value
+ */
+static kh_inline khint_t
+__ac_X31_hash_string (const char *s)
+{
+ khint_t h = (khint_t) *s;
+ if (h)
+ for (++s; *s; ++s)
+ h = (h << 5) - h + (khint_t) *s;
+ return h;
+}
+/*! @function
+ @abstract Another interface to const char* hash function
+ @param key Pointer to a null terminated string [const char*]
+ @return The hash value [khint_t]
+ */
+#define kh_str_hash_func(key) __ac_X31_hash_string (key)
+/*! @function
+ @abstract Const char* comparison function
+ */
+#define kh_str_hash_equal(a, b) (strcmp (a, b) == 0)
+
+static kh_inline khint_t
+__ac_Wang_hash (khint_t key)
+{
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+}
+#define kh_int_hash_func2(key) __ac_Wang_hash ((khint_t) key)
+
+/* --- END OF HASH FUNCTIONS --- */
+
+/* Other convenient macros... */
+
+/*!
+ @abstract Type of the hash table.
+ @param name Name of the hash table [symbol]
+ */
+#define khash_t(name) kh_##name##_t
+
+/*! @function
+ @abstract Initiate a hash table.
+ @param name Name of the hash table [symbol]
+ @return Pointer to the hash table [khash_t(name)*]
+ */
+#define kh_init(name) kh_init_##name ()
+
+/*! @function
+ @abstract Destroy a hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ */
+#define kh_destroy(name, h) kh_destroy_##name (h)
+
+/*! @function
+ @abstract Reset a hash table without deallocating memory.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ */
+#define kh_clear(name, h) kh_clear_##name (h)
+
+/*! @function
+ @abstract Resize a hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param s New size [khint_t]
+ */
+#define kh_resize(name, h, s) kh_resize_##name (h, s)
+
+/*! @function
+ @abstract Insert a key to the hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param k Key [type of keys]
+ @param r Extra return code: -1 if the operation failed;
+ 0 if the key is present in the hash table;
+ 1 if the bucket is empty (never used); 2 if the element in
+ the bucket has been deleted [int*]
+ @return Iterator to the inserted element [khint_t]
+ */
+#define kh_put(name, h, k, r) kh_put_##name (h, k, r)
+
+/*! @function
+ @abstract Retrieve a key from the hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param k Key [type of keys]
+ @return Iterator to the found element, or kh_end(h) if the element is
+ absent [khint_t]
+ */
+#define kh_get(name, h, k) kh_get_##name (h, k)
+
+/*! @function
+ @abstract Remove a key from the hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param k Iterator to the element to be deleted [khint_t]
+ */
+#define kh_del(name, h, k) kh_del_##name (h, k)
+
+/*! @function
+ @abstract Test whether a bucket contains data.
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param x Iterator to the bucket [khint_t]
+ @return 1 if containing data; 0 otherwise [int]
+ */
+#define kh_exist(h, x) (!__ac_iseither ((h)->flags, (x)))
+
+/*! @function
+ @abstract Get key given an iterator
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param x Iterator to the bucket [khint_t]
+ @return Key [type of keys]
+ */
+#define kh_key(h, x) ((h)->keys[x])
+
+/*! @function
+ @abstract Get value given an iterator
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param x Iterator to the bucket [khint_t]
+ @return Value [type of values]
+ @discussion For hash sets, calling this results in segfault.
+ */
+#define kh_val(h, x) ((h)->vals[x])
+
+/*! @function
+ @abstract Alias of kh_val()
+ */
+#define kh_value(h, x) ((h)->vals[x])
+
+/*! @function
+ @abstract Get the start iterator
+ @param h Pointer to the hash table [khash_t(name)*]
+ @return The start iterator [khint_t]
+ */
+#define kh_begin(h) (khint_t) (0)
+
+/*! @function
+ @abstract Get the end iterator
+ @param h Pointer to the hash table [khash_t(name)*]
+ @return The end iterator [khint_t]
+ */
+#define kh_end(h) ((h)->n_buckets)
+
+/*! @function
+ @abstract Get the number of elements in the hash table
+ @param h Pointer to the hash table [khash_t(name)*]
+ @return Number of elements in the hash table [khint_t]
+ */
+#define kh_size(h) ((h)->size)
+
+/*! @function
+ @abstract Get the number of buckets in the hash table
+ @param h Pointer to the hash table [khash_t(name)*]
+ @return Number of buckets in the hash table [khint_t]
+ */
+#define kh_n_buckets(h) ((h)->n_buckets)
+
+/*! @function
+ @abstract Iterate over the entries in the hash table
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param kvar Variable to which key will be assigned
+ @param vvar Variable to which value will be assigned
+ @param code Block of code to execute
+ */
+#define kh_foreach(h, kvar, vvar, code) \
+ { \
+ khint_t __i; \
+ for (__i = kh_begin (h); __i != kh_end (h); ++__i) \
+ { \
+ if (!kh_exist (h, __i)) \
+ continue; \
+ (kvar) = kh_key (h, __i); \
+ (vvar) = kh_val (h, __i); \
+ code; \
+ } \
+ }
+
+/*! @function
+ @abstract Iterate over the values in the hash table
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param vvar Variable to which value will be assigned
+ @param code Block of code to execute
+ */
+#define kh_foreach_value(h, vvar, code) \
+ { \
+ khint_t __i; \
+ for (__i = kh_begin (h); __i != kh_end (h); ++__i) \
+ { \
+ if (!kh_exist (h, __i)) \
+ continue; \
+ (vvar) = kh_val (h, __i); \
+ code; \
+ } \
+ }
+
+/* More convenient interfaces */
+
+/*! @function
+ @abstract Instantiate a hash set containing integer keys
+ @param name Name of the hash table [symbol]
+ */
+#define KHASH_SET_INIT_INT(name) \
+ KHASH_INIT (name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
+
+/*! @function
+ @abstract Instantiate a hash map containing integer keys
+ @param name Name of the hash table [symbol]
+ @param khval_t Type of values [type]
+ */
+#define KHASH_MAP_INIT_INT(name, khval_t) \
+ KHASH_INIT (name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
+
+/*! @function
+ @abstract Instantiate a hash set containing 64-bit integer keys
+ @param name Name of the hash table [symbol]
+ */
+#define KHASH_SET_INIT_INT64(name) \
+ KHASH_INIT (name, khint64_t, char, 0, kh_int64_hash_func, \
+ kh_int64_hash_equal)
+
+/*! @function
+ @abstract Instantiate a hash map containing 64-bit integer keys
+ @param name Name of the hash table [symbol]
+ @param khval_t Type of values [type]
+ */
+#define KHASH_MAP_INIT_INT64(name, khval_t) \
+ KHASH_INIT (name, khint64_t, khval_t, 1, kh_int64_hash_func, \
+ kh_int64_hash_equal)
+
+typedef const char *kh_cstr_t;
+/*! @function
+ @abstract Instantiate a hash map containing const char* keys
+ @param name Name of the hash table [symbol]
+ */
+#define KHASH_SET_INIT_STR(name) \
+ KHASH_INIT (name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
+
+/*! @function
+ @abstract Instantiate a hash map containing const char* keys
+ @param name Name of the hash table [symbol]
+ @param khval_t Type of values [type]
+ */
+#define KHASH_MAP_INIT_STR(name, khval_t) \
+ KHASH_INIT (name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
+
+/******************************************************************************
+ * Custom return codes
+ ******************************************************************************/
+
+// RESET: same as added, but the key was already added in the past
+#define foreach_kh_rc \
+ _ (REPLACED) \
+ _ (ADDED) \
+ _ (RESET) \
+ _ (NOT_FOUND) \
+ _ (FOUND) \
+ _ (FAIL)
+
+typedef enum
+{
+#define _(x) KH_##x,
+ foreach_kh_rc
+#undef _
+} kh_rc;
+
+/******************************************************************************
+ * Custom
+ *high-level interface
+ ******************************************************************************/
+
+#define _kh_var(x) _kh_var_##x
+
+/**
+ * @brief Return the value corresponding to a key in the hashtable.
+ * @return The value associated with the key or null if not found
+ */
+#define kh_get_val(kname, hashtable, key, default_val) \
+ ({ \
+ khiter_t _kh_var (k) = kh_get (kname, hashtable, key); \
+ (_kh_var (k) != kh_end (hashtable) ? kh_val (hashtable, _kh_var (k)) : \
+ default_val); \
+ })
+
+/**
+ * @brief Add key/value pair in the hashtable.
+ * @return 0 if an existing value (corresponding to the provided key)
+ * has been replaced; 1 if a new key/value pair has been added
+ * (the key was not already present in the hash table);
+ * 2 if a new key/value pair has been added in correspondence
+ * of a key previously deleted key
+ */
+#define kh_put_val(kname, hashtable, key, val) \
+ ({ \
+ int _kh_var (ret); \
+ khiter_t _kh_var (k) = kh_put (kname, hashtable, key, &_kh_var (ret)); \
+ kh_value (hashtable, _kh_var (k)) = val; \
+ _kh_var (ret); \
+ })
+
+/**
+ * @brief Remove a key/value pair from the hashtable.
+ * @return void
+ */
+#define kh_remove_val(kname, hashtable, key) \
+ ({ \
+ khiter_t _kh_var (k) = kh_get (kname, hashtable, key); \
+ if (_kh_var (k) != kh_end (hashtable)) \
+ { \
+ free ((void *) kh_key (hashtable, _kh_var (k))); \
+ kh_del (kname, hashtable, _kh_var (k)); \
+ } \
+ })
+
+/**
+ * @brief Free the hashtable.
+ * @return void
+ */
+#define kh_free(kname, hashtable) \
+ ({ \
+ const void *_kh_var (key); \
+ unsigned _kh_var (val); \
+ (void) _kh_var (val); \
+ \
+ kh_foreach (hashtable, _kh_var (key), _kh_var (val), { \
+ free ((void *) _kh_var (key)); \
+ }) kh_destroy (kname, hashtable); \
+ })
+
+#endif /* __AC_KHASH_H */
diff --git a/lib/includes/hicn/util/log.h b/lib/includes/hicn/util/log.h
index 6763d464f..b9b7725d6 100644
--- a/lib/includes/hicn/util/log.h
+++ b/lib/includes/hicn/util/log.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -17,53 +17,72 @@
#define UTIL_LOG_H
#include <stdarg.h> // va_*
-#include <stdio.h> // FILE
-#include <time.h> // time, localtime
+#include <stdio.h> // FILE
+#include <time.h> // time, localtime
-#define LOG_FATAL 0
-#define LOG_ERROR 1
-#define LOG_WARN 2
-#define LOG_INFO 3
-#define LOG_DEBUG 4
-#define LOG_TRACE 5
+typedef enum
+{
+ LOG_FATAL,
+ LOG_ERROR,
+ LOG_WARN,
+ LOG_INFO,
+ LOG_DEBUG,
+ LOG_TRACE
+} log_level_t;
-typedef struct {
+typedef struct
+{
int log_level;
int debug;
- FILE * log_file;
+ FILE *log_file;
} log_conf_t;
-#define DEFAULT_LOG_CONF { \
- .log_level = LOG_INFO, \
- .debug = 0, \
- .log_file = NULL, \
-};
+#define DEFAULT_LOG_CONF \
+ { \
+ .log_level = LOG_INFO, \
+ .debug = 0, \
+ .log_file = NULL, \
+ };
extern log_conf_t log_conf;
-#define WITH_DEBUG(BLOCK) \
- if (log_conf.log_level >= LOG_DEBUG) \
- BLOCK
+#define WITH_ERROR(BLOCK) \
+ if (log_conf.log_level >= LOG_ERROR) \
+ BLOCK
+#define WITH_WARN(BLOCK) \
+ if (log_conf.log_level >= LOG_WARN) \
+ BLOCK
+#define WITH_INFO(BLOCK) \
+ if (log_conf.log_level >= LOG_INFO) \
+ BLOCK
+#define WITH_DEBUG(BLOCK) \
+ if (log_conf.log_level >= LOG_DEBUG) \
+ BLOCK
+#define WITH_TRACE(BLOCK) \
+ if (log_conf.log_level >= LOG_TRACE) \
+ BLOCK
-#define FATAL(fmt, ...) (_log(LOG_FATAL, fmt, ##__VA_ARGS__ ))
+#define FATAL(fmt, ...) (_log (LOG_FATAL, fmt, ##__VA_ARGS__))
#ifdef ERROR
#undef ERROR
#endif
-#define ERROR(fmt, ...) (_log(LOG_ERROR, fmt, ##__VA_ARGS__ ))
-#define WARN(fmt, ...) (_log(LOG_WARN, fmt, ##__VA_ARGS__ ))
-#define INFO(fmt, ...) (_log(LOG_INFO, fmt, ##__VA_ARGS__ ))
-#define DEBUG(fmt, ...) (_log(LOG_DEBUG, fmt, ##__VA_ARGS__ ))
-#define TRACE(fmt, ...) (_log(LOG_TRACE, fmt, ##__VA_ARGS__ ))
+#define ERROR(fmt, ...) (_log (LOG_ERROR, fmt, ##__VA_ARGS__))
+#define WARN(fmt, ...) (_log (LOG_WARN, fmt, ##__VA_ARGS__))
+#define INFO(fmt, ...) (_log (LOG_INFO, fmt, ##__VA_ARGS__))
+#define DEBUG(fmt, ...) (_log (LOG_DEBUG, fmt, ##__VA_ARGS__))
+#define TRACE(fmt, ...) (_log (LOG_TRACE, fmt, ##__VA_ARGS__))
-void _log_va(int level, const char *fmt, va_list ap);
+void _log_va (int level, const char *fmt, va_list ap);
-void _log(int level, const char *fmt, ...);
+void _log (int level, const char *fmt, ...);
-void fatal(char *fmt, ...);
+void fatal (char *fmt, ...);
+
+int loglevel_from_str (const char *loglevel);
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
-void print_trace(void);
+void print_trace (void);
#endif
#endif // UTIL_LOG_H
diff --git a/lib/includes/hicn/util/map.h b/lib/includes/hicn/util/map.h
index 01195865e..6e23f222f 100644
--- a/lib/includes/hicn/util/map.h
+++ b/lib/includes/hicn/util/map.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -20,231 +20,227 @@
#include "set.h"
-#define ERR_MAP_EXISTS -2
+#define ERR_MAP_EXISTS -2
#define ERR_MAP_NOT_FOUND -3
-#define TYPEDEF_MAP_H(NAME, KEY_T, VAL_T) \
- \
-typedef struct { \
- KEY_T key; \
- VAL_T value; \
-} NAME ## _pair_t; \
- \
-NAME ## _pair_t * NAME ## _pair_create(KEY_T key, VAL_T value); \
- \
-void NAME ## _pair_free(NAME ## _pair_t * pair); \
- \
-int NAME ## _pair_cmp(const NAME ## _pair_t * p1, const NAME ## _pair_t * p2); \
- \
-TYPEDEF_SET_H(NAME ## _pair_set, NAME ## _pair_t *) \
- \
-typedef struct NAME ## _s { \
- NAME ## _pair_set_t pair_set; \
-} NAME ## _t; \
- \
-int NAME ## _initialize(NAME ## _t * map); \
- \
-int NAME ## _finalize(NAME ## _t * map); \
- \
-NAME ## _t * NAME ## _create(); \
- \
-void NAME ## _free(NAME ## _t * map); \
- \
-int NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value); \
- \
-int NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value); \
- \
-int NAME ## _get(NAME ## _t * map, KEY_T key, VAL_T * value); \
- \
-void NAME ## _dump(NAME ## _t * map);
+#define TYPEDEF_MAP_H(NAME, KEY_T, VAL_T) \
+ \
+ typedef struct \
+ { \
+ KEY_T key; \
+ VAL_T value; \
+ } NAME##_pair_t; \
+ \
+ NAME##_pair_t *NAME##_pair_create (KEY_T key, VAL_T value); \
+ \
+ void NAME##_pair_free (NAME##_pair_t *pair); \
+ \
+ int NAME##_pair_cmp (const NAME##_pair_t *p1, const NAME##_pair_t *p2); \
+ \
+ TYPEDEF_SET_H (NAME##_pair_set, NAME##_pair_t *) \
+ \
+ typedef struct NAME##_s \
+ { \
+ NAME##_pair_set_t pair_set; \
+ } NAME##_t; \
+ \
+ int NAME##_initialize (NAME##_t *map); \
+ \
+ int NAME##_finalize (NAME##_t *map); \
+ \
+ NAME##_t *NAME##_create (); \
+ \
+ void NAME##_free (NAME##_t *map); \
+ \
+ int NAME##_add (NAME##_t *map, KEY_T key, VAL_T value); \
+ \
+ int NAME##_remove (NAME##_t *map, KEY_T key, VAL_T *value); \
+ \
+ int NAME##_get (NAME##_t *map, KEY_T key, VAL_T *value); \
+ \
+ void NAME##_dump (NAME##_t *map); \
+ \
+ int NAME##_get_key_array (NAME##_t *map, KEY_T **array); \
+ \
+ int NAME##_get_value_array (NAME##_t *map, VAL_T **array);
-
-
-
-#define TYPEDEF_MAP(NAME, KEY_T, VAL_T, CMP, KEY_SNPRINTF, VALUE_SNPRINTF) \
- \
-NAME ## _pair_t * NAME ## _pair_create(KEY_T key, VAL_T value) \
-{ \
- /* Create pair */ \
- NAME ## _pair_t * pair = malloc(sizeof(NAME ## _pair_t)); \
- if (!pair) \
- return NULL; \
- \
- pair->key = key; \
- pair->value = value; \
- \
- return pair; \
-} \
- \
-void NAME ## _pair_free(NAME ## _pair_t * pair) \
-{ \
- free(pair); \
-} \
- \
-int \
-NAME ## _pair_cmp(const NAME ## _pair_t * p1, const NAME ## _pair_t * p2) \
-{ \
- return (CMP(p1->key, p2->key)); \
-} \
- \
-int \
-NAME ## _pair_snprintf(char * buf, size_t size, const NAME ## _pair_t * pair) { \
- int rc; \
- rc = KEY_SNPRINTF(buf, BUFSIZE/2, (KEY_T)pair->key); \
- if (rc < 0) \
- return rc; \
- rc = VALUE_SNPRINTF(buf+rc, BUFSIZE/2, (VAL_T)pair->value); \
- return (int)rc; \
-} \
- \
-TYPEDEF_SET(NAME ## _pair_set, NAME ## _pair_t *, NAME ## _pair_cmp, NAME ## _pair_snprintf); \
- \
-int \
-NAME ## _initialize(NAME ## _t * map) \
-{ \
- return NAME ## _pair_set_initialize(&map->pair_set); \
-} \
- \
-int \
-NAME ## _finalize(NAME ## _t * map) \
-{ \
- NAME ## _pair_t ** array; \
- int n = NAME ## _pair_set_get_array(&map->pair_set, &array); \
- if (n < 0) \
- return -1; \
- for (unsigned i = 0; i < n; i++) { \
- NAME ## _pair_t * pair = array[i]; \
- NAME ## _pair_set_remove(&map->pair_set, pair, NULL); \
- NAME ## _pair_free(pair); \
- } \
- free(array); \
- return NAME ## _pair_set_finalize(&map->pair_set); \
-} \
- \
-NAME ## _t * \
-NAME ## _create() \
-{ \
- NAME ## _t * map = malloc(sizeof(NAME ## _t)); \
- if (!map) \
- goto ERR_MALLOC; \
- \
- if (NAME ## _initialize(map) < 0) \
- goto ERR_INITIALIZE; \
- \
- return map; \
- \
-ERR_INITIALIZE: \
- free(map); \
-ERR_MALLOC: \
- return NULL; \
-} \
- \
-void \
-NAME ## _free(NAME ## _t * map) \
-{ \
- NAME ## _finalize(map); \
- free(map); \
-} \
- \
-int \
-NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value) \
-{ \
- int rc; \
- NAME ## _pair_t * found = NULL; \
- \
- NAME ## _pair_t * pair = NAME ## _pair_create(key, value); \
- if (!pair) \
- return -1; \
- \
- rc = NAME ## _pair_set_get(&map->pair_set, pair, &found); \
- if (rc < 0) \
- return -1; \
- if (found) { \
- NAME ## _pair_free(pair); \
- return ERR_MAP_EXISTS; \
- } \
- \
- rc = NAME ## _pair_set_add(&map->pair_set, pair); \
- if (rc < 0) { \
- NAME ## _pair_free(pair); \
- return -1; \
- } \
- return 0; \
-} \
- \
-int \
-NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value) \
-{ \
- NAME ## _pair_t * found = NULL; \
- NAME ## _pair_t search = { .key = key }; \
- int rc = NAME ## _pair_set_remove(&map->pair_set, &search, &found); \
- if (rc < 0) \
- return ERR_MAP_NOT_FOUND; \
- if (value) \
- *value = found->value; \
- NAME ## _pair_free(found); \
- return 0; \
-} \
- \
-int \
-NAME ## _get(NAME ## _t * map, KEY_T key, VAL_T * value) \
-{ \
- NAME ## _pair_t * found = NULL, search = { .key = key }; \
- int rc = NAME ## _pair_set_get(&map->pair_set, &search, &found); \
- if (rc < 0) \
- return -1; \
- if (found) \
- *value = found->value; \
- return 0; \
-} \
- \
-void \
-NAME ## _dump(NAME ## _t * map) { \
- NAME ## _pair_set_dump(&map->pair_set); \
-} \
- \
-int \
-NAME ## _get_key_array(NAME ## _t * map, KEY_T **array) { \
- NAME ## _pair_t ** pair_array; \
- int n = NAME ## _pair_set_get_array(&map->pair_set, &pair_array); \
- if (n < 0) \
- return -1; \
- if (!array) \
- goto END; \
- /* Allocate result array */ \
- *array = malloc(n * sizeof(KEY_T)); \
- if (!array) { \
- free(pair_array); \
- return -1; \
- } \
- /* Copy keys */ \
- for (int i = 0; i < n; i++) \
- (*array)[i] = pair_array[i]->key; \
- free(pair_array); \
-END: \
- return n; \
-} \
- \
-int \
-NAME ## _get_value_array(NAME ## _t * map, VAL_T **array) { \
- NAME ## _pair_t ** pair_array; \
- int n = NAME ## _pair_set_get_array(&map->pair_set, &pair_array); \
- if (n < 0) \
- return -1; \
- if (!array) \
- goto END; \
- /* Allocate result array */ \
- *array = malloc(n * sizeof(VAL_T)); \
- if (!array) { \
- free(pair_array); \
- return -1; \
- } \
- /* Copy values */ \
- for (int i = 0; i < n; i++) \
- (*array)[i] = pair_array[i]->value; \
- free(pair_array); \
-END: \
- return n; \
-}
+#define TYPEDEF_MAP(NAME, KEY_T, VAL_T, CMP, KEY_SNPRINTF, VALUE_SNPRINTF) \
+ \
+ NAME##_pair_t *NAME##_pair_create (KEY_T key, VAL_T value) \
+ { \
+ /* Create pair */ \
+ NAME##_pair_t *pair = malloc (sizeof (NAME##_pair_t)); \
+ if (!pair) \
+ return NULL; \
+ \
+ pair->key = key; \
+ pair->value = value; \
+ \
+ return pair; \
+ } \
+ \
+ void NAME##_pair_free (NAME##_pair_t *pair) { free (pair); } \
+ \
+ int NAME##_pair_cmp (const NAME##_pair_t *p1, const NAME##_pair_t *p2) \
+ { \
+ return (CMP (p1->key, p2->key)); \
+ } \
+ \
+ int NAME##_pair_snprintf (char *buf, size_t size, \
+ const NAME##_pair_t *pair) \
+ { \
+ int rc; \
+ rc = KEY_SNPRINTF (buf, BUFSIZE / 2, (KEY_T) pair->key); \
+ if (rc < 0) \
+ return rc; \
+ rc = VALUE_SNPRINTF (buf + rc, BUFSIZE / 2, (VAL_T) pair->value); \
+ return (int) rc; \
+ } \
+ \
+ TYPEDEF_SET (NAME##_pair_set, NAME##_pair_t *, NAME##_pair_cmp, \
+ NAME##_pair_snprintf); \
+ \
+ int NAME##_initialize (NAME##_t *map) \
+ { \
+ return NAME##_pair_set_initialize (&map->pair_set); \
+ } \
+ \
+ int NAME##_finalize (NAME##_t *map) \
+ { \
+ NAME##_pair_t **array; \
+ int n = NAME##_pair_set_get_array (&map->pair_set, &array); \
+ if (n < 0) \
+ return -1; \
+ for (unsigned i = 0; i < n; i++) \
+ { \
+ NAME##_pair_t *pair = array[i]; \
+ NAME##_pair_set_remove (&map->pair_set, pair, NULL); \
+ NAME##_pair_free (pair); \
+ } \
+ free (array); \
+ return NAME##_pair_set_finalize (&map->pair_set); \
+ } \
+ \
+ NAME##_t *NAME##_create () \
+ { \
+ NAME##_t *map = malloc (sizeof (NAME##_t)); \
+ if (!map) \
+ goto ERR_MALLOC; \
+ \
+ if (NAME##_initialize (map) < 0) \
+ goto ERR_INITIALIZE; \
+ \
+ return map; \
+ \
+ ERR_INITIALIZE: \
+ free (map); \
+ ERR_MALLOC: \
+ return NULL; \
+ } \
+ \
+ void NAME##_free (NAME##_t *map) \
+ { \
+ NAME##_finalize (map); \
+ free (map); \
+ } \
+ \
+ int NAME##_add (NAME##_t *map, KEY_T key, VAL_T value) \
+ { \
+ int rc; \
+ NAME##_pair_t *found = NULL; \
+ \
+ NAME##_pair_t *pair = NAME##_pair_create (key, value); \
+ if (!pair) \
+ return -1; \
+ \
+ rc = NAME##_pair_set_get (&map->pair_set, pair, &found); \
+ if (rc < 0) \
+ return -1; \
+ if (found) \
+ { \
+ NAME##_pair_free (pair); \
+ return ERR_MAP_EXISTS; \
+ } \
+ \
+ rc = NAME##_pair_set_add (&map->pair_set, pair); \
+ if (rc < 0) \
+ { \
+ NAME##_pair_free (pair); \
+ return -1; \
+ } \
+ return 0; \
+ } \
+ \
+ int NAME##_remove (NAME##_t *map, KEY_T key, VAL_T *value) \
+ { \
+ NAME##_pair_t *found = NULL; \
+ NAME##_pair_t search = { .key = key }; \
+ int rc = NAME##_pair_set_remove (&map->pair_set, &search, &found); \
+ if (rc < 0) \
+ return ERR_MAP_NOT_FOUND; \
+ if (value) \
+ *value = found->value; \
+ NAME##_pair_free (found); \
+ return 0; \
+ } \
+ \
+ int NAME##_get (NAME##_t *map, KEY_T key, VAL_T *value) \
+ { \
+ NAME##_pair_t *found = NULL, search = { .key = key }; \
+ int rc = NAME##_pair_set_get (&map->pair_set, &search, &found); \
+ if (rc < 0) \
+ return -1; \
+ if (found) \
+ *value = found->value; \
+ return 0; \
+ } \
+ \
+ void NAME##_dump (NAME##_t *map) { NAME##_pair_set_dump (&map->pair_set); } \
+ \
+ int NAME##_get_key_array (NAME##_t *map, KEY_T **array) \
+ { \
+ NAME##_pair_t **pair_array; \
+ int n = NAME##_pair_set_get_array (&map->pair_set, &pair_array); \
+ if (n < 0) \
+ return -1; \
+ if (!array) \
+ goto END; \
+ /* Allocate result array */ \
+ *array = malloc (n * sizeof (KEY_T)); \
+ if (!array) \
+ { \
+ free (pair_array); \
+ return -1; \
+ } \
+ /* Copy keys */ \
+ for (int i = 0; i < n; i++) \
+ (*array)[i] = pair_array[i]->key; \
+ free (pair_array); \
+ END: \
+ return n; \
+ } \
+ \
+ int NAME##_get_value_array (NAME##_t *map, VAL_T **array) \
+ { \
+ NAME##_pair_t **pair_array; \
+ int n = NAME##_pair_set_get_array (&map->pair_set, &pair_array); \
+ if (n < 0) \
+ return -1; \
+ if (!array) \
+ goto END; \
+ /* Allocate result array */ \
+ *array = malloc (n * sizeof (VAL_T)); \
+ if (!array) \
+ { \
+ free (pair_array); \
+ return -1; \
+ } \
+ /* Copy values */ \
+ for (int i = 0; i < n; i++) \
+ (*array)[i] = pair_array[i]->value; \
+ free (pair_array); \
+ END: \
+ return n; \
+ }
#endif /* UTIL_MAP_H */
diff --git a/lib/includes/hicn/util/pool.h b/lib/includes/hicn/util/pool.h
new file mode 100644
index 000000000..b8acadc44
--- /dev/null
+++ b/lib/includes/hicn/util/pool.h
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file pool.h
+ * \brief Fixed-size pool allocator.
+ *
+ * This memory pool allocates a single block of memory that is used to
+ * efficiently allocate/deallocate fixed-size blocks for high churn data
+ * structures.
+ *
+ * Internally this data structure leverages a vector for managing elements (and
+ * it thus resizeable if needed), as well as a list of free indices (in the
+ * form of another vector) and a bitmap marking free indices also (for fast
+ * iteration).
+ *
+ * The internal API manipulates a pointer to the vector that that is can be
+ * seamlessly resized, and a more convenient user interface is provided through
+ * macros.
+ *
+ * The vector of free indices is managed as a stack where elements indices are
+ * retrieved from and put back to the end of the vector. In the bitmap,
+ * available elements are set to 1, and unset to 0 when in use.
+ *
+ * The pool is not currently resized down when releasing elements.
+ *
+ * It is freely inspired (and simplified) from the VPP infra infrastructure
+ * library.
+ */
+
+#ifndef UTIL_POOL_H
+#define UTIL_POOL_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "bitmap.h"
+#include <hicn/util/vector.h>
+#include "../common.h"
+
+/* Pool header */
+
+typedef struct
+{
+ size_t elt_size;
+ size_t alloc_size;
+ size_t max_size;
+ bitmap_t *free_bitmap; /* bitmap of free indices */
+ off_t *free_indices; /* vector of free indices */
+} pool_hdr_t;
+
+#define POOL_HDRLEN SIZEOF_ALIGNED (pool_hdr_t)
+
+/* This header actually prepends the actual content of the pool. */
+#define pool_hdr(pool) ((pool_hdr_t *) ((uint8_t *) (pool) -POOL_HDRLEN))
+
+/******************************************************************************/
+/* Helpers */
+
+/** Local variable naming macro. */
+#define _pool_var(v) _pool_##v
+
+/**
+ * @brief Allocate and initialize a pool data structure (helper).
+ *
+ * @param[in,out] pool_ptr Pointer to the pool data structure.
+ * @param[in] elt_size Size of elements in vector.
+ * @param[in] max_size Maximum size.
+ *
+ * NOTE: that an empty pool might be equal to NULL.
+ */
+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).
+ *
+ * @param[in] pool_ptr Pointer to the pool data structure.
+ */
+void _pool_free (void **pool_ptr);
+
+/**
+ * @brief Resize a pool data structure (helper).
+ *
+ * @param pool_ptr Pointer to the pool data structure.
+ *
+ * This function should only be called internally, as the resize is implicitly
+ * done (if allowed by the maximum size) when the user tries to get a new slot.
+ */
+void _pool_resize (void **pool_ptr, size_t elt_size);
+
+/**
+ * @brief Get a free element from the pool data structure (helper).
+ *
+ * @param[in] pool Pointer to the pool data structure to use.
+ * @param[in,out] elt Pointer to an empty element that will be used to return
+ * the allocated one from the pool.
+ *
+ * NOTES:
+ * - The memory chunk is cleared upon attribution
+ */
+off_t _pool_get (void **pool, void **elt, size_t elt_size);
+
+/**
+ * @brief Put an element back into the pool data structure (helper).
+ *
+ * @param[in] pool_ptr Pointer to the pool data structure to use.
+ * @param[in] elt Pointer to the pool element to put back.
+ */
+void _pool_put (void **pool, void **elt, size_t elt_size);
+
+/**
+ * @brief Validate a pool element by index (helper).
+ *
+ * @param[in] pool The pool data structure to use.
+ * @param[in] id The index of the element to validate.
+ *
+ * @return bool A flag indicating whether the index is valid or not.
+ */
+bool _pool_validate_id (void **pool_ptr, off_t id);
+/******************************************************************************/
+/* Public API */
+
+/**
+ * @brief Allocate and initialize a pool data structure.
+ *
+ * @param[in,out] pool Pointer to the pool data structure.
+ * @param[in] elt_size Size of elements in pool.
+ * @param[in] max_size Maximum size.
+ *
+ * NOTE: that an empty pool might be equal to NULL.
+ */
+#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.
+ *
+ * @param[in] pool The pool data structure to free.
+ */
+#define pool_free(pool) _pool_free ((void **) &pool);
+
+/**
+ * @brief Get a free element from the pool data structure.
+ *
+ * @param[in] pool The pool data structure to use.
+ * @param[in,out] elt An empty element that will be used to return the
+ * allocated one from the pool.
+ *
+ * NOTES:
+ * - The memory chunk is cleared upon attribution
+ */
+#define pool_get(pool, elt) \
+ _pool_get ((void **) &pool, (void **) &elt, sizeof (*elt))
+
+/**
+ * @brief Put an element back into the pool data structure.
+ *
+ * @param[in] pool The pool data structure to use.
+ * @param[in] elt The pool element to put back.
+ */
+#define pool_put(pool, elt) \
+ _pool_put ((void **) &pool, (void **) &elt, sizeof (*elt))
+
+/**
+ * @brief Validate a pool element by index.
+ *
+ * @param[in] pool The pool data structure to use.
+ * @param[in] id The index of the element to validate.
+ *
+ * @return bool A flag indicating whether the index is valid or not.
+ */
+#define pool_validate_id(pool, id) _pool_validate_id ((void **) &pool, (id))
+
+#define pool_get_free_indices_size(pool) \
+ vector_len (pool_hdr (pool)->free_indices)
+
+/**
+ * @brief Returns the current length of the pool.
+ *
+ * @param[in] pool The pool data structure for which to return the length.
+ *
+ * @return size_t The current length of the pool.
+ *
+ * NOTE:
+ * - The pool length corresponds to the number of allocated elements, not the
+ * size of the pool.
+ */
+#define pool_len(pool) \
+ (pool_hdr (pool)->alloc_size - pool_get_free_indices_size (pool))
+
+/**
+ * @brief Enumerate elements from a pool.
+ *
+ * @param[in] pool The pool data structure to enumerate.
+ * @param[in, out] i An integer that will be used for enumeration.
+ * @param[in, out] eltp A pointer to the element type that will be used for
+ * enumeration.
+ * @param[in] BODY Block to execute during enumeration.
+ *
+ * Enumeration will iteratively execute BODY with (i, eltp) corresponding
+ * respectively to the index and element found in the pool.
+ *
+ * NOTE: i stars at 0.
+ */
+#define pool_enumerate(pool, i, eltp, BODY) \
+ do \
+ { \
+ pool_hdr_t *_pool_var (ph) = pool_hdr (pool); \
+ bitmap_t *_pool_var (fb) = _pool_var (ph)->free_bitmap; \
+ for ((i) = 0; (i) < _pool_var (ph)->alloc_size; (i)++) \
+ { \
+ if (bitmap_is_set (_pool_var (fb), (i))) \
+ continue; \
+ eltp = (pool) + (i); \
+ do \
+ { \
+ BODY; \
+ } \
+ while (0); \
+ } \
+ } \
+ while (0)
+
+#define pool_enumerate_typed(pool, i, TYPE, ELTP, BODY) \
+ do \
+ { \
+ pool_hdr_t *_pool_var (ph) = pool_hdr (pool); \
+ bitmap_t *_pool_var (fb) = _pool_var (ph)->free_bitmap; \
+ TYPE ELTP = NULL; \
+ for ((i) = 0; (i) < _pool_var (ph)->alloc_size; (i)++) \
+ { \
+ if (bitmap_is_set (_pool_var (fb), (i))) \
+ continue; \
+ ELTP = (pool) + (i); \
+ do \
+ { \
+ BODY; \
+ } \
+ while (0); \
+ } \
+ } \
+ while (0)
+
+/**
+ * @brief Iterate over elements in a pool.
+ *
+ * @param[in] pool The pool data structure to iterate over.
+ * @param[in,out] eltp A pointer to the element type that will be used for
+ * iteration.
+ * @param[in] BODY Block to execute during iteration.
+ *
+ * Iteration will execute BODY with eltp corresponding successively to all
+ * elements found in the pool. It is implemented using the more generic
+ * enumeration function.
+ */
+#define pool_foreach(pool, eltp, BODY) \
+ do \
+ { \
+ unsigned _pool_var (i); \
+ pool_enumerate ((pool), _pool_var (i), (eltp), BODY); \
+ } \
+ while (0)
+
+#define pool_get_alloc_size(pool) pool_hdr (pool)->alloc_size
+
+#define pool_foreach_typed(pool, TYPE, ELTP, BODY) \
+ do \
+ { \
+ unsigned _pool_var (i); \
+ pool_enumerate_typed ((pool), _pool_var (i), TYPE, ELTP, BODY); \
+ } \
+ while (0)
+
+#ifdef WITH_TESTS
+#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/lib/includes/hicn/util/ring.h b/lib/includes/hicn/util/ring.h
new file mode 100644
index 000000000..9510672b3
--- /dev/null
+++ b/lib/includes/hicn/util/ring.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file ring.h
+ * \brief Fixed-size pool allocator.
+ */
+
+#ifndef UTIL_RING_H
+#define UTIL_RING_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/param.h> // MIN
+#include <sys/types.h>
+
+#include <stdio.h> // XXX debug
+
+#include "../common.h"
+
+/******************************************************************************/
+/* Ring header */
+
+typedef struct
+{
+ size_t roff;
+ size_t woff;
+ size_t size;
+ size_t max_size;
+} ring_hdr_t;
+
+/* Make sure elements following the header are aligned */
+#define RING_HDRLEN SIZEOF_ALIGNED (ring_hdr_t)
+
+/* This header actually prepends the actual content of the vector */
+#define ring_hdr(ring) ((ring_hdr_t *) ((uint8_t *) ring - RING_HDRLEN))
+
+/******************************************************************************/
+/* Helpers */
+
+/** Local variable naming macro. */
+#define _ring_var(v) _ring_##v
+
+/**
+ * @brief Allocate and initialize a ring data structure (helper function).
+ *
+ * @param[in,out] ring_ptr Ring buffer to allocate and initialize.
+ * @param[in] elt_size Size of a ring element.
+ * @param[in] max_size Maximum vector size (O = unlimited).
+ */
+void _ring_init (void **ring_ptr, size_t elt_size, size_t max_size);
+
+/**
+ * @brief Free a ring data structure.
+ *
+ * @param ring_ptr[in] Pointer to the ring data structure to free.
+ */
+void _ring_free (void **ring_ptr);
+
+static inline int
+_ring_add (void **ring_ptr, size_t elt_size, void *eltp)
+{
+ assert (*ring_ptr);
+ ring_hdr_t *rh = ring_hdr (*ring_ptr);
+
+ /* We always write ! */
+ memcpy ((uint8_t *) *ring_ptr + rh->woff * elt_size, eltp, elt_size);
+ rh->woff++;
+ if (rh->woff == rh->max_size)
+ rh->woff = 0;
+ if (rh->size < rh->max_size)
+ {
+ rh->size++;
+ }
+ else
+ {
+ /* One packet was dropped */
+ rh->roff++;
+ if (rh->roff == rh->max_size)
+ rh->roff = 0;
+ }
+ return 0;
+}
+
+static inline unsigned
+_ring_get_fullness (void **ring_ptr)
+{
+ assert (*ring_ptr);
+ ring_hdr_t *rh = ring_hdr (*ring_ptr);
+ return (unsigned int) (rh->size * 100 / rh->max_size);
+}
+
+static inline unsigned
+_ring_is_full (void **ring_ptr)
+{
+ assert (*ring_ptr);
+ ring_hdr_t *rh = ring_hdr (*ring_ptr);
+ return rh->size == rh->max_size;
+}
+
+static inline size_t
+_ring_get_size (void **ring_ptr)
+{
+ assert (*ring_ptr);
+ ring_hdr_t *rh = ring_hdr (*ring_ptr);
+ return rh->size;
+}
+
+static inline int
+_ring_advance (void **ring_ptr, unsigned n)
+{
+ assert (*ring_ptr);
+ ring_hdr_t *rh = ring_hdr (*ring_ptr);
+ assert (n <= rh->size);
+
+ rh->roff += n;
+ rh->size -= n;
+ while (rh->roff >= rh->max_size)
+ rh->roff -= rh->max_size;
+ return 0;
+}
+
+static inline int
+_ring_get (void **ring_ptr, size_t elt_size, unsigned i, void *eltp)
+{
+ assert (*ring_ptr);
+ ring_hdr_t *rh = ring_hdr (*ring_ptr);
+ assert (i <= rh->size);
+ size_t pos = rh->roff + i;
+ if (pos >= rh->max_size)
+ pos -= rh->max_size;
+ memcpy (eltp, (uint8_t *) *ring_ptr + pos * elt_size, elt_size);
+ return 0;
+}
+
+/******************************************************************************/
+/* Public API */
+
+/**
+ * @brief Allocate and initialize a ring data structure.
+ *
+ * @param[in,out] ring Ring to allocate and initialize.
+ * @param[in] max_size Maximum ring size (nonzero).
+ *
+ * NOTE:
+ * - Allocated memory is set to 0 (used by bitmap)
+ */
+
+#define ring_init(RING, MAX_SIZE) \
+ _ring_init ((void **) &(RING), sizeof ((RING)[0]), (MAX_SIZE))
+
+#define ring_free(RING) _ring_free ((void **) &(RING))
+
+#define ring_get_fullness(RING) _ring_get_fullness ((void **) &(RING))
+
+#define ring_is_full(RING) _ring_is_full ((void **) &(RING))
+
+#define ring_get_size(RING) _ring_get_size ((void **) &(RING))
+
+#define ring_add(RING, ELT) \
+ _ring_add ((void **) &(RING), sizeof (RING[0]), ELT)
+
+#define ring_add_value(RING, VALUE) \
+ do \
+ { \
+ typeof (VALUE) _ring_var (v) = VALUE; \
+ _ring_add ((void **) &(RING), sizeof (RING[0]), &_ring_var (v)); \
+ } \
+ while (0)
+
+#define ring_advance(RING, N) _ring_advance ((void **) &(RING), (N))
+
+#define ring_get(RING, I, ELTP) \
+ _ring_get ((void **) &RING, sizeof (RING[0]), (I), (ELTP))
+
+/**
+ * @brief Helper function used by ring_foreach().
+ */
+#define ring_enumerate_n(RING, I, ELTP, COUNT, BODY) \
+ ({ \
+ for ((I) = 0; (I) < MIN (ring_get_size (RING), (COUNT)); (I)++) \
+ { \
+ ring_get ((RING), (I), (ELTP)); \
+ { \
+ BODY; \
+ } \
+ } \
+ })
+
+#define ring_enumerate(ring, i, eltp, BODY) \
+ ring_enumerate_n ((ring), (i), (eltp), 1, (BODY))
+
+/**
+ * @brief Iterate over elements in a ring.
+ *
+ * @param[in] pool The ring data structure to iterate over
+ * @param[in, out] eltp A pointer to the element that will be used for
+ * iteration
+ * @param[in] BODY Block to execute during iteration
+ *
+ * @note Iteration will execute BODY with eltp corresponding successively to
+ * all elements found in the ring. It is implemented using the more generic
+ * enumeration function.
+ */
+#define ring_foreach_n(ring, eltp, count, BODY) \
+ ({ \
+ unsigned _ring_var (i); \
+ ring_enumerate_n ((ring), _ring_var (i), (eltp), (count), BODY); \
+ })
+
+#define ring_foreach(ring, eltp, BODY) \
+ ring_foreach_n ((ring), (eltp), 1, (BODY))
+
+#endif /* UTIL_RING_H */
diff --git a/lib/includes/hicn/util/set.h b/lib/includes/hicn/util/set.h
index bc2e3caac..0a5ff6777 100644
--- a/lib/includes/hicn/util/set.h
+++ b/lib/includes/hicn/util/set.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -25,214 +25,196 @@
#define thread_local _Thread_local
//#endif /* ! __ANDROID__ */
-#define ERR_SET_EXISTS -2
+#define ERR_SET_EXISTS -2
#define ERR_SET_NOT_FOUND -3
/* FIXME: buffer overflow when this is too small... investigate */
#define BUFSIZE 1024
-static inline
-int
-int_cmp(const int x, const int y)
+static inline int
+int_cmp (const int x, const int y)
{
- return x - y;
+ return x - y;
}
-static inline
-int
-int_snprintf(char * buf, size_t size, int value) {
- return snprintf(buf, size, "%d", value);
+static inline int
+int_snprintf (char *buf, size_t size, int value)
+{
+ return snprintf (buf, size, "%d", value);
}
-static inline
-int
-string_snprintf(char * buf, size_t size, const char * s) {
- return snprintf(buf, size, "%s", s);
+static inline int
+string_snprintf (char *buf, size_t size, const char *s)
+{
+ return snprintf (buf, size, "%s", s);
}
-static inline
-int
-generic_snprintf(char * buf, size_t size, const void * value) {
- return snprintf(buf, BUFSIZE, "%p", value);
+static inline int
+generic_snprintf (char *buf, size_t size, const void *value)
+{
+ return snprintf (buf, BUFSIZE, "%p", value);
}
-typedef int(*cmp_t)(const void * x, const void * y);
-
-#define TYPEDEF_SET_H(NAME, T) \
- \
-typedef struct { \
- size_t size; \
- void * root; \
-} NAME ## _t; \
- \
-int NAME ## _initialize(NAME ## _t * set); \
- \
-int NAME ## _finalize(NAME ## _t * set); \
- \
-NAME ## _t * NAME ## _create(); \
- \
-void NAME ## _free(NAME ## _t * set); \
- \
-int NAME ## _add(NAME ## _t * set, const T element); \
- \
-int NAME ## _remove(NAME ## _t * set, const T search, T * element); \
- \
-int NAME ## _clear(NAME ## _t * set); \
- \
-int NAME ## _get(const NAME ## _t * set, const T search, T * element); \
- \
-int NAME ## _get_array(const NAME ## _t * set, T ** element); \
- \
-void NAME ## _dump(NAME ## _t * set);
+typedef int (*cmp_t) (const void *x, const void *y);
+#define TYPEDEF_SET_H(NAME, T) \
+ \
+ typedef struct \
+ { \
+ size_t size; \
+ void *root; \
+ } NAME##_t; \
+ \
+ int NAME##_initialize (NAME##_t *set); \
+ \
+ int NAME##_finalize (NAME##_t *set); \
+ \
+ NAME##_t *NAME##_create (); \
+ \
+ void NAME##_free (NAME##_t *set); \
+ \
+ int NAME##_add (NAME##_t *set, const T element); \
+ \
+ int NAME##_remove (NAME##_t *set, const T search, T *element); \
+ \
+ int NAME##_clear (NAME##_t *set); \
+ \
+ int NAME##_get (const NAME##_t *set, const T search, T *element); \
+ \
+ int NAME##_get_array (const NAME##_t *set, T **element); \
+ \
+ void NAME##_dump (NAME##_t *set);
-
-
-#define TYPEDEF_SET(NAME, T, CMP, SNPRINTF) \
-int \
-NAME ## _initialize(NAME ## _t * set) \
-{ \
- set->root = NULL; \
- set->size = 0; \
- return 0; \
-} \
- \
-int \
-NAME ## _finalize(NAME ## _t * set) \
-{ \
- return NAME ## _clear(set); \
-} \
- \
-NAME ## _t * \
-NAME ## _create() \
-{ \
- NAME ## _t * set = malloc(sizeof(NAME ## _t)); \
- if (!set) \
- goto ERR_MALLOC; \
- \
- if (NAME ## _initialize(set) < 0) \
- goto ERR_INITIALIZE; \
- \
- return set; \
- \
-ERR_INITIALIZE: \
- free(set); \
-ERR_MALLOC: \
- return NULL; \
-} \
- \
-void \
-NAME ## _free(NAME ## _t * set) \
-{ \
- NAME ## _finalize(set); \
- free(set); \
-} \
- \
-int \
-NAME ## _add(NAME ## _t * set, const T element) \
-{ \
- T * found = tfind(element, &set->root, (cmp_t)CMP); \
- void * ptr = tsearch(element, &set->root, (cmp_t)CMP); \
- if (!ptr) \
- return -1; \
- if (!found) \
- set->size++; \
- return 0; \
-} \
- \
-int \
-NAME ## _remove(NAME ## _t * set, const T search, T * element) \
-{ \
- T * found = tfind(search, &set->root, (cmp_t)CMP); \
- if (!found) \
- return ERR_SET_NOT_FOUND; \
- if (element) \
- *element = *found; \
- tdelete(search, &set->root, (cmp_t)CMP); \
- set->size--; \
- return 0; \
-} \
- \
-int \
-NAME ## _clear(NAME ## _t * set) \
-{ \
- T * array; \
- int n = NAME ## _get_array(set, &array); \
- if (n < 0) \
- return -1; \
- for (unsigned i = 0; i < n; i++) { \
- T element = array[i]; \
- NAME ## _remove(set, element, NULL); \
- } \
- free(array); \
- return 0; \
-} \
- \
-int \
-NAME ## _get(const NAME ## _t * set, const T search, T * element) \
-{ \
- T * found = tfind(search, &set->root, (cmp_t)CMP); \
- if (element) \
- *element = found ? *found : NULL; \
- return 0; \
-} \
- \
-static void \
-NAME ## _dump_node(const void *nodep, const VISIT which, \
- const int depth) \
-{ \
- char buf[BUFSIZE]; \
- switch (which) { \
- case preorder: \
- case endorder: \
- break; \
- case postorder: \
- case leaf: \
- SNPRINTF(buf, BUFSIZE, *(T*)nodep); \
- INFO("%s", buf); \
- break; \
- } \
-} \
- \
-void \
-NAME ## _dump(NAME ## _t * set) { \
- twalk(set->root, NAME ## _dump_node); \
-} \
- \
-thread_local \
-T * NAME ## _array_pos = NULL; \
- \
-static void \
-NAME ## _add_node_to_array(const void *nodep, const VISIT which, \
- const int depth) \
-{ \
- if (!NAME ## _array_pos) \
- return; \
- switch (which) { \
- case preorder: \
- case endorder: \
- break; \
- case postorder: \
- case leaf: \
- *NAME ## _array_pos = *(T*)nodep; \
- NAME ## _array_pos++; \
- break; \
- } \
-} \
- \
-int \
-NAME ## _get_array(const NAME ## _t * set, T ** element) \
-{ \
- if (!element) \
- goto END; \
- *element = malloc(set->size * sizeof(T)); \
- if (!*element) \
- return -1; \
- NAME ## _array_pos = *element; \
- twalk(set->root, NAME ## _add_node_to_array); \
- NAME ## _array_pos = NULL; \
-END: \
- return (int)(set->size); \
-}
+#define TYPEDEF_SET(NAME, T, CMP, SNPRINTF) \
+ int NAME##_initialize (NAME##_t *set) \
+ { \
+ set->root = NULL; \
+ set->size = 0; \
+ return 0; \
+ } \
+ \
+ int NAME##_finalize (NAME##_t *set) { return NAME##_clear (set); } \
+ \
+ NAME##_t *NAME##_create () \
+ { \
+ NAME##_t *set = malloc (sizeof (NAME##_t)); \
+ if (!set) \
+ goto ERR_MALLOC; \
+ \
+ if (NAME##_initialize (set) < 0) \
+ goto ERR_INITIALIZE; \
+ \
+ return set; \
+ \
+ ERR_INITIALIZE: \
+ free (set); \
+ ERR_MALLOC: \
+ return NULL; \
+ } \
+ \
+ void NAME##_free (NAME##_t *set) \
+ { \
+ NAME##_finalize (set); \
+ free (set); \
+ } \
+ \
+ int NAME##_add (NAME##_t *set, const T element) \
+ { \
+ T *found = tfind (element, &set->root, (cmp_t) CMP); \
+ void *ptr = tsearch (element, &set->root, (cmp_t) CMP); \
+ if (!ptr) \
+ return -1; \
+ if (!found) \
+ set->size++; \
+ return 0; \
+ } \
+ \
+ int NAME##_remove (NAME##_t *set, const T search, T *element) \
+ { \
+ T *found = tfind (search, &set->root, (cmp_t) CMP); \
+ if (!found) \
+ return ERR_SET_NOT_FOUND; \
+ if (element) \
+ *element = *found; \
+ tdelete (search, &set->root, (cmp_t) CMP); \
+ set->size--; \
+ return 0; \
+ } \
+ \
+ int NAME##_clear (NAME##_t *set) \
+ { \
+ T *array; \
+ int n = NAME##_get_array (set, &array); \
+ if (n < 0) \
+ return -1; \
+ for (unsigned i = 0; i < n; i++) \
+ { \
+ T element = array[i]; \
+ NAME##_remove (set, element, NULL); \
+ } \
+ free (array); \
+ return 0; \
+ } \
+ \
+ int NAME##_get (const NAME##_t *set, const T search, T *element) \
+ { \
+ T *found = tfind (search, &set->root, (cmp_t) CMP); \
+ if (element) \
+ *element = found ? *found : NULL; \
+ return 0; \
+ } \
+ \
+ static void NAME##_dump_node (const void *nodep, const VISIT which, \
+ const int depth) \
+ { \
+ char buf[BUFSIZE]; \
+ switch (which) \
+ { \
+ case preorder: \
+ case endorder: \
+ break; \
+ case postorder: \
+ case leaf: \
+ SNPRINTF (buf, BUFSIZE, *(T *) nodep); \
+ INFO ("%s", buf); \
+ break; \
+ } \
+ } \
+ \
+ void NAME##_dump (NAME##_t *set) { twalk (set->root, NAME##_dump_node); } \
+ \
+ thread_local T *NAME##_array_pos = NULL; \
+ \
+ static void NAME##_add_node_to_array (const void *nodep, const VISIT which, \
+ const int depth) \
+ { \
+ if (!NAME##_array_pos) \
+ return; \
+ switch (which) \
+ { \
+ case preorder: \
+ case endorder: \
+ break; \
+ case postorder: \
+ case leaf: \
+ *NAME##_array_pos = *(T *) nodep; \
+ NAME##_array_pos++; \
+ break; \
+ } \
+ } \
+ \
+ int NAME##_get_array (const NAME##_t *set, T **element) \
+ { \
+ if (!element) \
+ goto END; \
+ *element = calloc (set->size, sizeof (T)); \
+ if (!*element) \
+ return -1; \
+ NAME##_array_pos = *element; \
+ twalk (set->root, NAME##_add_node_to_array); \
+ NAME##_array_pos = NULL; \
+ END: \
+ return (int) (set->size); \
+ }
#endif /* UTIL_SET_H */
diff --git a/lib/includes/hicn/util/slab.h b/lib/includes/hicn/util/slab.h
new file mode 100644
index 000000000..2c6546add
--- /dev/null
+++ b/lib/includes/hicn/util/slab.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @brief The slab is used to store elements of the same size.
+ *
+ * The slab contains blocks of contiguous memory. Each block contains multiple
+ * chunks. An element is stored inside a chunk and the chunk has a header with
+ * a pointer to the block it belongs to.
+ *
+ * Blocks are stored in two doubly-linked lists: 'full' for blocks that
+ * are already full, 'partial_or_empty' for blocks with available chunks. When
+ * a block becomes full it is moved into the 'full' list and vice versa.
+ *
+ * When allocationg an element, a block is taken from the 'partial_or_empty'
+ * list if such list is not empty. If empty, a new block of contiguous memory
+ * is created and put in the 'partial_or_empty' list. Then, a chunk is taken
+ * from the block. When releasing an element, the block it belongs to is
+ * retrieved from the chunk header and used to release the chunk.
+ *
+ * Blocks are created with increasing capacity (i.e. number of chunks they
+ * contain) such that every new block allocaion doubles the total number of
+ * chunks stored in the slab.
+ */
+
+#ifndef UTIL_SLAB_H
+#define UTIL_SLAB_H
+
+#include <stddef.h>
+
+#define SLAB_INIT_SIZE 32
+
+/* CHUNK */
+
+typedef struct block_s block_t;
+typedef struct
+{
+ block_t *block; // Pointer to the block that contains the chunk
+} chunk_hdr_t;
+
+#define CHUNK_HDRLEN SIZEOF_ALIGNED (chunk_hdr_t)
+#define chunk_hdr(chunk) ((chunk_hdr_t *) ((uint8_t *) (chunk) -CHUNK_HDRLEN))
+
+/* BLOCK */
+
+struct block_s
+{
+ void *pool;
+ block_t *prev;
+ block_t *next;
+};
+
+/* SLAB */
+
+typedef struct
+{
+ size_t num_chunks; // Total number of chunks (from all blocks) currently
+ // stored in the slab
+ size_t chunk_size;
+ block_t *full;
+ block_t *partial_or_empty;
+} slab_t;
+
+/* Internal API */
+
+slab_t *_slab_create (size_t elt_size, size_t num_elts);
+void *_slab_get (slab_t *slab);
+void _slab_put (slab_t *slab, void *elt);
+
+/* Public API */
+
+/**
+ * @brief Create a slab able to store elements of type 'TYPE'.
+ *
+ * @param[in] TYPE Type of the elements to store in the slab.
+ * @param[in] SIZE Initial size of the slab, i.e. size of the initial block.
+ * @return slab_t* The slab created, NULL if error.
+ */
+#define slab_create(TYPE, SIZE) _slab_create (sizeof (TYPE), SIZE)
+
+/**
+ * @brief Free a slab.
+ *
+ * @param[in] slab Slab to free.
+ */
+void slab_free (slab_t *slab);
+
+/**
+ * @brief Get an element from the slab.
+ *
+ * @param[in] TYPE Type of the elements stored in the slab.
+ * @param[in] SLAB Slab to take the element from.
+ * @return TYPE* Element retrieved from the slab
+ */
+#define slab_get(TYPE, SLAB) (TYPE *) _slab_get (SLAB)
+
+/**
+ * @brief Same as 'slab_get' but with a different signature, to avoid passing
+ * the type that is instead inferred from the element.
+ *
+ * @param[in] SLAB Slab to take the element from.
+ * @param[in, out] ELT Element retrieved from the slab.
+ */
+#define slab_get2(SLAB, ELT) ELT = (typeof (*(ELT)) *) _slab_get (SLAB)
+
+/**
+ * @brief Put an element back into the slab.
+ *
+ * @param[in] SLAB Slab to return the element to.
+ * @param[in] ELT Element to put in the slab.
+ */
+#define slab_put(SLAB, ELT) _slab_put (SLAB, (void *) ELT)
+
+#endif /* UTIL_SLAB_H */
diff --git a/lib/includes/hicn/util/sstrncpy.h b/lib/includes/hicn/util/sstrncpy.h
new file mode 100644
index 000000000..0b397c26b
--- /dev/null
+++ b/lib/includes/hicn/util/sstrncpy.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UTIL_SSTRNCPY_H
+#define UTIL_SSTRNCPY_H
+
+#ifndef __STDC_WANT_LIB_EXT1__
+#define __STDC_WANT_LIB_EXT1__ 1
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+#ifdef __STDC_LIB_EXT1__
+// If safe string functions already available in the system, use them
+#elif ENABLE_SAFEC
+// If safe string functions not available and SafeC is enabled,
+// use SafeC
+#include <safe_string.h>
+#else
+// Use custom safe string functions
+typedef int errno_t;
+#define EOK 0
+
+#ifndef HICN_VPP_PLUGIN
+/* This function is already defined in vppinfra/string.h */
+
+/**
+ * @brief This function assures a null byte at the end of the buffer.
+ */
+static inline errno_t
+strcpy_s (char *dst, size_t n, const char *src)
+{
+ if (!dst || !src || !n)
+ {
+ fprintf (stderr, "[strncpy] invalid input received");
+ return EINVAL;
+ }
+
+ dst[n - 1] = 0;
+ strncpy (dst, src, n);
+
+ if (dst[n - 1] != 0)
+ {
+ fprintf (stderr, "[strncpy] '%s' has been trucated\n", src);
+ dst[n - 1] = 0;
+ return EINVAL;
+ }
+
+ return EOK;
+}
+
+static inline size_t
+strnlen_s (const char *s, size_t maxlen)
+{
+ if (s == NULL)
+ return 0;
+
+ return strnlen (s, maxlen);
+}
+#endif /* HICN_VPP_PLUGIN */
+
+#endif /* __STDC_LIB_EXT1__ */
+#endif /* UTIL_SSTRNCPY_H */
diff --git a/lib/includes/hicn/util/token.h b/lib/includes/hicn/util/token.h
index 43e0a77b2..c62c294bc 100644
--- a/lib/includes/hicn/util/token.h
+++ b/lib/includes/hicn/util/token.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -19,12 +19,12 @@
* Concatenate preprocessor tokens A and B without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
-#define PPCAT_NX(A, B) A ## B
+#define PPCAT_NX(A, B) A##B
/*
* Concatenate preprocessor tokens A and B after macro-expanding them.
*/
-#define PPCAT(A, B) PPCAT_NX(A, B)
+#define PPCAT(A, B) PPCAT_NX (A, B)
/* Token stringification */
@@ -37,4 +37,4 @@
/*
* Turn A into a string literal after macro-expanding it.
*/
-#define STRINGIZE(A) STRINGIZE_NX(A)
+#define STRINGIZE(A) STRINGIZE_NX (A)
diff --git a/lib/includes/hicn/util/types.h b/lib/includes/hicn/util/types.h
index 017e85b72..a883b8220 100644
--- a/lib/includes/hicn/util/types.h
+++ b/lib/includes/hicn/util/types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -19,21 +19,63 @@
#include <hicn/util/windows/windows_Utils.h>
#endif
+/* Standard types. */
+#include <stdint.h>
+
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
-/* Helper for avoiding warnings about type-punning */
-#define UNION_CAST(x, destType) \
- (((union {__typeof__(x) a; destType b;})x).b)
+typedef int8_t i8;
+typedef int16_t i16;
+typedef int32_t i32;
+typedef int64_t i64;
+
+typedef double f64;
+typedef float f32;
+
+/* Architecture-dependent uword size */
+#if INTPTR_MAX == INT64_MAX
+#define hicn_log2_uword_bits 6
+#elif INTPTR_MAX == INT32_MAX
+#define hicn_log2_uword_bits 5
+#else
+#error "Impossible to detect architecture"
+#endif
+
+#define _hicn_uword_bits (1 << hicn_log2_uword_bits)
-//typedef unsigned int hash_t;
+/* Word types. */
+#if _hicn_uword_bits == 64
+/* 64 bit word machines. */
+typedef u64 hicn_uword;
+#define hicn_uword_bits 64
+#else
+/* 32 bit word machines. */
+typedef u32 hicn_uword;
+#define hicn_uword_bits 32
+#endif
+
+typedef hicn_uword hicn_ip_csum_t;
+
+/* Helper for avoiding warnings about type-punning */
+#define UNION_CAST(x, destType) \
+ (((union { \
+ __typeof__ (x) a; \
+ destType b; \
+ }) x) \
+ .b)
-typedef int (*cmp_t)(const void *, const void *);
+typedef int (*cmp_t) (const void *, const void *);
/* Enums */
-#define IS_VALID_ENUM_TYPE(NAME, x) ((x > NAME ## _UNDEFINED) && (x < NAME ## _N))
+#define IS_VALID_ENUM_TYPE(NAME, x) ((x > NAME##_UNDEFINED) && (x < NAME##_N))
+
+/* Float */
+
+uint32_t htonf (float f);
+float ntohf (uint32_t i);
#endif /* UTIL_TYPES */
diff --git a/lib/includes/hicn/util/vector.h b/lib/includes/hicn/util/vector.h
new file mode 100644
index 000000000..e693df9e3
--- /dev/null
+++ b/lib/includes/hicn/util/vector.h
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file vector.h
+ * \brief Resizeable static array
+ *
+ * A vector is a resizeable area of contiguous memory that contains elements of
+ * fixed size. It is mostly useful to serve as the basis for more advanced data
+ * structures such as memory pools.
+ *
+ * The internal API manipulates a pointer to the vector so that it can be
+ * seamlessly resized, and a more convenient user interface is provided through
+ * macros.
+ *
+ * A vector starts at index 0, and is typed according to the elements it
+ * contains. For that matter, the data structure header precedes the returned
+ * pointer which corresponds to the storage area.
+ *
+ * A vector is by default used as a stack where an end marker is maintained and
+ * new elements are pushed right after this end marker (an indication of
+ * the size of the vector) after ensuring the vector is sufficiently large.
+ *
+ * A user should not store any pointer to vector elements as this might change
+ * during reallocations, but should use indices instead.
+ *
+ * NOTE: a maximum size is currently not implemented.
+ *
+ * It is freely inspired (and simplified) from the VPP infra infrastructure
+ * library.
+ */
+
+#ifndef UTIL_VECTOR_H
+#define UTIL_VECTOR_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <stdbool.h>
+
+#include "../common.h"
+
+/******************************************************************************/
+/* Vector header */
+
+typedef struct
+{
+ size_t cur_size; /** Vector current size (corresponding to the highest used
+ element). */
+ 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 */
+#define VECTOR_HDRLEN SIZEOF_ALIGNED (vector_hdr_t)
+
+/* This header actually prepends the actual content of the vector */
+#define vector_hdr(vector) \
+ ((vector_hdr_t *) ((uint8_t *) vector - VECTOR_HDRLEN))
+
+/******************************************************************************/
+/* Helpers */
+
+/** Local variable naming macro. */
+#define _vector_var(v) _vector_##v
+
+/**
+ * @brief Allocate and initialize a vector data structure (helper function).
+ *
+ * @param[in,out] vector_ptr Vector to allocate and initialize.
+ * @param[in] elt_size Size of a vector element.
+ * @param[in] init_size Initial vector size.
+ * @param[in] max_size Maximum vector size (O = unlimited).
+ * @return int 0 if successful, -1 otherwise
+ */
+int _vector_init (void **vector_ptr, size_t elt_size, size_t init_size,
+ size_t max_size);
+
+/**
+ * @brief Free a vector data structure.
+ *
+ * @param vector_ptr[in] Pointer to the vector data structure to free.
+ */
+void _vector_free (void **vector_ptr);
+
+/**
+ * @brief Resize a vector data structure.
+ *
+ * @param[in] vector_ptr A pointer to the vector data structure to resize.
+ * @param[in] elt_size The size of a vector element.
+ * @param[in] pos The position at which the vector should be able to hold an
+ * element.
+ *
+ * @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
+ * instead ensure that it is large enough to hold an element at the specified
+ * position. This allows the caller not to care about doing successive calls to
+ * this API while the vector is growing in size.
+ */
+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
+ * given position.
+ *
+ * @param[in] vector_ptr A pointer to the vector data structure to resize.
+ * @param[in] elt_size The size of a vector element.
+ * @param[in] pos The position to validate.
+ *
+ * @return int Flag indicating whether the vector is available.
+ *
+ * NOTE:
+ * - This function should always be called before writing to a vector element
+ * to eventually make room for it (the vector will eventually be resized).
+ * - This function can fail if the vector is full and for any reason it cannot
+ * be resized.
+ */
+static inline int
+_vector_ensure_pos (void **vector_ptr, size_t elt_size, off_t pos)
+{
+ vector_hdr_t *vh = vector_hdr (*vector_ptr);
+ if (pos >= (off_t) vh->alloc_size)
+ return _vector_resize (vector_ptr, elt_size, pos + 1);
+ return 0;
+}
+
+/**
+ * @brief Push an element at the end of a vector.
+ *
+ * @param[in] vector_ptr A pointer to the vector data structure to resize.
+ * @param[in] elt_size The size of a vector element.
+ * @param[in] elt The element to insert.
+ *
+ * NOTE:
+ * - This function ensures there is sufficient room for inserting the element,
+ * and evenutually resizes the vector to make room for it (if allowed by
+ * maximum size).
+ */
+static inline 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) < 0)
+ return -1;
+
+ /* Always get header after a potential resize */
+ vh = vector_hdr (*vector_ptr);
+ memcpy ((uint8_t *) *vector_ptr + vh->cur_size * elt_size, elt, elt_size);
+ vh = vector_hdr (*vector_ptr);
+ vh->cur_size++;
+ return 0;
+}
+
+/**
+ * @brief Remove all the occurrencies of an element from the vector.
+ * The order of the elements is NOT maintained.
+ *
+ * @param[in, out] vector The vector data structure to resize
+ * @param[in] elt_size The size of a vector element
+ * @param[in] elt The element to remove
+ * @return int Number of elemets (equal to 'elt') removed from the vector
+ */
+static inline int
+_vector_remove_unordered (void *vector, size_t elt_size, void *elt)
+{
+ size_t num_removed = 0;
+ vector_hdr_t *vh = vector_hdr (vector);
+ for (size_t i = 0; i < vector_hdr (vector)->cur_size; i++)
+ {
+ if (memcmp ((uint8_t *) vector + i * elt_size, elt, elt_size) == 0)
+ {
+ vh->cur_size--;
+ // Copy last element to current position (hence order is not
+ // maintained)
+ memcpy ((uint8_t *) vector + i * elt_size,
+ (uint8_t *) vector + vh->cur_size * elt_size, elt_size);
+ num_removed++;
+ }
+ }
+ return (int) num_removed;
+}
+
+/**
+ * @brief Get the element at the specified position and store in 'elt'.
+ *
+ * @param[in] vector Pointer to the vector data structure to use
+ * @param[in] pos Position of the element to retrieve
+ * @param[in] elt_size The size of a vector element
+ * @param[in] elt The element where the result is stored
+ * @return int 0 if successful, -1 otherwise
+ */
+static inline int
+_vector_get (void *vector, off_t pos, size_t elt_size, void *elt)
+{
+ vector_hdr_t *vh = vector_hdr (vector);
+ if ((size_t) pos >= vh->alloc_size)
+ return -1;
+
+ memcpy (elt, (uint8_t *) vector + pos * elt_size, elt_size);
+ return 0;
+}
+
+/**
+ * @brief Check if specified element is present in vector.
+ *
+ * @param[in] vector Pointer to the vector data structure to use
+ * @param[in] elt_size The size of a vector element
+ * @param[in] elt The element to search for
+ * @return true If specified element is contained in the vector
+ * @return false
+ */
+static inline bool
+_vector_contains (void *vector, size_t elt_size, void *elt)
+{
+ for (size_t i = 0; i < vector_hdr (vector)->cur_size; i++)
+ {
+ if (memcmp ((uint8_t *) vector + i * elt_size, elt, elt_size) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * @brief Remove the element at the specified position from the vector.
+ * Relative element order is preserved by shifting left the elements after the
+ * target.
+ *
+ * @param[in, out] vector Pointer to the vector data structure to use
+ * @param[in] elt_size The size of a vector element
+ * @param[in] pos Position of the element to remove
+ * @return int 0 if successful, -1 otherwise
+ */
+static inline int
+_vector_remove_at (void **vector_ptr, size_t elt_size, off_t pos)
+{
+ vector_hdr_t *vh = vector_hdr (*vector_ptr);
+ if ((size_t) pos >= vh->cur_size)
+ return -1;
+
+ // Shift backward by one position all the elements after the one specified
+ memmove ((uint8_t *) (*vector_ptr) + pos * elt_size,
+ (uint8_t *) (*vector_ptr) + (pos + 1) * elt_size,
+ (vh->cur_size - 1 - pos) * elt_size);
+ vh->cur_size--;
+
+ return 0;
+}
+
+/******************************************************************************/
+/* Public API */
+
+/**
+ * @brief Allocate and initialize a vector data structure.
+ *
+ * @param[in,out] vector Vector to allocate and initialize.
+ * @param[in] init_size Initial vector size.
+ * @param[in] max_size Maximum vector size (nonzero).
+ *
+ * NOTE:
+ * - Allocated memory is set to 0 (used by bitmap)
+ */
+
+#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.
+ *
+ * @param[in] vector The vector data structure to free.
+ */
+#define vector_free(vector) _vector_free ((void **) &vector)
+
+/**
+ * @brief Resize a vector data structure.
+ *
+ * @param[in] vector The vector data structure to resize.
+ * @param[in] pos The position at which the vector should be able to hold an
+ * element.
+ *
+ * @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
+ * instead ensure that it is large enough to hold an element at the specified
+ * position. This allows the caller not to care about doing successive calls to
+ * 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)
+
+/**
+ * @brief Ensures a vector is sufficiently large to hold an element at the
+ * given position.
+ *
+ * @param[in] vector The vector for which to validate the position.
+ * @param[in] pos The position to validate.
+ *
+ * NOTE:
+ * - This function should always be called before writing to a vector element
+ * to eventually make room for it (the vector will eventually be resized).
+ */
+#define vector_ensure_pos(vector, pos) \
+ _vector_ensure_pos ((void **) &(vector), sizeof ((vector)[0]), pos);
+
+/**
+ * @brief Push an element at the end of a vector.
+ *
+ * @param[in] vector The vector in which to insert the element.
+ * @param[in] elt The element to insert.
+ *
+ * NOTE:
+ * - This function ensures there is sufficient room for inserting the element,
+ * and evenutually resizes the vector to make room for it (if allowed by
+ * maximum size).
+ */
+#define vector_push(vector, elt) \
+ ({ \
+ typeof (elt) _vector_var (x) = elt; \
+ _vector_push ((void **) &(vector), sizeof ((vector)[0]), \
+ (void *) (&_vector_var (x))); \
+ })
+
+#define vector_at(vector, pos) \
+ ({ \
+ assert ((size_t) pos < vector_hdr (vector)->cur_size); \
+ (vector)[(pos)]; \
+ })
+
+#define vector_set(vector, pos, elt) \
+ ({ \
+ assert (pos < vector_hdr (vector)->cur_size); \
+ (vector)[(pos)] = elt; \
+ })
+
+/**
+ * @brief Clear the vector content, i.e. new pushes will insert starting from
+ * position 0.
+ *
+ * @param[in, out] vector The vector to reset
+ */
+#define vector_reset(vector) (vector_len (vector) = 0)
+
+/**
+ * @brief Get the element at the specified position and store in 'elt'.
+ *
+ * @param[in] vector The vector data structure to use
+ * @param[in] pos Position of the element to retrieve
+ * @param[in] elt The element where the result is stored
+ * @return int 0 if successful, -1 otherwise
+ */
+#define vector_get(vector, pos, elt) \
+ _vector_get ((void *) (vector), (pos), sizeof ((vector)[0]), \
+ (void *) (&elt));
+
+/**
+ * @brief Check if specified element is present in vector.
+ *
+ * @param[in] vector The vector data structure to use
+ * @param[in] elt The element to search for
+ * @return true If specified element is contained in the vector
+ * @return false
+ */
+#define vector_contains(vector, elt) \
+ ({ \
+ typeof (elt) _vector_var (x) = elt; \
+ _vector_contains ((void *) (vector), sizeof ((vector)[0]), \
+ (void *) (&_vector_var (x))); \
+ })
+
+/**
+ * @brief Remove the element at the specified position from the vector.
+ * Relative element order is preserved by shifting left the elements after the
+ * target.
+ *
+ * @param[in, out] vector The vector data structure to use
+ * @param[in] pos Position of the element to remove
+ * @return int 0 if successful, -1 otherwise
+ */
+#define vector_remove_at(vector, pos) \
+ _vector_remove_at ((void **) &(vector), sizeof ((vector)[0]), (pos))
+
+/**
+ * @brief Remove all the occurrencies of an element from the vector.
+ * The order of the elements is NOT maintained.
+ *
+ * @param[in, out] vector The vector data structure to resize
+ * @param[in] elt The element to remove
+ * @return int Number of elemets (equal to 'elt') removed from the vector
+ */
+#define vector_remove_unordered(vector, elt) \
+ ({ \
+ typeof (elt) x = elt; \
+ _vector_remove_unordered ((void *) (vector), sizeof ((vector)[0]), \
+ (void *) (&x)); \
+ })
+
+/**
+ * @brief Returns the length of a vector.
+ *
+ * @param[in] vector The vector from which to get the size.
+ *
+ * @see vector_ensure_pos
+ *
+ * NOTE:
+ * - The size of the vector corresponds to the highest accessed index (for
+ * example as specified in the resize operation) and not the currently
+ * allocated size which will typically be bigger to amortize allocations.
+ * - 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
+
+/**
+ * @brief Returns the allocated size of a vector.
+ */
+#define vector_get_alloc_size(vector) vector_hdr (vector)->alloc_size
+
+/**
+ * @brief Iterate over elements in a vector.
+ *
+ * @param[in] pool The vector data structure to iterate over
+ * @param[in, out] eltp A pointer to the element that will be used for
+ * iteration
+ * @param[in] BODY Block to execute during iteration
+ *
+ * @note Iteration will execute BODY with eltp corresponding successively to
+ * all elements found in the vector. It is implemented using the more generic
+ * enumeration function.
+ */
+#define vector_foreach(vector, eltp, BODY) \
+ ({ \
+ unsigned _vector_var (i); \
+ vector_enumerate ((vector), _vector_var (i), (eltp), BODY); \
+ })
+
+/**
+ * @brief Helper function used by vector_foreach().
+ */
+#define vector_enumerate(vector, i, eltp, BODY) \
+ ({ \
+ for ((i) = 0; (i) < vector_len (vector); (i)++) \
+ { \
+ eltp = (vector) + (i); \
+ { \
+ BODY; \
+ } \
+ } \
+ })
+
+#endif /* UTIL_VECTOR_H */
diff --git a/lib/includes/hicn/util/win_portability.h b/lib/includes/hicn/util/win_portability.h
index 5f30cfbb2..609203afc 100644
--- a/lib/includes/hicn/util/win_portability.h
+++ b/lib/includes/hicn/util/win_portability.h
@@ -1,45 +1,45 @@
-/*
- * Copyright (c) 2019 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.
- */
-
-#pragma once
-#include <hicn/util/windows/windows_Utils.h>
-#include <afunix.h>
-#include <io.h>
-#include <iphlpapi.h>
-#include <process.h>
-#include <stdio.h>
-#pragma comment(lib, "IPHLPAPI.lib")
-
-#ifndef in_port_t
-#define in_port_t uint16_t
-#endif
-
-#ifndef in_addr_t
-#define in_addr_t uint32_t
-#endif
-
-#ifndef strncasecmp
-#define strncasecmp _strnicmp
-#endif
-
-#ifndef strcasecmp
-#define strcasecmp _stricmp
-#endif
-
-#define HAVE_STRUCT_TIMESPEC
-
-#ifndef getline
-int getline(char **lineptr, size_t *n, FILE *stream);
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <hicn/util/windows/windows_Utils.h>
+#include <afunix.h>
+#include <io.h>
+#include <iphlpapi.h>
+#include <process.h>
+#include <stdio.h>
+#pragma comment(lib, "IPHLPAPI.lib")
+
+#ifndef in_port_t
+#define in_port_t uint16_t
+#endif
+
+#ifndef in_addr_t
+#define in_addr_t uint32_t
+#endif
+
+#ifndef strncasecmp
+#define strncasecmp _strnicmp
+#endif
+
+#ifndef strcasecmp
+#define strcasecmp _stricmp
+#endif
+
+#define HAVE_STRUCT_TIMESPEC
+
+#ifndef getline
+int getline (char **lineptr, size_t *n, FILE *stream);
#endif \ No newline at end of file
diff --git a/lib/includes/hicn/util/windows/dlfcn.h b/lib/includes/hicn/util/windows/dlfcn.h
index 7775226cd..f1457964e 100644
--- a/lib/includes/hicn/util/windows/dlfcn.h
+++ b/lib/includes/hicn/util/windows/dlfcn.h
@@ -5,8 +5,8 @@
#define RTLD_GLOBAL 0x100 /* do not hide entries in this module */
#define RTLD_LOCAL 0x000 /* hide entries in this module */
-#define RTLD_LAZY 0x000 /* accept unresolved externs */
-#define RTLD_NOW 0x001 /* abort if module has unresolved externs */
+#define RTLD_LAZY 0x000 /* accept unresolved externs */
+#define RTLD_NOW 0x001 /* abort if module has unresolved externs */
/*
How to call in Windows:
@@ -16,15 +16,16 @@
*/
#ifdef __cplusplus
-extern "C" {
+extern "C"
+{
#endif
- void *dlopen (const char *filename, int flag);
- int dlclose (void *handle);
+ void *dlopen (const char *filename, int flag);
+ int dlclose (void *handle);
- void *dlsym (void *handle, const char *name);
+ void *dlsym (void *handle, const char *name);
-const char *dlerror (void);
+ const char *dlerror (void);
#ifdef __cplusplus
}
diff --git a/lib/includes/hicn/util/windows/windows_utils.h b/lib/includes/hicn/util/windows/windows_utils.h
index d24aaadbf..e15c0d752 100755..100644
--- a/lib/includes/hicn/util/windows/windows_utils.h
+++ b/lib/includes/hicn/util/windows/windows_utils.h
@@ -1,162 +1,166 @@
-/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WINDOWS_UTILS_H
-#define WINDOWS_UTILS_H
-#define WIN32_LEAN_AND_MEAN
-#define HAVE_STRUCT_TIMESPEC
-#ifndef NOMINMAX
-#define NOMINMAX
-#endif
-#include <Windows.h>
-#include <stdint.h>
-#include <io.h>
-#include <stdlib.h>
-#include <winsock2.h>
-#include <WS2tcpip.h>
-#include "dlfcn.h"
-
-#ifndef IOVEC
-#define IOVEC
-struct iovec {
- void* iov_base;
- size_t iov_len;
-};
-#endif
-
-typedef uint16_t in_port_t;
-
-#ifndef SLEEP
-#define SLEEP
-#define sleep Sleep
-#endif
-
-#ifndef USLEEP
-#define USLEEP
-void usleep(__int64 usec);
-#endif
-
-#ifndef S_ISDIR
-#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
-#endif
-
-#define PARCLibrary_DISABLE_ATOMICS
-#include <BaseTsd.h>
-typedef SSIZE_T ssize_t;
-
-#ifndef __ATTRIBUTE__
-#define __ATTRIBUTE__
-#define __attribute__(A)
-#endif
-
-#ifndef RESTRICT
-#define RESTRICT
-#define restrict __restrict
-#endif
-
-#ifndef GETTIMEOFDAY
-#define GETTIMEOFDAY
-int gettimeofday(struct timeval * tp, struct timezone * tzp);
-#endif
-
-#ifndef timersub
-#define timersub(a, b, result) \
- do { \
- (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
- (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
- if ((result)->tv_usec < 0) { \
- --(result)->tv_sec; \
- (result)->tv_usec += 1000000; \
- } \
- } while (0)
-#endif // timersub
-
-#ifndef dup
-#define dup _dup
-#endif
-
-#ifndef access
-#define access _access
-#endif
-
-#ifndef __cplusplus
-
-#ifndef read
-#define read _read
-#endif
-
-#ifndef close
-#define close _close
-#endif
-
-#ifndef write
-#define write _write
-#endif
-
-#ifndef open
-#define open _open
-#endif
-
-#endif
-
-#ifndef unlink
-#define unlink _unlink
-#endif
-
-#ifndef strcasecmp
-#define strncasecmp _strnicmp
-#endif
-
-#ifndef strcasecmp
-
-#define strcasecmp _stricmp
-#endif
-
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
-#endif
-#ifndef R_OK
-#define R_OK 4 /* Test for read permission. */
-#endif
-#ifndef W_OK
-#define W_OK 2 /* Test for write permission. */
-#endif
-#ifndef F_OK
-#define F_OK 0
-#endif
-
-#ifndef STDIN_FILENO
-#define STDIN_FILENO _fileno(stdin)
-#endif
-
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO _fileno(stdout)
-#endif
-
-#ifndef STDERR_FILENO
-#define STDERR_FILENO _fileno(stderr)
-#endif
-
-#endif
-
-#ifndef __bswap_constant_32
-#define __bswap_constant_32(x) \
- ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) \
- | (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24))
-#endif
-
-#ifndef bzero
-#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WINDOWS_UTILS_H
+#define WINDOWS_UTILS_H
+#define WIN32_LEAN_AND_MEAN
+#define HAVE_STRUCT_TIMESPEC
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <Windows.h>
+#include <stdint.h>
+#include <io.h>
+#include <stdlib.h>
+#include <winsock2.h>
+#include <WS2tcpip.h>
+#include "dlfcn.h"
+
+#ifndef IOVEC
+#define IOVEC
+struct iovec
+{
+ void *iov_base;
+ size_t iov_len;
+};
+#endif
+
+typedef uint16_t in_port_t;
+
+#ifndef SLEEP
+#define SLEEP
+#define sleep Sleep
+#endif
+
+#ifndef USLEEP
+#define USLEEP
+void usleep (__int64 usec);
+#endif
+
+#ifndef S_ISDIR
+#define S_ISDIR(mode) (((mode) &S_IFMT) == S_IFDIR)
+#endif
+
+#define PARCLibrary_DISABLE_ATOMICS
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
+
+#ifndef __ATTRIBUTE__
+#define __ATTRIBUTE__
+#define __attribute__(A)
+#endif
+
+#ifndef RESTRICT
+#define RESTRICT
+#define restrict __restrict
+#endif
+
+#ifndef GETTIMEOFDAY
+#define GETTIMEOFDAY
+int gettimeofday (struct timeval *tp, struct timezone *tzp);
+#endif
+
+#ifndef timersub
+#define timersub(a, b, result) \
+ do \
+ { \
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+ if ((result)->tv_usec < 0) \
+ { \
+ --(result)->tv_sec; \
+ (result)->tv_usec += 1000000; \
+ } \
+ } \
+ while (0)
+#endif // timersub
+
+#ifndef dup
+#define dup _dup
+#endif
+
+#ifndef access
+#define access _access
+#endif
+
+#ifndef __cplusplus
+
+#ifndef read
+#define read _read
+#endif
+
+#ifndef close
+#define close _close
+#endif
+
+#ifndef write
+#define write _write
+#endif
+
+#ifndef open
+#define open _open
+#endif
+
+#endif
+
+#ifndef unlink
+#define unlink _unlink
+#endif
+
+#ifndef strcasecmp
+#define strncasecmp _strnicmp
+#endif
+
+#ifndef strcasecmp
+
+#define strcasecmp _stricmp
+#endif
+
+#ifndef S_ISREG
+#define S_ISREG(mode) (((mode) &S_IFMT) == S_IFREG)
+#endif
+#ifndef R_OK
+#define R_OK 4 /* Test for read permission. */
+#endif
+#ifndef W_OK
+#define W_OK 2 /* Test for write permission. */
+#endif
+#ifndef F_OK
+#define F_OK 0
+#endif
+
+#ifndef STDIN_FILENO
+#define STDIN_FILENO _fileno (stdin)
+#endif
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO _fileno (stdout)
+#endif
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO _fileno (stderr)
+#endif
+
+#endif
+
+#ifndef __bswap_constant_32
+#define __bswap_constant_32(x) \
+ ((((x) &0xff000000u) >> 24) | (((x) &0x00ff0000u) >> 8) | \
+ (((x) &0x0000ff00u) << 8) | (((x) &0x000000ffu) << 24))
+#endif
+
+#ifndef bzero
+#define bzero(b, len) (memset ((b), '\0', (len)), (void) 0)
#endif \ No newline at end of file
diff --git a/lib/includes/hicn/validation.h b/lib/includes/hicn/validation.h
new file mode 100644
index 000000000..05be6d306
--- /dev/null
+++ b/lib/includes/hicn/validation.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file validation.h
+ * \brief Functions for input validation
+ */
+#include <ctype.h>
+#include <hicn/util/sstrncpy.h>
+
+static inline bool
+is_number (const char *string, size_t maxlen)
+{
+ size_t len = strnlen_s (string, maxlen);
+ for (size_t i = 0; i < len; i++)
+ {
+ if (!isdigit (string[i]))
+ return false;
+ }
+ return len != 0;
+}
+
+/**
+ * A symbolic name must be at least 1 character and must begin with an alpha.
+ * The remainder must be an alphanum.
+ */
+static inline bool
+is_symbolic_name (const char *name, size_t maxlen)
+{
+ size_t len = strnlen_s (name, maxlen);
+ if (len <= 0)
+ return false;
+ if (!isalpha (name[0]))
+ return false;
+
+ for (size_t i = 1; i < len; i++)
+ {
+ if (!isalnum (name[i]) && name[i] != '_' && name[i] != '-')
+ return false;
+ }
+
+ return true;
+}
diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt
index 2588bde8b..27446a493 100644
--- a/lib/src/CMakeLists.txt
+++ b/lib/src/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-2022 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
@@ -11,53 +11,124 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+##############################################################
+# Source and Header files
+##############################################################
list(APPEND LIBHICN_SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/common.c
- ${CMAKE_CURRENT_SOURCE_DIR}/compat.c
- ${CMAKE_CURRENT_SOURCE_DIR}/error.c
- ${CMAKE_CURRENT_SOURCE_DIR}/mapme.c
- ${CMAKE_CURRENT_SOURCE_DIR}/name.c
- ${CMAKE_CURRENT_SOURCE_DIR}/ops.c
- ${CMAKE_CURRENT_SOURCE_DIR}/policy.c
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ah.c
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/icmp.c
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ipv4.c
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ipv6.c
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/tcp.c
- ${CMAKE_CURRENT_SOURCE_DIR}/util/ip_address.c
- ${CMAKE_CURRENT_SOURCE_DIR}/util/log.c
+ base.c
+ common.c
+ error.c
+ face.c
+ mapme.c
+ name.c
+ ops.c
+ packet.c
+ policy.c
+ strategy.c
+ protocol/ah.c
+ protocol/icmp.c
+ protocol/ipv4.c
+ protocol/ipv6.c
+ protocol/tcp.c
+ protocol/udp.c
+ protocol/new.c
+ util/ip_address.c
+ util/log.c
+ util/pool.c
+ util/ring.c
+ util/slab.c
+ util/types.c
+ util/vector.c
)
if (WIN32)
list(APPEND LIBHICN_SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/util/windows/dlfcn.c
+ util/windows/dlfcn.c
)
endif ()
-set (COMPILER_DEFINITIONS "-DWITH_MAPME")
+
+##############################################################
+# Compiler definitions
+##############################################################
+set (COMPILER_DEFINITIONS
+ PUBLIC "-DWITH_MAPME"
+ PUBLIC "-DWITH_POLICY"
+)
include(BuildMacros)
include(WindowsMacros)
-if (DISABLE_SHARED_LIBRARIES)
- build_library(${LIBHICN}
- STATIC
- SOURCES ${LIBHICN_SOURCE_FILES} ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
- COMPONENT lib${LIBHICN}
- INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../includes
- DEFINITIONS ${COMPILER_DEFINITIONS}
- HEADER_ROOT_DIR hicn
- INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
- LINK_LIBRARIES ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
+##############################################################
+# Build type
+##############################################################
+set (BUILD_TYPES "STATIC")
+
+if (NOT DISABLE_SHARED_LIBRARIES)
+ list(APPEND BUILD_TYPES
+ "SHARED"
)
-else ()
- build_library(${LIBHICN}
- SHARED STATIC
- SOURCES ${LIBHICN_SOURCE_FILES} ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
- COMPONENT lib${LIBHICN}
- INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../includes
- DEFINITIONS ${COMPILER_DEFINITIONS}
- HEADER_ROOT_DIR hicn
- INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
- LINK_LIBRARIES ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
+endif()
+
+
+##############################################################
+# Compiler Options
+##############################################################
+set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+ PRIVATE "-Wno-address-of-packed-member"
+)
+
+
+##############################################################
+# Link libraries
+##############################################################
+if (WIN32)
+ list(APPEND LIBRARIES
+ PRIVATE ${WSOCK32_LIBRARY}
+ PRIVATE ${WS2_32_LIBRARY}
)
endif ()
+
+
+##############################################################
+# Build library
+##############################################################
+build_library(${LIBHICN}
+ ${BUILD_TYPES}
+ SOURCES ${LIBHICN_SOURCE_FILES}
+ COMPONENT ${LIBHICN_COMPONENT}
+ INCLUDE_DIRS
+ PUBLIC
+ $<BUILD_INTERFACE:${Libhicn_INCLUDE_DIRS}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ $<BUILD_INTERFACE:${THIRD_PARTY_INCLUDE_DIRS}>
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
+ DEPENDS ${THIRD_PARTY_DEPENDENCIES}
+ LINK_LIBRARIES
+ PRIVATE ${WSOCK32_LIBRARY}
+ PRIVATE ${WS2_32_LIBRARY}
+ PUBLIC ${THIRD_PARTY_LIBRARIES}
+ VERSION ${CURRENT_VERSION}
+ EXPORT_NAME ${LIBHICN_COMPONENT}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+)
+
+##############################################################
+# Unit tests
+##############################################################
+if (${BUILD_TESTS})
+ add_subdirectory(test)
+endif()
+
+
+##############################################################
+# Cmake config files
+##############################################################
+create_cmake_config (
+ ${LIBHICN_COMPONENT}
+ INCLUDE_DIRS ${HICN_INCLUDE_DIRS}
+ VERSION ${CURRENT_VERSION}
+ COMPONENT ${LIBHICN_COMPONENT}
+ NAMESPACE hicn
+)
diff --git a/lib/src/base.c b/lib/src/base.c
new file mode 100644
index 000000000..1852666a6
--- /dev/null
+++ b/lib/src/base.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file base.c
+ * @brief Implementation of base hICN definitions.
+ */
+
+#include <hicn/base.h>
+#include "ops.h"
+
+const char *_hicn_packet_type_str[] = {
+#define _(x) [HICN_PACKET_TYPE_##x] = #x,
+ foreach_packet_type
+#undef _
+};
+
+int
+hicn_packet_format_snprintf (char *s, size_t size, hicn_packet_format_t format)
+{
+ char *cur = s;
+ int rc;
+
+ HICN_PACKET_FORMAT_ENUMERATE (format, i, protocol, {
+ if (i > 0)
+ {
+ rc = snprintf (cur, size - (cur - s), "%s", "/");
+ if (rc < 0 || rc >= size - (cur - s))
+ return rc;
+ cur += rc;
+ }
+
+ rc = snprintf (cur, size - (cur - s), "%s", hicn_ops_vft[protocol]->name);
+ if (rc < 0 || rc >= size - (cur - s))
+ return rc;
+ cur += rc;
+ });
+ return (int) (cur - s);
+}
diff --git a/lib/src/common.c b/lib/src/common.c
index 562771e09..362034942 100644
--- a/lib/src/common.c
+++ b/lib/src/common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -20,8 +20,8 @@
*/
#include <stdlib.h>
-#include <string.h> // memset
-#include <sys/types.h> // getaddrinfo
+#include <string.h> // memset
+#include <sys/types.h> // getaddrinfo
#ifndef _WIN32
#include <sys/socket.h>
#include <netdb.h>
@@ -31,8 +31,6 @@
#include <hicn/common.h>
#include <hicn/util/log.h>
-
-
int
get_addr_family (const char *ip_address)
{
@@ -56,61 +54,48 @@ get_addr_family (const char *ip_address)
/* hashes */
-u32
-cumulative_hash32 (const void *data, size_t len, u32 lastValue)
-{
- // Standard FNV 32-bit prime: see http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
- const u32 fnv1a_prime = 0x01000193;
- u32 hash = lastValue;
- size_t i;
+// FNV-1a 32-bit http://www.isthe.com/chongo/tech/comp/fnv/
+typedef u_int32_t Fnv32_t;
+#define FNV_32_PRIME ((Fnv32_t) 0x01000193)
+#define FNV1_32_INIT ((Fnv32_t) 0x811c9dc5)
+#define FNV1_32A_INIT FNV1_32_INIT
- const char *chardata = data;
+Fnv32_t
+cumulative_hash32 (const void *buf, size_t len, Fnv32_t hval)
+{
+ unsigned char *bp = (unsigned char *) buf; /* start of buffer */
+ unsigned char *be = bp + len; /* beyond end of buffer */
- for (i = 0; i < len; i++)
+ /*
+ * FNV-1a hash each octet in the buffer
+ */
+ while (bp < be)
{
- hash = hash ^ chardata[i];
- hash = hash * fnv1a_prime;
- }
-
- return hash;
-}
-
-u32
-hash32 (const void *data, size_t len)
-{
- // Standard FNV 32-bit offset: see http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
- const u32 fnv1a_offset = 0x811C9DC5;
- return cumulative_hash32 (data, len, fnv1a_offset);
-}
-u64
-cumulative_hash64 (const void *data, size_t len, u64 lastValue)
-{
- // Standard FNV 64-bit prime: see http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
- const u64 fnv1a_prime = 0x00000100000001B3ULL;
- u64 hash = lastValue;
- const char *chardata = data;
- size_t i;
+ /* xor the bottom with the current octet */
+ hval ^= (Fnv32_t) *bp++;
- for (i = 0; i < len; i++)
- {
- hash = hash ^ chardata[i];
- hash = hash * fnv1a_prime;
+ /* multiply by the 32 bit FNV magic prime mod 2^32 */
+#if defined(NO_FNV_GCC_OPTIMIZATION)
+ hval *= FNV_32_PRIME;
+#else
+ hval +=
+ (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
+#endif
}
- return hash;
+ /* return our new hash value */
+ return hval;
}
-u64
-hash64 (const void *data, size_t len)
+u32
+hash32 (const void *data, size_t len)
{
- // Standard FNV 64-bit offset: see http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
- const u64 fnv1a_offset = 0xCBF29CE484222325ULL;
- return cumulative_hash64 (data, len, fnv1a_offset);
+ return cumulative_hash32 (data, len, FNV1_32A_INIT);
}
void
-hicn_packet_dump (const uint8_t * buffer, size_t len)
+hicn_packet_dump (const uint8_t *buffer, size_t len)
{
int i;
unsigned char buff[17];
diff --git a/lib/src/compat.c b/lib/src/compat.c
deleted file mode 100644
index 932c11d9e..000000000
--- a/lib/src/compat.c
+++ /dev/null
@@ -1,1273 +0,0 @@
-/*
- * Copyright (c) 2017-2019 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 compat.c
- * @brief Implementation of the compatibility layer.
- */
-#ifndef _WIN32
-#include <netinet/in.h>
-#endif
-#include <string.h> // memset
-#include <stddef.h> // offsetof
-
-#include <hicn/common.h>
-#include <hicn/compat.h>
-#include <hicn/error.h>
-#include <hicn/header.h>
-#include <hicn/name.h>
-#include <hicn/ops.h>
-
-#define member_size(type, member) sizeof (((type *) 0)->member)
-#define ARRAY_SIZE(a) (sizeof (a) / sizeof (*(a)))
-
-#define HICN_NAME_COMPONENT_SIZE 2
-
-int
-hicn_packet_get_format (const hicn_header_t *h, hicn_format_t *format)
-{
- *format = HF_UNSPEC;
-
- switch (HICN_IP_VERSION (h))
- {
- case 4:
- switch (h->v4.ip.protocol)
- {
- case IPPROTO_TCP:
- if (h->v4.tcp.flags & AH_FLAG)
- *format = HF_INET_TCP_AH;
- else
- *format = HF_INET_TCP;
- break;
- case IPPROTO_ICMP:
- *format = HF_INET_ICMP;
- break;
- default:
- return HICN_LIB_ERROR_NOT_HICN;
- }
- break;
- case 6:
- switch (h->v6.ip.nxt)
- {
- case IPPROTO_TCP:
- if (h->v6.tcp.flags & AH_FLAG)
- *format = HF_INET6_TCP_AH;
- else
- *format = HF_INET6_TCP;
- break;
- case IPPROTO_ICMPV6:
- *format = HF_INET6_ICMP;
- break;
- default:
- return HICN_LIB_ERROR_NOT_HICN;
- }
- break;
- default:
- return HICN_LIB_ERROR_NOT_HICN;
- }
-
- return HICN_LIB_ERROR_NONE;
-}
-
-/**
- * @brief Convert (former) hICN format into (newer) hICN type
- * @param [in] format - hICN format
- * @return hICN type, all zero'ed if type is unknown
- */
-hicn_type_t
-hicn_format_to_type (hicn_format_t format)
-{
- switch (format)
- {
- case HF_INET_TCP:
- return HICN_TYPE_IPV4_TCP;
- case HF_INET6_TCP:
- return HICN_TYPE_IPV6_TCP;
- case HF_INET_ICMP:
- return HICN_TYPE_IPV4_ICMP;
- case HF_INET6_ICMP:
- return HICN_TYPE_IPV6_ICMP;
- case HF_INET_TCP_AH:
- return HICN_TYPE_IPV4_TCP_AH;
- case HF_INET6_TCP_AH:
- return HICN_TYPE_IPV6_TCP_AH;
- case HF_INET_ICMP_AH:
- return HICN_TYPE_IPV4_ICMP_AH;
- case HF_INET6_ICMP_AH:
- return HICN_TYPE_IPV6_ICMP_AH;
- default:
- break;
- }
- return HICN_TYPE_NONE;
-}
-
-/**
- * @brief Parse hICN header and return hICN type
- * @param [in] h - hICN header
- * @param [out] format - hICN type
- * @return hICN error code
- *
- * This function is used to wrap old API calls to new ones
- */
-hicn_type_t
-hicn_header_to_type (const hicn_header_t *h)
-{
- hicn_format_t format;
- hicn_packet_get_format (h, &format);
- return hicn_format_to_type (format);
-}
-
-int
-hicn_packet_init_header (hicn_format_t format, hicn_header_t *packet)
-{
- hicn_type_t type = hicn_format_to_type (format);
-
- if (hicn_type_is_none (type))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- return hicn_ops_vft[type.l1]->init_packet_header (type, &packet->protocol);
-}
-
-int
-hicn_packet_compute_checksum (hicn_format_t format, hicn_header_t *h)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->update_checksums (type, &h->protocol, 0, ~0);
-}
-
-int
-hicn_packet_compute_header_checksum (hicn_format_t format, hicn_header_t *h,
- u16 init_sum)
-{
- hicn_type_t type = hicn_format_to_type (format);
- /* payload_length == 0: ignore payload */
- return hicn_ops_vft[type.l1]->update_checksums (type, &h->protocol, init_sum,
- 0);
-}
-
-int
-hicn_packet_check_integrity_no_payload (hicn_format_t format, hicn_header_t *h,
- u16 init_sum)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->verify_checksums (type, &h->protocol, init_sum,
- 0);
-}
-
-int
-hicn_packet_get_header_length_from_format (hicn_format_t format,
- size_t *header_length)
-{
- *header_length = _is_ipv4 (format) * IPV4_HDRLEN;
- *header_length += _is_ipv6 (format) * IPV6_HDRLEN;
- *header_length += _is_icmp (format) * ICMP_HDRLEN;
- *header_length += _is_tcp (format) * TCP_HDRLEN;
- *header_length += _is_ah (format) * AH_HDRLEN;
-
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_get_header_length (hicn_format_t format, const hicn_header_t *h,
- size_t *header_length)
-{
- hicn_packet_get_header_length_from_format (format, header_length);
- int is_ah = _is_ah (format);
- int is_ipv4 = _is_ipv4 (format);
- int is_ipv6 = _is_ipv6 (format);
- // The signature payload is expressed as number of 32 bits words
- if (is_ah && is_ipv4)
- *header_length += (h->v4ah.ah.payloadlen) << 2;
- else if (is_ah && is_ipv6)
- *header_length += (h->v6ah.ah.payloadlen) << 2;
-
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_get_payload_length (hicn_format_t format, const hicn_header_t *h,
- size_t *payload_length)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->get_payload_length (type, &h->protocol,
- payload_length);
-}
-
-int
-hicn_packet_set_payload_length (hicn_format_t format, hicn_header_t *h,
- const size_t payload_length)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->set_payload_length (type, &h->protocol,
- payload_length);
-}
-
-int
-hicn_packet_compare (const hicn_header_t *packet1,
- const hicn_header_t *packet2)
-{
- hicn_type_t type1 = hicn_header_to_type (packet1);
- hicn_type_t type2 = hicn_header_to_type (packet2);
-
- size_t len1, len2;
- int rc;
-
- if (type1.as_u32 != type2.as_u32)
- return HICN_LIB_ERROR_UNEXPECTED;
-
- rc = hicn_ops_vft[type1.l1]->get_length (type1, &packet1->protocol, &len1);
- if (PREDICT_FALSE (rc < 0))
- return HICN_LIB_ERROR_UNEXPECTED;
-
- rc = hicn_ops_vft[type2.l1]->get_length (type2, &packet2->protocol, &len2);
- if (PREDICT_FALSE (rc < 0))
- return HICN_LIB_ERROR_UNEXPECTED;
-
- if (len1 != len2)
- return HICN_LIB_ERROR_UNEXPECTED;
-
- return memcmp ((u8 *) packet1, (u8 *) packet2, len1);
-}
-
-int
-hicn_packet_get_name (hicn_format_t format, const hicn_header_t *h,
- hicn_name_t *name, u8 is_interest)
-{
- hicn_type_t type = hicn_format_to_type (format);
-
- if (is_interest)
- return hicn_ops_vft[type.l1]->get_interest_name (type, &h->protocol, name);
- else
- return hicn_ops_vft[type.l1]->get_data_name (type, &h->protocol, name);
-}
-
-int
-hicn_packet_set_name (hicn_format_t format, hicn_header_t *h,
- const hicn_name_t *name, u8 is_interest)
-{
- hicn_type_t type = hicn_format_to_type (format);
-
-#ifndef HICN_VPP_PLUGIN
- if (name->type & HNT_IOV)
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
-#endif /* HICN_VPP_PLUGIN */
-
- if (is_interest)
- return hicn_ops_vft[type.l1]->set_interest_name (type, &h->protocol, name);
- else
- return hicn_ops_vft[type.l1]->set_data_name (type, &h->protocol, name);
-}
-
-int
-hicn_packet_set_payload (hicn_format_t format, hicn_header_t *h,
- const u8 *payload, u16 payload_length)
-{
- hicn_type_t type = hicn_format_to_type (format);
- size_t header_length;
- int rc;
-
- rc = hicn_ops_vft[type.l1]->get_header_length (type, &h->protocol,
- &header_length);
- if (rc < 0)
- return rc;
-
- memcpy ((u8 *) h + header_length, payload, payload_length);
-
- return hicn_ops_vft[type.l1]->set_payload_length (type, &h->protocol,
- payload_length);
-}
-
-int
-hicn_packet_get_payload (hicn_format_t format, const hicn_header_t *h,
- u8 **payload, size_t *payload_size, bool hard_copy)
-{
- size_t header_length, payload_length;
- int rc;
- hicn_type_t type = hicn_format_to_type (format);
-
- rc = hicn_ops_vft[type.l1]->get_header_length (type, &h->protocol,
- &header_length);
- if (rc < 0)
- return rc;
-
- rc = hicn_ops_vft[type.l1]->get_payload_length (type, &h->protocol,
- &payload_length);
- if (rc < 0)
- return rc;
-
- if (hard_copy)
- {
- memcpy (payload, (u8 *) h + header_length, payload_length);
- }
- else
- {
- *payload = (u8 *) h + header_length;
- }
-
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_get_locator (hicn_format_t format, const hicn_header_t *h,
- ip_address_t *address, bool is_interest)
-{
- int is_ipv4 = (format & HFO_INET);
- int is_ipv6 = (format & HFO_INET6) >> 1;
-
- if (is_ipv4)
- {
- address->v4.as_inaddr =
- is_interest ? h->v4.ip.saddr.as_inaddr : h->v4.ip.daddr.as_inaddr;
- }
- else if (is_ipv6)
- {
- address->v6.as_in6addr =
- is_interest ? h->v6.ip.saddr.as_in6addr : h->v6.ip.daddr.as_in6addr;
- }
- else
- {
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
-
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_set_locator (hicn_format_t format, hicn_header_t *h,
- const ip_address_t *address, bool is_interest)
-{
- int is_ipv4 = (format & HFO_INET);
- int is_ipv6 = (format & HFO_INET6) >> 1;
-
- if (is_ipv6)
- {
- if (is_interest)
- h->v6.ip.saddr.as_in6addr = address->v6.as_in6addr;
- else
- h->v6.ip.daddr.as_in6addr = address->v6.as_in6addr;
- }
- else if (is_ipv4)
- {
- if (is_interest)
- h->v4.ip.saddr.as_inaddr = address->v4.as_inaddr;
- else
- h->v4.ip.daddr.as_inaddr = address->v4.as_inaddr;
- }
- else
- {
- return HICN_LIB_ERROR_INVALID_PARAMETER;
- }
-
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_get_signature_size (hicn_format_t format, const hicn_header_t *h,
- size_t *bytes)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->get_signature_size (type, &h->protocol, bytes);
-}
-
-int
-hicn_packet_set_signature_size (hicn_format_t format, hicn_header_t *h,
- size_t bytes)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->set_signature_size (type, &h->protocol, bytes);
-}
-
-int
-hicn_packet_get_signature_gap (hicn_format_t format, const hicn_header_t *h,
- uint8_t *bytes)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->get_signature_gap (type, &h->protocol, bytes);
-}
-
-int
-hicn_packet_set_signature_gap (hicn_format_t format, hicn_header_t *h,
- uint8_t bytes)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->set_signature_gap (type, &h->protocol, bytes);
-}
-
-int
-hicn_packet_set_signature_timestamp (hicn_format_t format, hicn_header_t *h,
- uint64_t signature_timestamp)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->set_signature_timestamp (type, &h->protocol,
- signature_timestamp);
-}
-
-int
-hicn_packet_get_signature_timestamp (hicn_format_t format,
- const hicn_header_t *h,
- uint64_t *signature_timestamp)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->get_signature_timestamp (type, &h->protocol,
- signature_timestamp);
-}
-
-int
-hicn_packet_set_validation_algorithm (hicn_format_t format, hicn_header_t *h,
- uint8_t validation_algorithm)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->set_validation_algorithm (
- type, &h->protocol, validation_algorithm);
-}
-
-int
-hicn_packet_get_validation_algorithm (hicn_format_t format,
- const hicn_header_t *h,
- uint8_t *validation_algorithm)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->get_validation_algorithm (
- type, &h->protocol, validation_algorithm);
-}
-
-int
-hicn_packet_set_key_id (hicn_format_t format, hicn_header_t *h,
- uint8_t *key_id)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->set_key_id (type, &h->protocol, key_id);
-}
-
-int
-hicn_packet_get_key_id (hicn_format_t format, hicn_header_t *h,
- uint8_t **key_id, uint8_t *key_id_length)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->get_key_id (type, &h->protocol, key_id,
- key_id_length);
-}
-
-int
-hicn_packet_get_hoplimit (const hicn_header_t *h, u8 *hops)
-{
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- *hops = h->v6.ip.hlim;
- break;
- case 4:
- *hops = h->v4.ip.ttl;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_set_hoplimit (hicn_header_t *h, u8 hops)
-{
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.ip.hlim = hops;
- break;
- case 4:
- h->v4.ip.ttl = hops;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_get_lifetime (const hicn_header_t *h, u32 *lifetime)
-{
- hicn_type_t type = hicn_header_to_type (h);
- return hicn_ops_vft[type.l1]->get_lifetime (type, &h->protocol,
- (hicn_lifetime_t *) lifetime);
-}
-
-int
-hicn_packet_set_lifetime (hicn_header_t *h, u32 lifetime)
-{
- hicn_type_t type = hicn_header_to_type (h);
- return hicn_ops_vft[type.l1]->set_lifetime (type, &h->protocol,
- (hicn_lifetime_t) lifetime);
-}
-
-int
-hicn_packet_get_reserved_bits (const hicn_header_t *h, u8 *reserved_bits)
-{
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- *reserved_bits = (u8) (h->v6.tcp.reserved);
- break;
- case 4:
- *reserved_bits = (u8) (h->v4.tcp.reserved);
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_set_reserved_bits (hicn_header_t *h, const u8 reserved_bits)
-{
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.reserved = reserved_bits;
- break;
- case 4:
- h->v4.tcp.reserved = reserved_bits;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_get_payload_type (const hicn_header_t *h,
- hicn_payload_type_t *payload_type)
-{
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- *payload_type =
- ((h->v6.tcp.flags & HICN_TCP_FLAG_URG) == HICN_TCP_FLAG_URG);
- break;
- case 4:
- *payload_type =
- ((h->v4.tcp.flags & HICN_TCP_FLAG_URG) == HICN_TCP_FLAG_URG);
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- if (*payload_type == HPT_UNSPEC)
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_set_payload_type (hicn_header_t *h,
- hicn_payload_type_t payload_type)
-{
- if (payload_type != HPT_DATA && payload_type != HPT_MANIFEST)
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- if (payload_type)
- h->v6.tcp.flags = h->v6.tcp.flags | HICN_TCP_FLAG_URG;
- else
- h->v6.tcp.flags = h->v6.tcp.flags & ~HICN_TCP_FLAG_URG;
- break;
- case 4:
- if (payload_type)
- h->v4.tcp.flags = h->v4.tcp.flags | HICN_TCP_FLAG_URG;
- else
- h->v4.tcp.flags = h->v4.tcp.flags & ~HICN_TCP_FLAG_URG;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_set_syn (hicn_format_t format, hicn_header_t *h)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.flags = h->v6.tcp.flags | HICN_TCP_FLAG_SYN;
- break;
- case 4:
- h->v4.tcp.flags = h->v4.tcp.flags | HICN_TCP_FLAG_SYN;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_reset_syn (hicn_format_t format, hicn_header_t *h)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.flags = h->v6.tcp.flags & ~HICN_TCP_FLAG_SYN;
- break;
- case 4:
- h->v4.tcp.flags = h->v4.tcp.flags & ~HICN_TCP_FLAG_SYN;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_test_syn (hicn_format_t format, const hicn_header_t *h, bool *flag)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- *flag = h->v6.tcp.flags & HICN_TCP_FLAG_SYN;
- break;
- case 4:
- *flag = h->v4.tcp.flags & HICN_TCP_FLAG_SYN;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_set_ack (hicn_format_t format, hicn_header_t *h)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.flags = h->v6.tcp.flags | HICN_TCP_FLAG_ACK;
- break;
- case 4:
- h->v4.tcp.flags = h->v4.tcp.flags | HICN_TCP_FLAG_ACK;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_reset_ack (hicn_format_t format, hicn_header_t *h)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.flags = h->v6.tcp.flags & ~HICN_TCP_FLAG_ACK;
- break;
- case 4:
- h->v4.tcp.flags = h->v4.tcp.flags & ~HICN_TCP_FLAG_ACK;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_test_ack (hicn_format_t format, const hicn_header_t *h, bool *flag)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- *flag = h->v6.tcp.flags & HICN_TCP_FLAG_ACK;
- break;
- case 4:
- *flag = h->v4.tcp.flags & HICN_TCP_FLAG_ACK;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_set_rst (hicn_format_t format, hicn_header_t *h)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.flags = h->v6.tcp.flags | HICN_TCP_FLAG_RST;
- break;
- case 4:
- h->v4.tcp.flags = h->v4.tcp.flags | HICN_TCP_FLAG_RST;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_reset_rst (hicn_format_t format, hicn_header_t *h)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.flags = h->v6.tcp.flags & ~HICN_TCP_FLAG_RST;
- break;
- case 4:
- h->v4.tcp.flags = h->v4.tcp.flags & ~HICN_TCP_FLAG_RST;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_test_rst (hicn_format_t format, const hicn_header_t *h, bool *flag)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- *flag = h->v6.tcp.flags & HICN_TCP_FLAG_RST;
- break;
- case 4:
- *flag = h->v4.tcp.flags & HICN_TCP_FLAG_RST;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_set_fin (hicn_format_t format, hicn_header_t *h)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.flags = h->v6.tcp.flags | HICN_TCP_FLAG_FIN;
- break;
- case 4:
- h->v4.tcp.flags = h->v4.tcp.flags | HICN_TCP_FLAG_FIN;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_reset_fin (hicn_format_t format, hicn_header_t *h)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.flags = h->v6.tcp.flags & ~HICN_TCP_FLAG_FIN;
- break;
- case 4:
- h->v4.tcp.flags = h->v4.tcp.flags & ~HICN_TCP_FLAG_FIN;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_test_fin (hicn_format_t format, const hicn_header_t *h, bool *flag)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- *flag = h->v6.tcp.flags & HICN_TCP_FLAG_FIN;
- break;
- case 4:
- *flag = h->v4.tcp.flags & HICN_TCP_FLAG_FIN;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_set_ece (hicn_format_t format, hicn_header_t *h)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.flags = h->v6.tcp.flags | HICN_TCP_FLAG_ECE;
- break;
- case 4:
- h->v4.tcp.flags = h->v4.tcp.flags | HICN_TCP_FLAG_ECE;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_reset_ece (hicn_format_t format, hicn_header_t *h)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.flags = h->v6.tcp.flags & ~HICN_TCP_FLAG_ECE;
- break;
- case 4:
- h->v4.tcp.flags = h->v4.tcp.flags & ~HICN_TCP_FLAG_ECE;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_test_ece (hicn_format_t format, const hicn_header_t *h, bool *flag)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- *flag = h->v6.tcp.flags & HICN_TCP_FLAG_ECE;
- break;
- case 4:
- *flag = h->v4.tcp.flags & HICN_TCP_FLAG_ECE;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_set_src_port (hicn_format_t format, hicn_header_t *h, u16 src_port)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.sport = htons (src_port);
- break;
- case 4:
- h->v4.tcp.sport = htons (src_port);
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_get_src_port (hicn_format_t format, const hicn_header_t *h,
- u16 *src_port)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- *src_port = ntohs (h->v6.tcp.sport);
- break;
- case 4:
- *src_port = ntohs (h->v4.tcp.sport);
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_set_dst_port (hicn_format_t format, hicn_header_t *h, u16 dst_port)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- h->v6.tcp.dport = htons (dst_port);
- break;
- case 4:
- h->v4.tcp.dport = htons (dst_port);
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_get_dst_port (hicn_format_t format, const hicn_header_t *h,
- u16 *dst_port)
-{
- if (!_is_tcp (format))
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- *dst_port = ntohs (h->v6.tcp.dport);
- break;
- case 4:
- *dst_port = ntohs (h->v4.tcp.dport);
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
- return HICN_LIB_ERROR_NONE;
-}
-
-int
-hicn_packet_copy_header (hicn_format_t format, const hicn_header_t *packet,
- hicn_header_t *destination, bool copy_ah)
-{
- size_t header_length = _is_ipv4 (format) * IPV4_HDRLEN;
- header_length += _is_ipv6 (format) * IPV6_HDRLEN;
- header_length += _is_icmp (format) * ICMP_HDRLEN;
- header_length += _is_tcp (format) * TCP_HDRLEN;
- header_length += _is_ah (format) * copy_ah * AH_HDRLEN;
-
- memcpy (destination, packet, header_length);
-
- return HICN_LIB_ERROR_NONE;
-}
-
-#define _INTEREST 1
-#define _DATA 0
-
-/* Interest */
-
-int
-hicn_interest_get_name (hicn_format_t format, const hicn_header_t *interest,
- hicn_name_t *name)
-{
- return hicn_packet_get_name (format, interest, name, _INTEREST);
-}
-
-int
-hicn_interest_set_name (hicn_format_t format, hicn_header_t *interest,
- const hicn_name_t *name)
-{
- int ret_err = hicn_packet_reset_ece (
- format, interest); // interest packet -> ece flag unset
- if (ret_err < 0)
- return HICN_LIB_ERROR_UNEXPECTED;
- return hicn_packet_set_name (format, interest, name, _INTEREST);
-}
-
-int
-hicn_interest_get_locator (hicn_format_t format, const hicn_header_t *interest,
- ip_address_t *address)
-{
- return hicn_packet_get_locator (format, interest, address, _INTEREST);
-}
-
-int
-hicn_interest_set_locator (hicn_format_t format, hicn_header_t *interest,
- const ip_address_t *address)
-{
- return hicn_packet_set_locator (format, interest, address, _INTEREST);
-}
-
-int
-hicn_interest_compare (const hicn_header_t *interest_1,
- const hicn_header_t *interest_2)
-{
- return hicn_packet_compare (interest_1, interest_2);
-}
-
-int
-hicn_interest_get_lifetime (const hicn_header_t *interest, u32 *lifetime)
-{
- return hicn_packet_get_lifetime (interest, lifetime);
-}
-
-int
-hicn_interest_set_lifetime (hicn_header_t *interest, u32 lifetime)
-{
- return hicn_packet_set_lifetime (interest, lifetime);
-}
-
-int
-hicn_interest_get_header_length (hicn_format_t format,
- const hicn_header_t *interest,
- size_t *header_length)
-{
- return hicn_packet_get_header_length (format, interest, header_length);
-}
-
-int
-hicn_interest_get_payload_length (hicn_format_t format,
- const hicn_header_t *interest,
- size_t *payload_length)
-{
- return hicn_packet_get_payload_length (format, interest, payload_length);
-}
-
-int
-hicn_interest_get_payload (hicn_format_t format, const hicn_header_t *interest,
- u8 **payload, size_t *payload_size, bool hard_copy)
-{
- return hicn_packet_get_payload (format, interest, payload, payload_size,
- hard_copy);
-}
-
-int
-hicn_interest_set_payload (hicn_format_t format, hicn_header_t *interest,
- const u8 *payload, size_t payload_length)
-{
- return hicn_packet_set_payload (format, interest, payload,
- (u16) payload_length);
-}
-
-int
-hicn_interest_reset_for_hash (hicn_format_t format, hicn_header_t *packet)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->reset_interest_for_hash (type,
- &packet->protocol);
-}
-
-/* Data */
-
-int
-hicn_data_get_name (hicn_format_t format, const hicn_header_t *data,
- hicn_name_t *name)
-{
- return hicn_packet_get_name (format, data, name, _DATA);
-}
-
-int
-hicn_data_set_name (hicn_format_t format, hicn_header_t *data,
- const hicn_name_t *name)
-{
- int ret_err =
- hicn_packet_set_ece (format, data); // data packet -> ece flag set
- if (ret_err < 0)
- return HICN_LIB_ERROR_UNEXPECTED;
- return hicn_packet_set_name (format, data, name, _DATA);
-}
-
-int
-hicn_data_get_locator (hicn_format_t format, const hicn_header_t *data,
- ip_address_t *address)
-{
- return hicn_packet_get_locator (format, data, address, _DATA);
-}
-
-int
-hicn_data_set_locator (hicn_format_t format, hicn_header_t *data,
- const ip_address_t *address)
-{
- return hicn_packet_set_locator (format, data, address, _DATA);
-}
-
-int
-hicn_data_compare (const hicn_header_t *data_1, const hicn_header_t *data_2)
-{
- return hicn_packet_compare (data_1, data_2);
-}
-
-int
-hicn_data_get_expiry_time (const hicn_header_t *data, u32 *expiry_time)
-{
- return hicn_packet_get_lifetime (data, expiry_time);
-}
-
-int
-hicn_data_set_expiry_time (hicn_header_t *data, u32 expiry_time)
-{
- return hicn_packet_set_lifetime (data, (hicn_lifetime_t) expiry_time);
-}
-
-int
-hicn_data_get_header_length (hicn_format_t format, hicn_header_t *data,
- size_t *header_length)
-{
- return hicn_packet_get_header_length (format, data, header_length);
-}
-
-int
-hicn_data_get_payload_length (hicn_format_t format, const hicn_header_t *data,
- size_t *payload_length)
-{
- return hicn_packet_get_payload_length (format, data, payload_length);
-}
-
-int
-hicn_data_set_payload_type (hicn_header_t *data,
- hicn_payload_type_t payload_type)
-{
- return hicn_packet_set_payload_type (data, payload_type);
-}
-
-int
-hicn_data_get_payload_type (const hicn_header_t *data,
- hicn_payload_type_t *payload_type)
-{
- return hicn_packet_get_payload_type (data, payload_type);
-}
-
-int
-hicn_data_get_path_label (const hicn_header_t *data, u32 *path_label)
-{
- hicn_type_t type = hicn_header_to_type (data);
- return hicn_ops_vft[type.l1]->get_data_pathlabel (type, &data->protocol,
- path_label);
-}
-
-int
-hicn_data_set_path_label (hicn_header_t *data, u32 path_label)
-{
- hicn_type_t type = hicn_header_to_type (data);
- return hicn_ops_vft[type.l1]->set_data_pathlabel (type, &data->protocol,
- path_label);
-}
-
-int
-hicn_data_set_payload (hicn_format_t format, hicn_header_t *data,
- const u8 *payload, size_t payload_length)
-{
- return hicn_packet_set_payload (format, data, payload, (u16) payload_length);
-}
-
-int
-hicn_data_get_payload (hicn_format_t format, const hicn_header_t *data,
- u8 **payload, size_t *payload_size, bool hard_copy)
-{
- return hicn_packet_get_payload (format, data, payload, payload_size,
- hard_copy);
-}
-
-int
-hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t *packet)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->reset_data_for_hash (type, &packet->protocol);
-}
-
-int
-hicn_packet_get_signature (hicn_format_t format, hicn_header_t *packet,
- uint8_t **sign_buf)
-{
- hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->get_signature (type, &packet->protocol,
- sign_buf);
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/lib/src/error.c b/lib/src/error.c
index ab5d6e27d..0d7c80d9b 100644
--- a/lib/src/error.c
+++ b/lib/src/error.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -21,7 +21,7 @@
#include <hicn/error.h>
const char *HICN_LIB_ERROR_STRING[] = {
-#define _(a,b,c) [b] = c,
+#define _(a, b, c) [b] = c,
foreach_libhicn_error
#undef _
};
diff --git a/lib/src/face.c b/lib/src/face.c
new file mode 100644
index 000000000..81395c4b1
--- /dev/null
+++ b/lib/src/face.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file face.c
+ * \brief Implementation of face abstraction
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <hicn/face.h>
+#include <hicn/util/token.h>
+
+#define member_size(type, member) sizeof (((type *) 0)->member)
+
+/* Netdevice */
+
+const char *_netdevice_type_str[] = {
+#define _(x) [NETDEVICE_TYPE_##x] = STRINGIZE (x),
+ foreach_netdevice_type
+#undef _
+};
+
+netdevice_t *
+netdevice_create_from_index (u32 index)
+{
+ netdevice_t *netdevice = malloc (sizeof (netdevice_t));
+ if (!netdevice)
+ goto ERR_MALLOC;
+
+ int rc = netdevice_set_index (netdevice, index);
+ if (rc < 0)
+ goto ERR_INIT;
+
+ return netdevice;
+
+ERR_INIT:
+ free (netdevice);
+ERR_MALLOC:
+ return NULL;
+}
+
+netdevice_t *
+netdevice_create_from_name (const char *name)
+{
+ netdevice_t *netdevice = malloc (sizeof (netdevice_t));
+ if (!netdevice)
+ goto ERR_MALLOC;
+
+ int rc = netdevice_set_name (netdevice, name);
+ if (rc < 0)
+ goto ERR_INIT;
+
+ return netdevice;
+
+ERR_INIT:
+ free (netdevice);
+ERR_MALLOC:
+ return NULL;
+}
+
+/**
+ * \brief Update the index of the netdevice based on the name
+ */
+int
+netdevice_update_index (netdevice_t *netdevice)
+{
+ netdevice->index = if_nametoindex (netdevice->name);
+ if (netdevice->index == 0)
+ return -1;
+ return 0;
+}
+
+int
+netdevice_update_name (netdevice_t *netdevice)
+{
+ if (!if_indextoname (netdevice->index, netdevice->name))
+ return -1;
+ return 0;
+}
+
+void
+netdevice_free (netdevice_t *netdevice)
+{
+ free (netdevice);
+}
+
+int
+netdevice_get_index (const netdevice_t *netdevice, u32 *index)
+{
+ if (netdevice->index == 0)
+ return -1;
+ *index = netdevice->index;
+ return 0;
+}
+
+int
+netdevice_set_index (netdevice_t *netdevice, u32 index)
+{
+ netdevice->index = index;
+ return netdevice_update_name (netdevice);
+}
+
+int
+netdevice_get_name (const netdevice_t *netdevice, const char **name)
+{
+ if (netdevice->name[0] == '\0')
+ return -1;
+ *name = netdevice->name;
+ return 0;
+}
+
+int
+netdevice_set_name (netdevice_t *netdevice, const char *name)
+{
+ memset (netdevice->name, 0, sizeof (netdevice->name));
+ int rc = snprintf (netdevice->name, IFNAMSIZ, "%s", name);
+ if (rc < 0)
+ return -1;
+ if (rc >= IFNAMSIZ)
+ return -2; /* truncated */
+ return netdevice_update_index (netdevice);
+}
+
+int
+netdevice_cmp (const netdevice_t *nd1, const netdevice_t *nd2)
+{
+ return (nd1->index - nd2->index);
+}
+
+bool
+netdevice_is_empty (const netdevice_t *netdevice)
+{
+ return (netdevice->index != 0) || (netdevice->name[0] != '\0');
+}
+
+/* Face state */
+
+const char *_face_state_str[] = {
+#define _(x) [FACE_STATE_##x] = STRINGIZE (x),
+ foreach_face_state
+#undef _
+};
+
+/* Face type */
+
+const char *_face_type_str[] = {
+#define _(x) [FACE_TYPE_##x] = STRINGIZE (x),
+ foreach_face_type
+#undef _
+};
+
+face_type_t
+face_type_from_str (const char *str)
+{
+#define _(x) \
+ if (strcasecmp (str, STRINGIZE (x)) == 0) \
+ return FACE_TYPE_##x; \
+ else
+ foreach_face_type
+#undef _
+ return FACE_TYPE_UNDEFINED;
+}
+
+/* Face */
+
+int
+face_initialize (face_t *face)
+{
+ memset (face, 0, sizeof (face_t)); /* 0'ed for hash */
+ return 1;
+}
+
+int
+face_initialize_udp (face_t *face, const char *interface_name,
+ const hicn_ip_address_t *local_addr, u16 local_port,
+ const hicn_ip_address_t *remote_addr, u16 remote_port,
+ int family)
+{
+ if (!local_addr)
+ return -1;
+
+ *face = (face_t){
+ .type = FACE_TYPE_UDP,
+ .family = family,
+ .local_addr = *local_addr,
+ .local_port = local_port,
+ .remote_addr = remote_addr ? *remote_addr : IP_ADDRESS_EMPTY,
+ .remote_port = remote_port,
+ };
+
+ snprintf (face->netdevice.name, IFNAMSIZ, "%s", interface_name);
+
+ return 1;
+}
+
+int
+face_initialize_udp_sa (face_t *face, const char *interface_name,
+ const struct sockaddr *local_addr,
+ const struct sockaddr *remote_addr)
+{
+ if (!local_addr)
+ return -1;
+
+ if (remote_addr && (local_addr->sa_family != remote_addr->sa_family))
+ return -1;
+
+ switch (local_addr->sa_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *lsai = (struct sockaddr_in *) local_addr;
+ struct sockaddr_in *rsai = (struct sockaddr_in *) remote_addr;
+ *face = (face_t){
+ .type = FACE_TYPE_UDP,
+ .family = AF_INET,
+ .local_addr.v4.as_inaddr = lsai->sin_addr,
+ .local_port = lsai ? ntohs (lsai->sin_port) : 0,
+ .remote_addr = IP_ADDRESS_EMPTY,
+ .remote_port = rsai ? ntohs (rsai->sin_port) : 0,
+ };
+ if (rsai)
+ face->remote_addr.v4.as_inaddr = rsai->sin_addr;
+ }
+ break;
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *lsai = (struct sockaddr_in6 *) local_addr;
+ struct sockaddr_in6 *rsai = (struct sockaddr_in6 *) remote_addr;
+ *face = (face_t){
+ .type = FACE_TYPE_UDP,
+ .family = AF_INET6,
+ .local_addr.v6.as_in6addr = lsai->sin6_addr,
+ .local_port = lsai ? ntohs (lsai->sin6_port) : 0,
+ .remote_addr = IP_ADDRESS_EMPTY,
+ .remote_port = rsai ? ntohs (rsai->sin6_port) : 0,
+ };
+ if (rsai)
+ face->remote_addr.v6.as_in6addr = rsai->sin6_addr;
+ }
+ break;
+ default:
+ return -1;
+ }
+
+ snprintf (face->netdevice.name, IFNAMSIZ, "%s", interface_name);
+
+ return 1;
+}
+
+face_t *
+face_create ()
+{
+ face_t *face = calloc (1, sizeof (face_t)); /* 0'ed for hash */
+ return face;
+}
+
+face_t *
+face_create_udp (const char *interface_name,
+ const hicn_ip_address_t *local_addr, u16 local_port,
+ const hicn_ip_address_t *remote_addr, u16 remote_port,
+ int family)
+{
+ face_t *face = face_create ();
+ if (face_initialize_udp (face, interface_name, local_addr, local_port,
+ remote_addr, remote_port, family) < 0)
+ goto ERR_INIT;
+ return face;
+
+ERR_INIT:
+ free (face);
+ return NULL;
+}
+
+face_t *
+face_create_udp_sa (const char *interface_name,
+ const struct sockaddr *local_addr,
+ const struct sockaddr *remote_addr)
+{
+ face_t *face = face_create ();
+ if (face_initialize_udp_sa (face, interface_name, local_addr, remote_addr) <
+ 0)
+ goto ERR_INIT;
+ return face;
+
+ERR_INIT:
+ free (face);
+ return NULL;
+}
+
+void
+face_free (face_t *face)
+{
+ free (face);
+}
+
+/**
+ * \brief Compare two faces
+ * \param [in] f1 - First face
+ * \param [in] f2 - Second face
+ * \return whether faces are equal, ie both their types are parameters are
+ * equal.
+ *
+ * NOTE: this function implements a partial order.
+ */
+int
+face_cmp (const face_t *f1, const face_t *f2)
+{
+
+ int ret = f1->type - f2->type;
+ if (ret != 0)
+ return ret;
+
+ ret = f1->family - f2->family;
+ if (ret != 0)
+ return ret;
+
+ /*
+ * FIXME As hicn-light API might not return the netdevice, we can discard the
+ * comparison when one of the two is not set for now...
+ */
+ if ((f1->netdevice.index != 0) && (f2->netdevice.index != 0))
+ {
+ ret = netdevice_cmp (&f1->netdevice, &f2->netdevice);
+ if (ret != 0)
+ return ret;
+ }
+
+ switch (f1->type)
+ {
+ case FACE_TYPE_HICN:
+ ret = hicn_ip_address_cmp (&f1->local_addr, &f2->local_addr);
+ if (ret != 0)
+ return ret;
+
+ ret = hicn_ip_address_cmp (&f1->remote_addr, &f2->remote_addr);
+ if (ret != 0)
+ return ret;
+
+ break;
+
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ ret = hicn_ip_address_cmp (&f1->local_addr, &f2->local_addr);
+ if (ret != 0)
+ return ret;
+
+ ret = f1->local_port - f2->local_port;
+ if (ret != 0)
+ return ret;
+
+ ret = hicn_ip_address_cmp (&f1->remote_addr, &f2->remote_addr);
+ if (ret != 0)
+ return ret;
+
+ ret = f1->remote_port - f2->remote_port;
+ if (ret != 0)
+ return ret;
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* /!\ Please update constants in header file upon changes */
+size_t
+face_snprintf (char *s, size_t size, const face_t *face)
+{
+ char local[MAXSZ_IP_ADDRESS];
+ char remote[MAXSZ_IP_ADDRESS];
+ char tags[MAXSZ_POLICY_TAGS];
+
+ if (!hicn_ip_address_match_family (&face->local_addr, face->family))
+ return 0;
+ if (!hicn_ip_address_match_family (&face->remote_addr, face->family))
+ return 0;
+
+ hicn_ip_address_snprintf (local, MAXSZ_IP_ADDRESS, &face->local_addr);
+ hicn_ip_address_snprintf (remote, MAXSZ_IP_ADDRESS, &face->remote_addr);
+ policy_tags_snprintf (tags, MAXSZ_POLICY_TAGS, face->tags);
+
+ switch (face->type)
+ {
+ case FACE_TYPE_HICN:
+ {
+
+ return snprintf (s, size, "%s [%s -> %s] [%s]",
+ face_type_str (face->type), local, remote, tags);
+ }
+ case FACE_TYPE_UNDEFINED:
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ {
+ return snprintf (s, size, "%s [%s:%d -> %s:%d] [%s]",
+ face_type_str (face->type), local, face->local_port,
+ remote, face->remote_port, tags);
+ }
+ default:
+ return -1;
+ }
+}
+
+policy_tags_t
+face_get_tags (const face_t *face)
+{
+ return face->tags;
+}
+
+int
+face_set_tags (face_t *face, policy_tags_t tags)
+{
+ face->tags = tags;
+ return 1;
+}
+
+face_protocol_t
+get_protocol (face_type_t face_type)
+{
+ switch (face_type)
+ {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_HICN_LISTENER:
+ return FACE_PROTOCOL_HICN;
+
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_TCP_LISTENER:
+ return FACE_PROTOCOL_TCP;
+
+ case FACE_TYPE_UDP:
+ case FACE_TYPE_UDP_LISTENER:
+ return FACE_PROTOCOL_UDP;
+
+ case FACE_TYPE_UNDEFINED:
+ case FACE_TYPE_N:
+ break;
+ }
+ return FACE_PROTOCOL_UNKNOWN;
+}
diff --git a/lib/src/libhicn-config.cmake.in b/lib/src/libhicn-config.cmake.in
new file mode 100644
index 000000000..1ae219280
--- /dev/null
+++ b/lib/src/libhicn-config.cmake.in
@@ -0,0 +1,12 @@
+set(Libhicn_VERSION "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@")
+
+@PACKAGE_INIT@
+
+set(Libhicn_VERSION_MAJOR "@VERSION_MAJOR@")
+set(Libhicn_VERSION_MINOR "@VERSION_MINOR@")
+set(Libhicn_VERSION_PATCH "@VERSION_PATCH@")
+
+set_and_check(Libhicn_INCLUDE_DIRS "@PACKAGE_Libhicn_INCLUDE_DIRS@")
+include("${CMAKE_CURRENT_LIST_DIR}/libhicn-targets.cmake")
+
+check_required_components(Libhicn)
diff --git a/lib/src/mapme.c b/lib/src/mapme.c
index 3e7e8bc80..3f864e768 100644
--- a/lib/src/mapme.c
+++ b/lib/src/mapme.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -22,12 +22,48 @@
#include <hicn/common.h>
#include <hicn/error.h>
-#include <hicn/protocol/ipv4.h>
-#include <hicn/protocol/ipv6.h>
+#include "protocol/ipv4.h"
+#include "protocol/ipv6.h"
+#include "protocol/icmprd.h"
+
+/** @brief MAP-Me packet header for IPv4 */
+typedef struct
+{
+ _ipv4_header_t ip;
+ _icmprd4_header_t icmp_rd;
+ seq_t seq;
+ u8 len;
+ u8 _pad[3];
+} hicn_mapme_v4_header_t;
+
+/** @brief MAP-Me packet header for IPv6 */
+typedef struct
+{
+ _ipv6_header_t ip;
+ _icmprd_header_t icmp_rd;
+ seq_t seq;
+ u8 len;
+ u8 _pad[3];
+} hicn_mapme_v6_header_t;
+
+/** @brief MAP-Me packet header (IP version agnostic) */
+typedef union
+{
+ hicn_mapme_v4_header_t v4;
+ hicn_mapme_v6_header_t v6;
+} hicn_mapme_header_t;
+
+#define HICN_MAPME_V4_HDRLEN sizeof (hicn_mapme_v4_header_t)
+#define HICN_MAPME_V6_HDRLEN sizeof (hicn_mapme_v6_header_t)
+
+static_assert (EXPECTED_MAPME_V4_HDRLEN == HICN_MAPME_V4_HDRLEN,
+ "Size of MAPME_V4 struct does not match its expected size.");
+static_assert (EXPECTED_MAPME_V6_HDRLEN == HICN_MAPME_V6_HDRLEN,
+ "Size of MAPME_V6 struct does not match its expected size.");
size_t
-hicn_mapme_v4_create_packet (u8 * buf, const hicn_prefix_t * prefix,
- const mapme_params_t * params)
+hicn_mapme_v4_create_packet (u8 *buf, const hicn_prefix_t *prefix,
+ const mapme_params_t *params)
{
hicn_mapme_v4_header_t *mh = (hicn_mapme_v4_header_t *) buf;
/* *INDENT-OFF* */
@@ -41,14 +77,14 @@ hicn_mapme_v4_create_packet (u8 * buf, const hicn_prefix_t * prefix,
.ttl = HICN_MAPME_TTL,
.protocol = IPPROTO_ICMP,
.csum = 0,
- .saddr.as_u32 = 0,
- .daddr = prefix->name.ip4,
+ .saddr.as_u32 = IPV4_LOOPBACK.v4.as_u32,
+ .daddr = prefix->name.v4,
},
.icmp_rd = {
.type = ((params->type == UPDATE) || (params->type == NOTIFICATION)) ? HICN_MAPME_ICMP_TYPE_IPV4 : HICN_MAPME_ICMP_TYPE_ACK_IPV4,
.code = HICN_MAPME_ICMP_CODE,
.csum = 0,
- .ip = prefix->name.ip4,
+ .ip = prefix->name.v4,
},
.seq = htonl(params->seq),
.len = prefix->len,
@@ -59,15 +95,15 @@ hicn_mapme_v4_create_packet (u8 * buf, const hicn_prefix_t * prefix,
}
size_t
-hicn_mapme_v6_create_packet (u8 * buf, const hicn_prefix_t * prefix,
- const mapme_params_t * params)
+hicn_mapme_v6_create_packet (u8 *buf, const hicn_prefix_t *prefix,
+ const mapme_params_t *params)
{
hicn_mapme_v6_header_t *mh = (hicn_mapme_v6_header_t *) buf;
/* *INDENT-OFF* */
*mh = (hicn_mapme_v6_header_t) {
.ip = {
- .saddr = {{0}},
- .daddr = prefix->name.ip6,
+ .saddr = IPV6_LOOPBACK.v6,
+ .daddr = prefix->name.v6,
.version_class_flow = htonl(
(IPV6_DEFAULT_VERSION << 28) |
(IPV6_DEFAULT_TRAFFIC_CLASS << 20) |
@@ -81,8 +117,8 @@ hicn_mapme_v6_create_packet (u8 * buf, const hicn_prefix_t * prefix,
.code = HICN_MAPME_ICMP_CODE,
.csum = 0,
.res = 0,
- .tgt = prefix->name.ip6,
- .dst = prefix->name.ip6,
+ .tgt = prefix->name.v6,
+ .dst = prefix->name.v6,
},
.seq = htonl(params->seq),
.len = prefix->len,
@@ -92,20 +128,20 @@ hicn_mapme_v6_create_packet (u8 * buf, const hicn_prefix_t * prefix,
}
size_t
-hicn_mapme_create_packet (u8 * buf, const hicn_prefix_t * prefix,
- const mapme_params_t * params)
+hicn_mapme_create_packet (u8 *buf, const hicn_prefix_t *prefix,
+ const mapme_params_t *params)
{
/* We currently ignore subsequent protocol definitions */
- if (PREDICT_TRUE (params->protocol == IPPROTO_IPV6))
+ if (HICN_EXPECT_TRUE (params->protocol == IPPROTO_IPV6))
return hicn_mapme_v6_create_packet (buf, prefix, params);
else
return hicn_mapme_v4_create_packet (buf, prefix, params);
}
size_t
-hicn_mapme_v4_create_ack (u8 * buf, const mapme_params_t * params)
+hicn_mapme_v4_create_ack (u8 *buf, const mapme_params_t *params)
{
- ip4_address_t tmp; // tmp storage for swapping IP addresses for ACK
+ ipv4_address_t tmp; // tmp storage for swapping IP addresses for ACK
hicn_mapme_v4_header_t *mh = (hicn_mapme_v4_header_t *) buf;
tmp = mh->ip.daddr;
@@ -119,9 +155,9 @@ hicn_mapme_v4_create_ack (u8 * buf, const mapme_params_t * params)
}
size_t
-hicn_mapme_v6_create_ack (u8 * buf, const mapme_params_t * params)
+hicn_mapme_v6_create_ack (u8 *buf, const mapme_params_t *params)
{
- ip6_address_t tmp; // tmp storage for swapping IP addresses for ACK
+ ipv6_address_t tmp; // tmp storage for swapping IP addresses for ACK
hicn_mapme_v6_header_t *mh = (hicn_mapme_v6_header_t *) buf;
tmp = mh->ip.daddr;
@@ -135,32 +171,33 @@ hicn_mapme_v6_create_ack (u8 * buf, const mapme_params_t * params)
}
size_t
-hicn_mapme_create_ack (u8 * buf, const mapme_params_t * params)
+hicn_mapme_create_ack (u8 *buf, const mapme_params_t *params)
{
/* We currently ignore subsequent protocol definitions */
- if (PREDICT_TRUE (params->protocol == IPPROTO_IPV6))
+ if (HICN_EXPECT_TRUE (params->protocol == IPPROTO_IPV6))
return hicn_mapme_v6_create_ack (buf, params);
else
return hicn_mapme_v4_create_ack (buf, params);
}
int
-hicn_mapme_v4_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
- mapme_params_t * params)
+hicn_mapme_v4_parse_packet (const u8 *packet, hicn_prefix_t *prefix,
+ mapme_params_t *params)
{
hicn_mapme_v4_header_t *mh = (hicn_mapme_v4_header_t *) packet;
/* *INDENT-OFF* */
*prefix = (hicn_prefix_t) {
.name = {
- .ip4 = HICN_MAPME_TYPE_IS_IU (mh->icmp_rd.type) ? mh->ip.daddr : mh->ip.saddr,
+ .v4 = HICN_MAPME_TYPE_IS_IU (mh->icmp_rd.type) ? mh->ip.daddr : mh->ip.saddr,
},
.len = mh->len,
};
- *params = (mapme_params_t) {
+ *params = (mapme_params_t){
.protocol = IPPROTO_IP,
- .type = (mh->icmp_rd.type == HICN_MAPME_ICMP_TYPE_IPV4) ? UPDATE : UPDATE_ACK,
+ .type =
+ (mh->icmp_rd.type == HICN_MAPME_ICMP_TYPE_IPV4) ? UPDATE : UPDATE_ACK,
.seq = ntohl (mh->seq),
};
/* *INDENT-ON* */
@@ -169,22 +206,23 @@ hicn_mapme_v4_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
}
int
-hicn_mapme_v6_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
- mapme_params_t * params)
+hicn_mapme_v6_parse_packet (const u8 *packet, hicn_prefix_t *prefix,
+ mapme_params_t *params)
{
hicn_mapme_v6_header_t *mh = (hicn_mapme_v6_header_t *) packet;
/* *INDENT-OFF* */
*prefix = (hicn_prefix_t) {
.name = {
- .ip6 = HICN_MAPME_TYPE_IS_IU (mh->icmp_rd.type) ? mh->ip.daddr : mh->ip.saddr,
+ .v6 = HICN_MAPME_TYPE_IS_IU (mh->icmp_rd.type) ? mh->ip.daddr : mh->ip.saddr,
},
.len = mh->len,
};
- *params = (mapme_params_t) {
+ *params = (mapme_params_t){
.protocol = IPPROTO_IPV6,
- .type = (mh->icmp_rd.type == HICN_MAPME_ICMP_TYPE_IPV6) ? UPDATE : UPDATE_ACK,
+ .type =
+ (mh->icmp_rd.type == HICN_MAPME_ICMP_TYPE_IPV6) ? UPDATE : UPDATE_ACK,
.seq = ntohl (mh->seq),
};
/* *INDENT-ON* */
@@ -193,8 +231,8 @@ hicn_mapme_v6_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
}
int
-hicn_mapme_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
- mapme_params_t * params)
+hicn_mapme_parse_packet (const u8 *packet, hicn_prefix_t *prefix,
+ mapme_params_t *params)
{
switch (HICN_IP_VERSION (packet))
{
@@ -203,8 +241,9 @@ hicn_mapme_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
case 6:
return hicn_mapme_v6_parse_packet (packet, prefix, params);
default:
- return HICN_LIB_ERROR_UNEXPECTED;
+ break;
}
+ return HICN_LIB_ERROR_UNEXPECTED;
}
/*
diff --git a/lib/src/name.c b/lib/src/name.c
index 54b2a76aa..f363eea90 100644
--- a/lib/src/name.c
+++ b/lib/src/name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -19,533 +19,470 @@
*/
#ifndef _WIN32
-#include <arpa/inet.h> // inet_ptin
+#include <arpa/inet.h> // inet_ptin
#endif
#include <errno.h>
#include <stdio.h>
-#include <stdlib.h> // strtoul
-#include <string.h> // memcpy
+#include <stdlib.h> // strtoul
+#include <string.h> // memcpy
#include <hicn/common.h>
#include <hicn/error.h>
#include <hicn/name.h>
+#include <hicn/util/sstrncpy.h>
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#if ! HICN_VPP_PLUGIN
int
-hicn_name_create (const char *ip_address, u32 id, hicn_name_t * name)
+hicn_name_create (const char *ip_address, u32 id, hicn_name_t *name)
{
int af, rc;
- af = get_addr_family (ip_address);
-
- switch (af)
- {
- case AF_INET:
- if (name->type == HNT_UNSPEC)
- {
- name->type = HNT_CONTIGUOUS_V4;
- }
- name->len = IPV4_ADDR_LEN;
- break;
- case AF_INET6:
- if (name->type == HNT_UNSPEC)
- {
- name->type = HNT_CONTIGUOUS_V6;
- }
- name->len = IPV6_ADDR_LEN;
- break;
- default:
- return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
- }
+ memset (name, 0, sizeof (hicn_name_t));
- if ((name->type != HNT_CONTIGUOUS_V4) && (name->type != HNT_CONTIGUOUS_V6))
- {
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
+ af = get_addr_family (ip_address);
+ int v4 = (af == AF_INET);
+ u8 *dst = (u8 *) (v4 * (intptr_t) (name->prefix.v4.as_u8) +
+ (1 - v4) * (intptr_t) (name->prefix.v6.as_u8));
+ rc = inet_pton (af, ip_address, dst);
- rc = inet_pton (af, ip_address, name->buffer);
- if (rc <= 0)
+ if (rc != 1)
{
return HICN_LIB_ERROR_UNKNOWN_ADDRESS;
}
- *(u32 *) (name->buffer + name->len) = id;
+
+ name->suffix = id;
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_create_from_ip_prefix (const ip_prefix_t * prefix, u32 id,
- hicn_name_t * name)
+hicn_name_create_from_ip_address (const hicn_ip_address_t ip_address,
+ u32 suffix, hicn_name_t *name)
{
- switch (prefix->family)
- {
- case AF_INET:
- name->type = HNT_CONTIGUOUS_V4;
- memcpy (name->buffer, prefix->address.v4.buffer,
- ip_address_len(prefix->family));
- name->len = IPV4_ADDR_LEN;
- break;
- case AF_INET6:
- name->type = HNT_CONTIGUOUS_V6;
- memcpy (name->buffer, prefix->address.v6.buffer,
- ip_address_len(prefix->family));
- name->len = IPV6_ADDR_LEN;
- break;
- default:
- return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
- }
-
- *(u32 *) (name->buffer + name->len) = id;
+ name->prefix = ip_address;
+ name->suffix = suffix;
return HICN_LIB_ERROR_NONE;
}
-u8
-hicn_name_get_length (const hicn_name_t * name)
+int
+hicn_name_create_from_ip_prefix (const hicn_ip_prefix_t *prefix, u32 id,
+ hicn_name_t *name)
{
- return name->len;
+ name->prefix = prefix->address;
+ name->suffix = id;
+
+ return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_compare (const hicn_name_t * name_1, const hicn_name_t * name_2,
- bool consider_segment)
+hicn_name_compare (const hicn_name_t *name_1, const hicn_name_t *name_2,
+ bool consider_segment)
{
- hicn_name_t *name1 = (hicn_name_t *) name_1;
- hicn_name_t *name2 = (hicn_name_t *) name_2;
+ int ret;
+ ret = memcmp (&name_1->prefix.v6.buffer, &name_2->prefix.v6.buffer,
+ sizeof (name_1->prefix.v6));
- if ((name1->type == HNT_CONTIGUOUS_V4 && name2->type == HNT_CONTIGUOUS_V6)
- || (name1->type == HNT_CONTIGUOUS_V6
- && name2->type == HNT_CONTIGUOUS_V4))
- {
- return -1;
- }
+ if (consider_segment)
+ ret |= !(name_1->suffix == name_2->suffix);
- if ((name1->type == HNT_IOV_V4 && name2->type == HNT_IOV_V6) ||
- (name1->type == HNT_IOV_V6 && name2->type == HNT_IOV_V4))
- {
- return -1;
- }
+ return ret;
+}
- if ((name1->type == HNT_IOV_V4 && name2->type == HNT_CONTIGUOUS_V6) ||
- (name1->type == HNT_IOV_V6 && name2->type == HNT_CONTIGUOUS_V4))
- {
- return -1;
- }
+uint32_t
+_hicn_name_get_hash (const hicn_name_t *name, bool consider_suffix)
+{
+ uint32_t hash = hash32 (&name->prefix, sizeof (name->prefix));
- if (name1->type == HNT_UNSPEC || name2->type == HNT_UNSPEC)
- {
- return -1;
- }
+ if (consider_suffix)
+ hash = cumulative_hash32 (&name->suffix, sizeof (name->suffix), hash);
- size_t len1 = 0, len2 = 0;
+ return hash;
+}
- u8 *buffer11, *buffer12, *buffer21, *buffer22;
+int
+hicn_name_empty (hicn_name_t *name)
+{
+ return _is_unspec (name);
+}
- switch (name1->type)
- {
- case HNT_CONTIGUOUS_V4:
- buffer11 = name1->buffer;
- buffer12 = name1->buffer + IPV4_ADDR_LEN;
- len1 = IPV4_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V6:
- buffer11 = name1->buffer;
- buffer12 = name1->buffer + IPV6_ADDR_LEN;
- len1 = IPV6_ADDR_LEN;
- break;
- case HNT_IOV_V4:
- buffer11 = name1->iov.buffers[0].iov_base;
- buffer12 = name1->iov.buffers[1].iov_base;
- len1 = IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- buffer11 = name1->iov.buffers[0].iov_base;
- buffer12 = name1->iov.buffers[1].iov_base;
- len1 = IPV6_ADDR_LEN;
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
+int
+hicn_name_copy (hicn_name_t *dst, const hicn_name_t *src)
+{
+ *dst = *src;
+ return HICN_LIB_ERROR_NONE;
+}
- switch (name2->type)
- {
- case HNT_CONTIGUOUS_V4:
- buffer21 = name2->buffer;
- buffer22 = name2->buffer + IPV4_ADDR_LEN;
- len2 = IPV4_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V6:
- buffer21 = name2->buffer;
- buffer22 = name2->buffer + IPV6_ADDR_LEN;
- len2 = IPV6_ADDR_LEN;
- break;
- case HNT_IOV_V4:
- buffer21 = name2->iov.buffers[0].iov_base;
- buffer22 = name2->iov.buffers[1].iov_base;
- len2 = IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- buffer21 = name2->iov.buffers[0].iov_base;
- buffer22 = name2->iov.buffers[1].iov_base;
- len2 = IPV6_ADDR_LEN;
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
+int
+hicn_name_copy_prefix_to_destination (u8 *dst, const hicn_name_t *name)
+{
+ int v4 = _is_inet4 (name);
+ const u8 *src = (u8 *) (v4 * (intptr_t) (name->prefix.v4.as_u8) +
+ (1 - v4) * (intptr_t) (name->prefix.v6.as_u8));
+ size_t size = v4 * IPV4_ADDR_LEN + (1 - v4) * IPV6_ADDR_LEN;
+ memcpy (dst, src, size);
- // Sanity check
- if (len1 != len2)
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+ return HICN_LIB_ERROR_NONE;
+}
- int ret1 = memcmp ((u8 *) buffer11, (u8 *) buffer21, len1);
+int
+hicn_name_set_suffix (hicn_name_t *name, hicn_name_suffix_t suffix)
+{
+ name->suffix = suffix;
+ return HICN_LIB_ERROR_NONE;
+}
- if (!consider_segment)
+int
+hicn_name_to_sockaddr_address (const hicn_name_t *name,
+ struct sockaddr *ip_address)
+{
+ struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) ip_address;
+ struct sockaddr_in *tmp4 = (struct sockaddr_in *) ip_address;
+
+ assert (!_is_unspec (name));
+
+ if (_is_inet4 (name))
+ {
+ tmp4->sin_family = AF_INET;
+ tmp4->sin_port = DUMMY_PORT;
+ memcpy (&tmp4->sin_addr, &name->prefix.v4, IPV4_ADDR_LEN);
+ }
+ else
{
- return ret1;
+ tmp6->sin6_family = AF_INET6;
+ tmp6->sin6_scope_id = 0;
+ tmp6->sin6_port = DUMMY_PORT;
+ memcpy (&tmp6->sin6_addr, &name->prefix.v6, IPV6_ADDR_LEN);
}
- int ret2 = memcmp ((u8 *) buffer12, (u8 *) buffer22, HICN_SEGMENT_LEN);
-
- return ret1 || ret2;
+ return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_hash (const hicn_name_t * name, u32 * hash, bool consider_suffix)
+hicn_name_to_hicn_ip_prefix (const hicn_name_t *name, hicn_ip_prefix_t *prefix)
{
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V4:
- *hash = hash32 (name->buffer, consider_suffix ? HICN_V4_NAME_LEN : HICN_V4_PREFIX_LEN);
- break;
- case HNT_CONTIGUOUS_V6:
- *hash = hash32 (name->buffer, consider_suffix ? HICN_V6_NAME_LEN : HICN_V6_PREFIX_LEN);
- break;
- case HNT_IOV_V4:
- case HNT_IOV_V6:
- *hash =
- hash32 (name->iov.buffers[0].iov_base, name->iov.buffers[0].iov_len);
- if (consider_suffix)
- {
- *hash = cumulative_hash32 (name->iov.buffers[1].iov_base,
- name->iov.buffers[1].iov_len, *hash);
- }
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
-
+ int family, rc;
+ rc = hicn_name_get_family (name, &family);
+ if (rc)
+ return rc;
+
+ prefix->family = family;
+ prefix->address.v6.as_u64[0] = name->prefix.v6.as_u64[0];
+ prefix->address.v6.as_u64[1] = name->prefix.v6.as_u64[1];
+ prefix->len = 128;
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_empty (hicn_name_t * name)
+hicn_name_get_seq_number (const hicn_name_t *name, u32 *seq_number)
{
- return name->type == HNT_UNSPEC ? 1 : 0;
+ *seq_number = name->suffix;
+ return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_copy (hicn_name_t * dst, const hicn_name_t * src)
+hicn_name_ntop (const hicn_name_t *src, char *dst, size_t len)
{
- switch (src->type)
+ int offset;
+ const char *rc = NULL;
+ int v4 = _is_inet4 (src);
+ const u8 *addr = (u8 *) (v4 * (intptr_t) src->prefix.v4.as_u8 +
+ (1 - v4) * (intptr_t) src->prefix.v6.as_u8);
+ int family = v4 * AF_INET + (1 - v4) * AF_INET6;
+ rc = inet_ntop (family, addr, dst, (socklen_t) len);
+
+ if (!rc)
{
- case HNT_CONTIGUOUS_V4:
- case HNT_CONTIGUOUS_V6:
- *dst = *src;
- break;
- case HNT_IOV_V4:
- case HNT_IOV_V6:
- dst->type =
- src->type == HNT_IOV_V4 ? HNT_CONTIGUOUS_V4 : HNT_CONTIGUOUS_V6;
- memcpy (dst->buffer, src->iov.buffers[0].iov_base,
- src->iov.buffers[0].iov_len);
- memcpy (dst->buffer + src->iov.buffers[0].iov_len,
- src->iov.buffers[1].iov_base, src->iov.buffers[1].iov_len);
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ return HICN_LIB_ERROR_UNSPECIFIED;
}
+ offset = (int) strnlen_s (dst, len);
+ dst[offset] = '|';
+
+ snprintf (dst + offset + 1, len - offset - 1, "%lu",
+ (unsigned long) (src->suffix));
+
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_copy_to_destination (u8 * dst, const hicn_name_t * src,
- bool copy_suffix)
+hicn_name_pton (const char *src, hicn_name_t *dst)
{
- size_t length;
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+}
- switch (src->type)
- {
- case HNT_CONTIGUOUS_V4:
- if (copy_suffix)
- {
- length = HICN_V4_NAME_LEN;
- }
- else
- {
- length = IPV4_ADDR_LEN;
- }
- memcpy (dst, src->buffer, length);
- break;
- case HNT_CONTIGUOUS_V6:
- if (copy_suffix)
- {
- length = HICN_V6_NAME_LEN;
- }
- else
- {
- length = IPV6_ADDR_LEN;
- }
- memcpy (dst, src->buffer, length);
- break;
- case HNT_IOV_V4:
- case HNT_IOV_V6:
- memcpy (dst, src->iov.buffers[0].iov_base, src->iov.buffers[0].iov_len);
- if (copy_suffix)
- {
- memcpy (dst + src->iov.buffers[0].iov_len,
- src->iov.buffers[1].iov_base, src->iov.buffers[1].iov_len);
- }
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
+int
+hicn_name_get_family (const hicn_name_t *name, int *family)
+{
+ assert (!_is_unspec (name));
+ int v4 = _is_inet4 (name);
+ *family = v4 * AF_INET + (1 - v4) * AF_INET6;
return HICN_LIB_ERROR_NONE;
}
+bool
+hicn_name_is_v4 (const hicn_name_t *name)
+{
+ return _is_inet4 (name);
+}
+
int
-hicn_name_set_seq_number (hicn_name_t * name, u32 seq_number)
+hicn_name_snprintf (char *s, size_t size, const hicn_name_t *name)
{
- u8 *sequence_number = NULL;
+ int n, rc;
+ n = hicn_ip_address_snprintf (s, size, &name->prefix);
+ if (n < 0 || n >= size)
+ return n;
+ rc = snprintf (s + n, size - n, "|%d", name->suffix);
+ if (rc < 0)
+ return rc;
+ return rc + n;
+}
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V6:
- sequence_number = name->buffer + IPV6_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V4:
- sequence_number = name->buffer + IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- case HNT_IOV_V4:
- sequence_number = name->iov.buffers[1].iov_base;
- break;
- case HNT_UNSPEC:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+int
+hicn_name_no_suffix_snprintf (char *s, size_t size, const hicn_name_t *name)
+{
+ return hicn_ip_address_snprintf (s, size, &name->prefix);
+}
- if (sequence_number)
- {
- *(u32 *) sequence_number = seq_number;
- }
- else
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+int
+hicn_prefix_create_from_ip_prefix (const hicn_ip_prefix_t *hicn_ip_prefix,
+ hicn_prefix_t *prefix)
+{
+ if (hicn_ip_prefix->family != AF_INET && hicn_ip_prefix->family != AF_INET6)
+ return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
+ prefix->name = hicn_ip_prefix->address;
+ prefix->len = (u8) (hicn_ip_prefix->len);
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_to_sockaddr_address (const hicn_name_t * name,
- struct sockaddr *ip_address)
+hicn_name_cmp (const hicn_name_t *n1, const hicn_name_t *n2)
{
- struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) ip_address;
- struct sockaddr_in *tmp4 = (struct sockaddr_in *) ip_address;
-
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V6:
- tmp6->sin6_family = AF_INET6;
- tmp6->sin6_scope_id = 0;
- tmp6->sin6_port = DUMMY_PORT;
- memcpy (&tmp6->sin6_addr, name->buffer, IPV6_ADDR_LEN);
- break;
- case HNT_IOV_V6:
- tmp6->sin6_family = AF_INET6;
- tmp6->sin6_scope_id = 0;
- tmp6->sin6_port = DUMMY_PORT;
- memcpy (&tmp6->sin6_addr, name->iov.buffers[0].iov_base,
- name->iov.buffers[0].iov_len);
- break;
- case HNT_CONTIGUOUS_V4:
- tmp4->sin_family = AF_INET;
- tmp4->sin_port = DUMMY_PORT;
- memcpy (&tmp4->sin_addr, name->buffer, IPV4_ADDR_LEN);
- break;
- case HNT_IOV_V4:
- tmp4->sin_family = AF_INET;
- tmp4->sin_port = DUMMY_PORT;
- memcpy (&tmp4->sin_addr, name->iov.buffers[0].iov_base,
- name->iov.buffers[0].iov_len);
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+ int rc = hicn_ip_address_cmp (&n1->prefix, &n2->prefix);
+ if (rc != 0)
+ return rc;
+ return n2->suffix - n1->suffix;
+}
- return HICN_LIB_ERROR_NONE;
+bool
+hicn_name_equals (const hicn_name_t *n1, const hicn_name_t *n2)
+{
+ return (hicn_name_cmp (n1, n2) == 0);
}
int
-hicn_name_to_ip_prefix (const hicn_name_t * name, ip_prefix_t * prefix)
+hicn_prefix_create_from_ip_address_len (const hicn_ip_address_t *ip_address,
+ uint8_t len, hicn_prefix_t *prefix)
{
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V6:
- memcpy (&prefix->address.v6.buffer, name->buffer, IPV6_ADDR_LEN);
- prefix->family = AF_INET6;
- break;
- case HNT_IOV_V6:
- memcpy (&prefix->address.v6.buffer, name->iov.buffers[0].iov_base,
- name->iov.buffers[0].iov_len);
- prefix->family = AF_INET6;
- break;
- case HNT_CONTIGUOUS_V4:
- memcpy (&prefix->address.v4.buffer, name->buffer, IPV4_ADDR_LEN);
- prefix->family = AF_INET;
- break;
- case HNT_IOV_V4:
- memcpy (&prefix->address.v4.buffer, name->iov.buffers[0].iov_base,
- name->iov.buffers[0].iov_len);
- prefix->family = AF_INET;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+ prefix->name = *ip_address;
+ prefix->len = len;
return HICN_LIB_ERROR_NONE;
}
+hicn_prefix_t *
+hicn_prefix_dup (const hicn_prefix_t *prefix)
+{
+ hicn_prefix_t *copy = malloc (sizeof (hicn_prefix_t));
+ if (!copy)
+ goto ERR_MALLOC;
+ if (hicn_prefix_copy (copy, prefix) < 0)
+ goto ERR_COPY;
+ return copy;
+
+ERR_COPY:
+ free (copy);
+ERR_MALLOC:
+ return NULL;
+}
+
int
-hicn_name_get_seq_number (const hicn_name_t * name, u32 * seq_number)
+hicn_prefix_copy (hicn_prefix_t *dst, const hicn_prefix_t *src)
{
- const u8 *sequence_number = NULL;
+ dst->name = src->name;
+ dst->len = src->len;
+ return 0;
+}
- switch (name->type)
+bool
+hicn_prefix_is_v4 (const hicn_prefix_t *prefix)
+{
+ return hicn_ip_address_is_v4 (&prefix->name);
+}
+
+/*
+ * The ip address is in network byte order (big endian, msb last) in
+ * hicn_{prefix,name}_t, as in ip_address_t which builds upon struct in*_addr,
+ * But the bits are in host order... so we cannot use builtin functions to get
+ * the position of the first 1 unless we swap bytes as was done previously,
+ * which is costly and non-essential.
+ *
+ *
+ * Example:
+ *
+ * bits | 127 .. 120 | ... | 8 9 10 11 12 13 14 15 | 0 .. 7 |
+ * diff | | ... | 1 0 1 0 0 0 0 0 | |
+ * ^
+ * bit of interest ----------------+
+ */
+
+uint64_t
+_log2_nbo (uint64_t val)
+{
+ assert (val != 0); /* There is at least 1 bit set (network byte order) */
+
+ uint64_t result = 0;
+
+ /* Search for the first 1, starting from left */
+
+ /* The first 32 bits of val are 0 */
+ if (!(val & 0x00000000FFFFFFFF))
{
- case HNT_CONTIGUOUS_V6:
- sequence_number = name->buffer + IPV6_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V4:
- sequence_number = name->buffer + IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- case HNT_IOV_V4:
- sequence_number = name->iov.buffers[1].iov_base;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
+ val = val >> 32;
+ result = result | 32;
}
- if (sequence_number)
+ if (!(val & 0x0000FFFF))
{
- *seq_number = *(u32 *) sequence_number;
+ val = val >> 16;
+ result = result | 16;
}
- else
+
+ if (!(val & 0x00FF))
{
- return HICN_LIB_ERROR_UNEXPECTED;
+ val = val >> 8;
+ result = result | 8;
}
- return HICN_LIB_ERROR_NONE;
+ /* Val now contains the byte with at last 1 bit set (host bit order) */
+ if (val & 0xF0)
+ val = val >> 4;
+ else
+ result = result | 4;
+
+ if (val & 0xC)
+ val = val >> 2;
+ else
+ result = result | 2;
+
+ if (val & 0x2)
+ val = val >> 1;
+ else
+ result = result | 1;
+
+ return result;
}
-int
-hicn_name_ntop (const hicn_name_t * src, char *dst, size_t len)
+uint32_t
+hicn_prefix_lpm (const hicn_prefix_t *p1, const hicn_prefix_t *p2)
{
- int offset;
- const char *rc;
- void *seg_number = NULL;
-
- switch (src->type)
+ uint32_t prefix_len = 0;
+ /* Test each block of 64 bits as a whole */
+ for (unsigned i = 0; i < 2; i++)
{
- case HNT_CONTIGUOUS_V6:
- rc = inet_ntop (AF_INET6, src->buffer, dst, (socklen_t)len);
- seg_number = (u8 *) src->buffer + IPV6_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V4:
- rc = inet_ntop (AF_INET, src->buffer, dst, (socklen_t)len);
- seg_number = (u8 *) src->buffer + IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- rc = inet_ntop (AF_INET6, src->iov.buffers[0].iov_base, dst, (socklen_t)len);
- seg_number = src->iov.buffers[1].iov_base;
- break;
- case HNT_IOV_V4:
- rc = inet_ntop (AF_INET, src->iov.buffers[0].iov_base, dst, (socklen_t)len);
- seg_number = src->iov.buffers[1].iov_base;
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
- if (!rc)
- {
- goto ERR;
+ /* Check for differences in the two u64 */
+ uint64_t diff = p1->name.v6.as_u64[i] ^ p2->name.v6.as_u64[i];
+ if (diff)
+ {
+ /*
+ * As the ip_address_t mimics in*_addr and has network byte order
+ * (and host bit order, we cannot directly use 64-bit operations:
+ */
+ prefix_len += _log2_nbo (diff);
+ break;
+ }
+ prefix_len += 8 * sizeof (uint64_t);
}
- offset = (int) strlen (dst);
- dst[offset] = '|';
-
- sprintf (dst + offset + 1, "%lu", (unsigned long) (*(u32 *) seg_number));
-
- return HICN_LIB_ERROR_NONE;
+ /* Bound the returned prefix length by the length of all input */
+ return MIN (prefix_len,
+ MIN (hicn_prefix_get_len (p1), hicn_prefix_get_len (p2)));
+}
-ERR:
- return HICN_LIB_ERROR_UNSPECIFIED;
+void
+hicn_prefix_clear (hicn_prefix_t *prefix, uint8_t start_from)
+{
+ uint8_t *buffer = prefix->name.v6.as_u8;
+
+ /* Compute the offset of the byte from which to clear the name... */
+ uint8_t offset = start_from / 8;
+ if (hicn_prefix_is_v4 (prefix))
+ offset += IP_ADDRESS_V4_OFFSET_LEN; /* Ignore padding */
+ /* ... and the position of the first bit to clear */
+ uint8_t pos = start_from % 8;
+
+ /* Mask to clear specific bits at offset...
+ * pos 7 6 5 4 3 2 1 0 (eg. start_from = 19, pos = 3)
+ * mask 0 0 0 0 0 1 1 1 (= 1<<pos - 1)
+ * */
+ uint8_t mask = 0xFF ^ ((1 << (8 - pos)) - 1);
+ buffer[offset] &= mask;
+
+ /* ... then fully clear remaining bytes */
+ for (uint8_t i = offset + 1; i < HICN_PREFIX_MAX_LEN; i++)
+ buffer[i] = 0;
}
-int
-hicn_name_pton (const char *src, hicn_name_t * dst)
+void
+hicn_prefix_truncate (hicn_prefix_t *prefix, uint8_t len)
{
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ hicn_prefix_clear (prefix, len);
+ prefix->len = len;
}
int
-hicn_name_get_family (const hicn_name_t * name, int *family)
+hicn_prefix_cmp (const hicn_prefix_t *p1, const hicn_prefix_t *p2)
{
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V6:
- case HNT_IOV_V6:
- *family = AF_INET6;
- break;
- case HNT_CONTIGUOUS_V4:
- case HNT_IOV_V4:
- *family = AF_INET;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+ if (p1->len != p2->len)
+ return p2->len - p1->len;
+ return hicn_ip_address_cmp (&p1->name, &p2->name);
+}
- return HICN_LIB_ERROR_NONE;
+bool
+hicn_prefix_equals (const hicn_prefix_t *p1, const hicn_prefix_t *p2)
+{
+ return hicn_prefix_cmp (p1, p2) == 0;
}
int
-hicn_prefix_create_from_ip_prefix (const ip_prefix_t * ip_prefix,
- hicn_prefix_t * prefix)
+hicn_prefix_snprintf (char *s, size_t size, const hicn_prefix_t *prefix)
{
- switch (ip_prefix->family)
- {
- case AF_INET:
- prefix->name.ip4.as_u32 = ip_prefix->address.v4.as_u32;
- break;
- case AF_INET6:
- prefix->name.ip6.as_u64[0] = ip_prefix->address.v6.as_u64[0];
- prefix->name.ip6.as_u64[1] = ip_prefix->address.v6.as_u64[1];
- break;
- default:
- return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
- }
- prefix->len = (u8) (ip_prefix->len);
+ hicn_ip_prefix_t ip_prefix = { .family =
+ hicn_ip_address_get_family (&prefix->name),
+ .address = prefix->name,
+ .len = prefix->len };
+ return hicn_ip_prefix_snprintf (s, size, &ip_prefix);
+}
- return HICN_LIB_ERROR_NONE;
+uint8_t
+_hicn_prefix_get_bit (const hicn_prefix_t *prefix, uint8_t pos)
+{
+ const hicn_ip_address_t *address = hicn_prefix_get_ip_address (prefix);
+ return hicn_ip_address_get_bit (address, pos);
}
-#endif /* ! HICN_VPP_PLUGIN */
+uint8_t
+hicn_prefix_get_bit (const hicn_prefix_t *prefix, uint8_t pos)
+{
+ assert (pos <= hicn_prefix_get_len (prefix));
+ return _hicn_prefix_get_bit (prefix, pos);
+}
+int
+hicn_prefix_get_ip_prefix (const hicn_prefix_t *prefix,
+ hicn_ip_prefix_t *ip_prefix)
+{
+ *ip_prefix =
+ (hicn_ip_prefix_t){ .family = hicn_ip_address_get_family (&prefix->name),
+ .address = prefix->name,
+ .len = prefix->len };
+ return HICN_LIB_ERROR_NONE;
+}
/*
* fd.io coding-style-patch-verification: ON
diff --git a/lib/src/ops.c b/lib/src/ops.c
index ef12e9bf0..2c38b5374 100644
--- a/lib/src/ops.c
+++ b/lib/src/ops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -22,25 +22,35 @@
#include <netinet/in.h>
#endif
#include <stdlib.h>
-#include <hicn/ops.h>
-#include <hicn/header.h>
+
+#include "ops.h"
+#include "protocol.h"
extern const hicn_ops_t hicn_ops_ipv4;
extern const hicn_ops_t hicn_ops_icmp;
+extern const hicn_ops_t hicn_ops_udp;
extern const hicn_ops_t hicn_ops_tcp;
extern const hicn_ops_t hicn_ops_ipv6;
+extern const hicn_ops_t hicn_ops_new;
extern const hicn_ops_t hicn_ops_ah;
/* Declare empty operations (terminates recursion on protocol layers) */
-DECLARE_init_packet_header (none, NONE);
+
+int
+none_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos)
+{
+ pkbuf->payload = pkbuf->len;
+ return HICN_LIB_ERROR_NONE;
+}
+
DECLARE_get_interest_locator (none, NONE);
DECLARE_set_interest_locator (none, NONE);
DECLARE_get_interest_name (none, NONE);
DECLARE_set_interest_name (none, NONE);
DECLARE_get_interest_name_suffix (none, NONE);
DECLARE_set_interest_name_suffix (none, NONE);
-DECLARE_mark_packet_as_interest (none, NONE);
-DECLARE_mark_packet_as_data (none, NONE);
+DECLARE_get_type (none, NONE);
+DECLARE_set_type (none, NONE);
DECLARE_reset_interest_for_hash (none, NONE);
DECLARE_get_data_locator (none, NONE);
DECLARE_set_data_locator (none, NONE);
@@ -48,21 +58,20 @@ DECLARE_get_data_name (none, NONE);
DECLARE_set_data_name (none, NONE);
DECLARE_get_data_name_suffix (none, NONE);
DECLARE_set_data_name_suffix (none, NONE);
-DECLARE_get_data_pathlabel (none, NONE);
-DECLARE_set_data_pathlabel (none, NONE);
-DECLARE_update_data_pathlabel (none, NONE);
+DECLARE_get_data_path_label (none, NONE);
+DECLARE_set_data_path_label (none, NONE);
+DECLARE_update_data_path_label (none, NONE);
DECLARE_reset_data_for_hash (none, NONE);
DECLARE_get_lifetime (none, NONE);
DECLARE_set_lifetime (none, NONE);
DECLARE_update_checksums (none, NONE);
+DECLARE_update_checksums_incremental (none, NONE);
DECLARE_verify_checksums (none, NONE);
DECLARE_rewrite_interest (none, NONE);
DECLARE_rewrite_data (none, NONE);
-DECLARE_get_length (none, NONE);
-DECLARE_get_header_length (none, NONE);
-DECLARE_get_current_header_length (none, NONE);
-DECLARE_get_payload_length (none, NONE);
-DECLARE_set_payload_length (none, NONE);
+DECLARE_set_payload_len (none, NONE);
+DECLARE_get_payload_type (none, NONE);
+DECLARE_set_payload_type (none, NONE);
DECLARE_get_signature_size (none, NONE);
DECLARE_set_signature_size (none, NONE);
DECLARE_set_signature_timestamp (none, NONE);
@@ -72,9 +81,12 @@ DECLARE_get_validation_algorithm (none, NONE);
DECLARE_set_key_id (none, NONE);
DECLARE_get_key_id (none, NONE);
DECLARE_get_signature (none, NONE);
-DECLARE_get_signature_gap (none, NONE);
-DECLARE_set_signature_gap (none, NONE);
-DECLARE_HICN_OPS (none);
+DECLARE_has_signature (none, NONE);
+DECLARE_get_signature_padding (none, NONE);
+DECLARE_set_signature_padding (none, NONE);
+DECLARE_is_last_data (none, NONE);
+DECLARE_set_last_data (none, NONE);
+DECLARE_HICN_OPS (none, 0);
/**
* @brief Virtual function table for packet operations
@@ -84,10 +96,12 @@ const hicn_ops_t *const hicn_ops_vft[] = {
/* 0 */ [IPPROTO_IP] = &hicn_ops_ipv4,
/* 1 */[IPPROTO_ICMP] = &hicn_ops_icmp,
/* 6 */[IPPROTO_TCP] = &hicn_ops_tcp,
+ /* 6 */[IPPROTO_UDP] = &hicn_ops_udp,
/* 41 */[IPPROTO_IPV6] = &hicn_ops_ipv6,
/* 51 */[IPPROTO_AH] = &hicn_ops_ah,
/* 58 */[IPPROTO_ICMPV6] = &hicn_ops_icmp,
- [IPPROTO_NONE] = &hicn_ops_none,
+ /* 59 */[IPPROTO_NONE] = &hicn_ops_none,
+ /* 98 */[IPPROTO_ENCAP] = &hicn_ops_new,
};
/*
diff --git a/lib/src/ops.h b/lib/src/ops.h
new file mode 100644
index 000000000..843945690
--- /dev/null
+++ b/lib/src/ops.h
@@ -0,0 +1,979 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file base.h
+ * @brief Protocol-independent packet operations
+ */
+
+#ifndef HICN_OPS_H
+#define HICN_OPS_H
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <hicn/base.h>
+#include <hicn/error.h>
+#include <hicn/name.h>
+#include <hicn/packet.h> // HICN_OPAQUE_LEN
+#include <hicn/util/ip_address.h>
+
+#include "protocol.h"
+
+/*
+ * In order to provide fast lookup and accelerate packet operations, we allow
+ * ourselves to use a header cache structure under the responsibility of the
+ * caller, and that can be associated to each packet. This structure is exposed
+ * as a opaque pointer.
+ */
+
+/*
+ * hICN operations on packets
+ *
+ * All prototypes take an hicn_type_t parameter as their first argument, as
+ * this decides the sequence of protocols that are being used by the different
+ * operations.
+ */
+
+typedef struct hicn_ops_s
+{
+ const char *name;
+
+ size_t header_len;
+
+ /**
+ * @brief Initialize the headers of the hicn packet
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ */
+ int (*init_packet_header) (hicn_packet_buffer_t *pkbuf, size_t pos);
+
+ /**
+ * @brief Retrieves an Interest locator
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [out] ip_address - Retrieved locator
+ * @return hICN error code
+ */
+ int (*get_interest_locator) (const hicn_packet_buffer_t *pkbuf,
+ const size_t pos,
+ hicn_ip_address_t *ip_address);
+
+ /**
+ * @brief Sets an Interest locator
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] ip_address - Locator to set
+ * @return hICN error code
+ */
+ int (*set_interest_locator) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *ip_address);
+
+ /**
+ * @brief Retrieves an Interest name
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [out] name - Retrieved name
+ * @return hICN error code
+ */
+ int (*get_interest_name) (const hicn_packet_buffer_t *pkbuf,
+ const size_t pos, hicn_name_t *name);
+
+ /**
+ * @brief Sets an Interest name
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] name - Name to set
+ * @return hICN error code
+ */
+ int (*set_interest_name) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_name_t *name);
+
+ /**
+ * @brief Retrieves an Interest name suffix
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [out] suffix - Retrieved name suffix
+ * @return hICN error code
+ */
+ int (*get_interest_name_suffix) (const hicn_packet_buffer_t *pkbuf,
+ const size_t pos,
+ hicn_name_suffix_t *suffix);
+
+ /**
+ * @brief Sets an Interest name suffix
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] suffix - Name suffix to set
+ * @return hICN error code
+ */
+ int (*set_interest_name_suffix) (const hicn_packet_buffer_t *pkbuf,
+ size_t pos,
+ const hicn_name_suffix_t *suffix);
+
+ /**
+ * @brief Get packet type
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Position within the network layers
+ * @param [out] type - Packet type
+ * @return hICN error code
+ */
+ int (*get_type) (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ hicn_packet_type_t *type);
+
+ /**
+ * @brief Set flag to mark current packet as interest
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Position within the network layers
+ * @param [in] type - Packet type
+ * @return hICN error code
+ */
+ int (*set_type) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_packet_type_t type);
+
+ /**
+ * @brief Clear the necessary Interest fields in order to hash it
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @return hICN error code
+ */
+ int (*reset_interest_for_hash) (hicn_packet_buffer_t *pkbuf, size_t pos);
+
+ /**
+ * @brief Retrieves a Data locator
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [out] ip_address - Retrieved locator
+ * @return hICN error code
+ */
+ int (*get_data_locator) (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ hicn_ip_address_t *ip_address);
+
+ /**
+ * @brief Sets a Data locator
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] ip_address - Locator to set
+ * @return hICN error code
+ */
+ int (*set_data_locator) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *ip_address);
+
+ /**
+ * @brief Retrieves a Data name
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [out] name - Retrieved name
+ * @return hICN error code
+ */
+ int (*get_data_name) (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ hicn_name_t *name);
+
+ /**
+ * @brief Sets a Data name
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] name - Name to set
+ * @return hICN error code
+ */
+ int (*set_data_name) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_name_t *name);
+
+ /**
+ * @brief Retrieves a Data name suffix
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [out] suffix - Retrieved name suffix
+ * @return hICN error code
+ */
+ int (*get_data_name_suffix) (const hicn_packet_buffer_t *pkbuf,
+ const size_t pos, hicn_name_suffix_t *suffix);
+
+ /**
+ * @brief Sets a Data name suffix
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] suffix - Name suffix to set
+ * @return hICN error code
+ */
+ int (*set_data_name_suffix) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_name_suffix_t *suffix);
+
+ /**
+ * @brief Retrieves a Data path_label
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [out] path_label - Retrieved path_label
+ * @return hICN error code
+ */
+ int (*get_data_path_label) (const hicn_packet_buffer_t *pkbuf,
+ const size_t pos, hicn_path_label_t *path_label);
+
+ /**
+ * @brief Sets a Data path_label
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] path_label - Pathlabel to set
+ * @return hICN error code
+ */
+ int (*set_data_path_label) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_path_label_t path_label);
+
+ /**
+ * @brief Update a Data path_label with a new face identifier
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] path_label - Face identifier used to update path_label
+ * @return hICN error code
+ */
+ int (*update_data_path_label) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_faceid_t face_id);
+
+ /**
+ * @brief Clear the necessary Data fields in order to hash it
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @return hICN error code
+ */
+ int (*reset_data_for_hash) (hicn_packet_buffer_t *pkbuf, size_t pos);
+
+ /**
+ * @brief Retrieves an Interest or Data lifetime
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [out] path_label - Retrieved lifetime
+ * @return hICN error code
+ */
+ int (*get_lifetime) (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ hicn_lifetime_t *lifetime);
+
+ /**
+ * @brief Sets an Interest or Data lifetime
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [in] path_label - Lifetime to set
+ * @return hICN error code
+ */
+ int (*set_lifetime) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_lifetime_t lifetime);
+
+ /**
+ * @brief Update all checksums in packet headers
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] partial_csum - Partial checksum (set to 0, used internally to
+ * carry intermediate values from IP pseudo-header)
+ * @param [in] payload_len - Payload len (can be set to ~0, retrieved
+ * and used internally to carry payload len across protocol headers)
+ * @return hICN error code
+ *
+ * Payload len is initialized during the initial steps (eg. IP) if not
+ * provided (value is ~0), and not ignored (value is 0).
+ */
+ int (*update_checksums) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len);
+
+ /**
+ * @brief Update all checksums in packet headers
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] old_val - Pointer to the old value
+ * @param [in] new_val - Pointer to the new value
+ * @param [in] size - Size of the changed value
+ * @param [in] skip_first - Skip the first protocol (ignore IP checksum)
+ * @return hICN error code
+ */
+ int (*update_checksums_incremental) (const hicn_packet_buffer_t *pkbuf,
+ size_t pos, u16 *old_val, u16 *new_val,
+ u8 size, bool skip_first);
+
+ /**
+ * @brief Validate all checksums in packet headers
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] partial_csum - Partial checksum, or zero if no partial
+ * checksum available
+ * @param [in] payload_len - Payload len (can be set to ~0, retrieved
+ * and used internally to carry payload len across protocol headers)
+ * @return hICN error code
+ */
+ int (*verify_checksums) (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ u16 partial_csum, size_t payload_len);
+
+ /**
+ * @brief Rewrite an Interest packet header (locator)
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] addr_new - New locator
+ * @param [in] addr_old - Old locator (set to NULL, used internally to
+ * compute incremental checksums)
+ * @return hICN error code
+ */
+ int (*rewrite_interest) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old);
+
+ /**
+ * @brief Rewrite a Data packet header (locator + path_label)
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @param [in] addr_new - New locator
+ * @param [in] addr_old - Old locator (set to NULL, used internally to
+ * compute incremental checksums)
+ * @param [in] face_id - Face identifier used to update path_label
+ * @param [in] reset_pl - If not zero, reset the current path_label
+ * before update it
+ * @return hICN error code
+ */
+ int (*rewrite_data) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old,
+ const hicn_faceid_t face_id, u8 reset_pl);
+
+ /**
+ * @brief Return the packet len
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @parma [out] len - Returned packet len
+ * @return hICN error code
+ */
+ int (*get_len) (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ size_t *len);
+
+ /**
+ * @brief Return the current packet header len
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @parma [out] header_len - Returned packet current header len
+ * @return hICN error code
+ */
+ int (*get_current_header_len) (const hicn_packet_buffer_t *pkbuf,
+ const size_t pos, size_t *header_len);
+
+ /**
+ * @brief Sets the packet paylaod len
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Depth in the header stack
+ * @parma [out] payload_len - Payload len to set
+ * @return hICN error code
+ */
+ int (*set_payload_len) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t payload_len);
+
+ /**
+ * @brief Retrieves an Interest or Data signature size
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [out] signature_size - Retrieved signature size
+ * @return hICN error code
+ */
+ int (*get_signature_size) (const hicn_packet_buffer_t *pkbuf,
+ const size_t pos, size_t *signature_size);
+
+ /**
+ * @brief Sets an Interest or Data signature size
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [in] signature_size - Signature size to set
+ * @return hICN error code
+ */
+ int (*set_signature_size) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t signature_size);
+
+ /**
+ * @brief Sets an Interest or Data signature padding between maximum size and
+ * real size
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [in] signature_size - Signature size to set
+ * @return hICN error code
+ */
+ int (*set_signature_padding) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t signature_padding);
+
+ /**
+ * @brief gets an Interest or Data signature padding between maximum size and
+ * real size
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [in] signature_size - retrieve the padding between maximum size and
+ * real size
+ * @return hICN error code
+ */
+ int (*get_signature_padding) (const hicn_packet_buffer_t *pkbuf,
+ const size_t pos, size_t *signature_padding);
+
+ /**
+ * @brief Gets the signature timestamp
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [out] signature_timestamp - Retrieved signature timestamp
+ * @return hICN error code
+ */
+ int (*get_signature_timestamp) (const hicn_packet_buffer_t *pkbuf,
+ const size_t pos,
+ uint64_t *signature_timestamp);
+
+ /**
+ * @brief Sets the signature timestamp
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [in] signature_timestamp - Signature timestamp to set
+ * @return hICN error code
+ */
+ int (*set_signature_timestamp) (const hicn_packet_buffer_t *pkbuf,
+ size_t pos, uint64_t signature_timestamp);
+
+ /**
+ * @brief Gets the signature validation algorithm
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [out] validation_algorithm - Retrieved validation_algorithm
+ * @return hICN error code
+ */
+ int (*get_validation_algorithm) (const hicn_packet_buffer_t *pkbuf,
+ const size_t pos,
+ uint8_t *validation_algorithm);
+
+ /**
+ * @brief Sets the signature validation algorithm
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [in] validation_algorithm - Validation algorithm enumeration
+ * @return hICN error code
+ */
+ int (*set_validation_algorithm) (const hicn_packet_buffer_t *pkbuf,
+ size_t pos, uint8_t validation_algorithm);
+
+ /**
+ * @brief Gets the key id
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [out] key_id - Retrieved key id first byte address
+ * @return hICN error code
+ */
+ int (*get_key_id) (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ uint8_t **key_id, uint8_t *key_id_size);
+
+ /**
+ * @brief Sets the key id
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [in] key_id - Key id first byte address
+ * @return hICN error code
+ */
+ int (*set_key_id) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t *key_id, size_t size);
+
+ /**
+ * @brief Get a pointer to the signature field in the packet
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [out] signature - Pointer to the memory region holding the
+ * signature
+ * @return hICN error code
+ */
+ int (*get_signature) (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ uint8_t **signature);
+
+ /**
+ * @brief Returns whether the packet holds a signature.
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [out] flag - Boolean indicating whether the packet has a signature.
+ * @return hICN error code
+ */
+ int (*has_signature) (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ bool *flag);
+
+ /**
+ * @brief Set payload type of the packet
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in,out] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [in] payload_type - The payload type of this packet
+ * @return hICN error code
+ */
+ int (*set_payload_type) (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_payload_type_t payload_type);
+
+ /**
+ * @brief Get payload type from the packet
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [out] payload_type - The payload type of this packet
+ * @return hICN error code
+ */
+ int (*get_payload_type) (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ hicn_payload_type_t *payload_type);
+
+ /**
+ * @brief Check if data packet is last one.
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in] pos - Current position in the sequence of headers while
+ * executing command
+ * @param [out] is_last - 1 if last data, 0 otherwise
+ * @return hICN error code
+ */
+ int (*is_last_data) (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ int *is_last);
+
+ /**
+ * @brief Mark data packet as last
+ * @param [in] pkbuf - hICN packet buffer
+ * @param [in, out] pos - Current position in the sequence of headers while
+ * executing command
+ * @return hICN error code
+ */
+ int (*set_last_data) (const hicn_packet_buffer_t *pkbuf, size_t pos);
+
+} hicn_ops_t;
+
+#define DECLARE_HICN_OPS(protocol, len) \
+ const hicn_ops_t hicn_ops_##protocol = { \
+ ATTR_INIT (name, #protocol), \
+ ATTR_INIT (header_len, len), \
+ ATTR_INIT (init_packet_header, protocol##_init_packet_header), \
+ ATTR_INIT (get_interest_locator, protocol##_get_interest_locator), \
+ ATTR_INIT (set_interest_locator, protocol##_set_interest_locator), \
+ ATTR_INIT (get_interest_name, protocol##_get_interest_name), \
+ ATTR_INIT (set_interest_name, protocol##_set_interest_name), \
+ ATTR_INIT (get_interest_name_suffix, \
+ protocol##_get_interest_name_suffix), \
+ ATTR_INIT (set_interest_name_suffix, \
+ protocol##_set_interest_name_suffix), \
+ ATTR_INIT (get_type, protocol##_get_type), \
+ ATTR_INIT (set_type, protocol##_set_type), \
+ ATTR_INIT (reset_interest_for_hash, protocol##_reset_interest_for_hash), \
+ ATTR_INIT (get_data_locator, protocol##_get_data_locator), \
+ ATTR_INIT (set_data_locator, protocol##_set_data_locator), \
+ ATTR_INIT (get_data_name, protocol##_get_data_name), \
+ ATTR_INIT (set_data_name, protocol##_set_data_name), \
+ ATTR_INIT (get_data_name_suffix, protocol##_get_data_name_suffix), \
+ ATTR_INIT (set_data_name_suffix, protocol##_set_data_name_suffix), \
+ ATTR_INIT (get_data_path_label, protocol##_get_data_path_label), \
+ ATTR_INIT (set_data_path_label, protocol##_set_data_path_label), \
+ ATTR_INIT (update_data_path_label, protocol##_update_data_path_label), \
+ ATTR_INIT (reset_data_for_hash, protocol##_reset_data_for_hash), \
+ ATTR_INIT (get_lifetime, protocol##_get_lifetime), \
+ ATTR_INIT (set_lifetime, protocol##_set_lifetime), \
+ ATTR_INIT (update_checksums, protocol##_update_checksums), \
+ ATTR_INIT (update_checksums_incremental, \
+ protocol##_update_checksums_incremental), \
+ ATTR_INIT (verify_checksums, protocol##_verify_checksums), \
+ ATTR_INIT (rewrite_interest, protocol##_rewrite_interest), \
+ ATTR_INIT (rewrite_data, protocol##_rewrite_data), \
+ ATTR_INIT (set_payload_len, protocol##_set_payload_len), \
+ ATTR_INIT (get_payload_type, protocol##_get_payload_type), \
+ ATTR_INIT (set_payload_type, protocol##_set_payload_type), \
+ ATTR_INIT (get_signature_size, protocol##_get_signature_size), \
+ ATTR_INIT (get_signature_timestamp, protocol##_get_signature_timestamp), \
+ ATTR_INIT (set_signature_timestamp, protocol##_set_signature_timestamp), \
+ ATTR_INIT (get_validation_algorithm, \
+ protocol##_get_validation_algorithm), \
+ ATTR_INIT (set_validation_algorithm, \
+ protocol##_set_validation_algorithm), \
+ ATTR_INIT (get_key_id, protocol##_get_key_id), \
+ ATTR_INIT (set_key_id, protocol##_set_key_id), \
+ ATTR_INIT (get_signature, protocol##_get_signature), \
+ ATTR_INIT (has_signature, protocol##_has_signature), \
+ ATTR_INIT (set_signature_padding, protocol##_set_signature_padding), \
+ ATTR_INIT (set_signature_size, protocol##_set_signature_size), \
+ ATTR_INIT (get_signature_padding, protocol##_get_signature_padding), \
+ ATTR_INIT (is_last_data, protocol##_is_last_data), \
+ }
+
+/**
+ * @brief Protocol-independent packet operations VFT
+ * NOTE: The following declarations should be kept in order
+ */
+extern const hicn_ops_t *const hicn_ops_vft[];
+
+static inline uint8_t
+PROT (const hicn_packet_buffer_t *pkbuf, int pos)
+{
+ if (pos < -1 || pos >= HICN_PACKET_FORMAT_SIZE - 1)
+ return IPPROTO_NONE;
+ hicn_packet_format_t format = hicn_packet_get_format (pkbuf);
+ return HICN_PACKET_FORMAT_GET (format, pos + 1);
+}
+
+#define CALL_CHILD(method, pkbuf, pos, ...) \
+ hicn_ops_vft[PROT (pkbuf, (pos))]->method (pkbuf, (pos) + 1, ##__VA_ARGS__);
+
+#define CALL(method, pkbuf, ...) CALL_CHILD (method, pkbuf, -1, ##__VA_ARGS__)
+
+/** Shortcuts to entry points in VFT */
+#define HICN_OPS4 hicn_ops_vft[IPPROTO_IP]
+#define HICN_OPS6 hicn_ops_vft[IPPROTO_IPV6]
+
+/* Helpers for simple declarations */
+
+#define DECLARE_init_packet_header(protocol, error) \
+ int protocol##_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_interest_locator(protocol, error) \
+ int protocol##_get_interest_locator (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, \
+ hicn_ip_address_t *ip_address) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_interest_locator(protocol, error) \
+ int protocol##_set_interest_locator (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, \
+ const hicn_ip_address_t *ip_address) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_interest_name(protocol, error) \
+ int protocol##_get_interest_name (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, hicn_name_t *name) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_interest_name(protocol, error) \
+ int protocol##_set_interest_name (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, const hicn_name_t *name) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_interest_name_suffix(protocol, error) \
+ int protocol##_get_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, \
+ hicn_name_suffix_t *suffix) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_interest_name_suffix(protocol, error) \
+ int protocol##_set_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, \
+ const hicn_name_suffix_t *suffix) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_type(protocol, error) \
+ int protocol##_get_type (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, hicn_packet_type_t *type) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_type(protocol, error) \
+ int protocol##_set_type (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, hicn_packet_type_t type) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_reset_interest_for_hash(protocol, error) \
+ int protocol##_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, \
+ size_t pos) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_data_locator(protocol, error) \
+ int protocol##_get_data_locator (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, \
+ hicn_ip_address_t *ip_address) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_data_locator(protocol, error) \
+ int protocol##_set_data_locator (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, \
+ const hicn_ip_address_t *ip_address) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_data_name(protocol, error) \
+ int protocol##_get_data_name (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, hicn_name_t *name) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_data_name(protocol, error) \
+ int protocol##_set_data_name (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, const hicn_name_t *name) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_data_name_suffix(protocol, error) \
+ int protocol##_get_data_name_suffix (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, \
+ hicn_name_suffix_t *suffix) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_data_name_suffix(protocol, error) \
+ int protocol##_set_data_name_suffix (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, \
+ const hicn_name_suffix_t *suffix) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_data_path_label(protocol, error) \
+ int protocol##_get_data_path_label (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, \
+ hicn_path_label_t *path_label) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_data_path_label(protocol, error) \
+ int protocol##_set_data_path_label (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, \
+ const hicn_path_label_t path_label) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_update_data_path_label(protocol, error) \
+ int protocol##_update_data_path_label (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, \
+ const hicn_faceid_t face_id) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_reset_data_for_hash(protocol, error) \
+ int protocol##_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, \
+ size_t pos) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_lifetime(protocol, error) \
+ int protocol##_get_lifetime (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, hicn_lifetime_t *lifetime) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_lifetime(protocol, error) \
+ int protocol##_set_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos, \
+ const hicn_lifetime_t lifetime) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_update_checksums(protocol, error) \
+ int protocol##_update_checksums (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, u16 partial_csum, \
+ size_t payload_len) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_update_checksums_incremental(protocol, error) \
+ int protocol##_update_checksums_incremental ( \
+ const hicn_packet_buffer_t *pkbuf, size_t pos, u16 *old_val, \
+ u16 *new_val, u8 size, bool skip_first) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_verify_checksums(protocol, error) \
+ int protocol##_verify_checksums (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, u16 partial_csum, \
+ size_t payload_len) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_rewrite_interest(protocol, error) \
+ int protocol##_rewrite_interest ( \
+ const hicn_packet_buffer_t *pkbuf, size_t pos, \
+ const hicn_ip_address_t *addr_new, hicn_ip_address_t *addr_old) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_rewrite_data(protocol, error) \
+ int protocol##_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos, \
+ const hicn_ip_address_t *addr_new, \
+ hicn_ip_address_t *addr_old, \
+ const hicn_faceid_t face_id, u8 reset_pl) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_payload_len(protocol, error) \
+ int protocol##_set_payload_len (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, size_t payload_len) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_payload_type(protocol, error) \
+ int protocol##_get_payload_type (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, \
+ hicn_payload_type_t *payload_type) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_payload_type(protocol, error) \
+ int protocol##_set_payload_type (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, \
+ hicn_payload_type_t payload_type) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_signature_size(protocol, error) \
+ int protocol##_get_signature_size (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, \
+ size_t *signature_size) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_signature_size(protocol, error) \
+ int protocol##_set_signature_size (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, size_t signature_size) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_signature_padding(protocol, error) \
+ int protocol##_set_signature_padding (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, size_t padding) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_signature_padding(protocol, error) \
+ int protocol##_get_signature_padding (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, size_t *padding) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_signature_timestamp(protocol, error) \
+ int protocol##_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, \
+ uint64_t signature_timestamp) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_signature_timestamp(protocol, error) \
+ int protocol##_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, \
+ uint64_t *signature_timestamp) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_validation_algorithm(protocol, error) \
+ int protocol##_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos, \
+ uint8_t validation_algorithm) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_validation_algorithm(protocol, error) \
+ int protocol##_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, \
+ uint8_t *validation_algorithm) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_key_id(protocol, error) \
+ int protocol##_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, \
+ uint8_t *key_id, size_t size) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_key_id(protocol, error) \
+ int protocol##_get_key_id (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, uint8_t **key_id, \
+ uint8_t *key_id_size) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_signature(protocol, error) \
+ int protocol##_get_signature (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, uint8_t **signature) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_has_signature(protocol, error) \
+ int protocol##_has_signature (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, bool *flag) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_is_last_data(protocol, error) \
+ int protocol##_is_last_data (const hicn_packet_buffer_t *pkbuf, \
+ const size_t pos, int *is_last) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_last_data(protocol, error) \
+ int protocol##_set_last_data (const hicn_packet_buffer_t *pkbuf, \
+ size_t pos) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#endif /* HICN_OPS_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/packet.c b/lib/src/packet.c
new file mode 100644
index 000000000..bebfad23e
--- /dev/null
+++ b/lib/src/packet.c
@@ -0,0 +1,806 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file packet.c
+ * @brief Implementation of the compatibility layer.
+ */
+#ifndef _WIN32
+#include <netinet/in.h>
+#endif
+#include <string.h> // memset
+#include <stddef.h> // offsetof
+
+#include <hicn/common.h>
+#include <hicn/packet.h>
+#include <hicn/error.h>
+#include <hicn/name.h>
+#include <hicn/util/log.h>
+#include "ops.h"
+
+#define member_size(type, member) sizeof (((type *) 0)->member)
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof (*(a)))
+
+#define HICN_NAME_COMPONENT_SIZE 2
+
+hicn_packet_format_t
+hicn_packet_get_format (const hicn_packet_buffer_t *pkbuf)
+{
+ return pkbuf->format;
+}
+
+void
+hicn_packet_set_format (hicn_packet_buffer_t *pkbuf,
+ hicn_packet_format_t format)
+{
+ pkbuf->format = format;
+}
+
+hicn_packet_type_t
+hicn_packet_get_type (const hicn_packet_buffer_t *pkbuf)
+{
+ return pkbuf->type;
+}
+
+void
+hicn_packet_initialize_type (hicn_packet_buffer_t *pkbuf,
+ hicn_packet_type_t type)
+{
+ assert (pkbuf->format != HICN_PACKET_FORMAT_NONE);
+ pkbuf->type = type;
+ CALL (set_type, pkbuf, type);
+}
+
+void
+hicn_packet_set_type (hicn_packet_buffer_t *pkbuf, hicn_packet_type_t type)
+{
+ pkbuf->type = type;
+}
+
+bool
+hicn_packet_is_interest (const hicn_packet_buffer_t *pkbuf)
+{
+ return pkbuf->type == HICN_PACKET_TYPE_INTEREST;
+}
+
+bool
+hicn_packet_is_data (const hicn_packet_buffer_t *pkbuf)
+{
+ return pkbuf->type == HICN_PACKET_TYPE_DATA;
+}
+
+bool
+hicn_packet_is_undefined (const hicn_packet_buffer_t *pkbuf)
+{
+ return pkbuf->type == HICN_PACKET_TYPE_UNDEFINED;
+}
+
+int
+hicn_packet_init_header (hicn_packet_buffer_t *pkbuf,
+ size_t additional_header_size)
+{
+ if (hicn_packet_is_undefined (pkbuf))
+ return HICN_LIB_ERROR_UNEXPECTED;
+ if (hicn_packet_get_format (pkbuf) == HICN_PACKET_FORMAT_NONE)
+ return HICN_LIB_ERROR_UNEXPECTED;
+ if (!pkbuf_get_header (pkbuf))
+ return HICN_LIB_ERROR_UNEXPECTED;
+ pkbuf->len = 0;
+ pkbuf->payload = 0;
+
+ int rc = CALL (init_packet_header, pkbuf);
+
+ /*
+ * Additional header size is there for the signature, and assumes the AH
+ * header is always located at the end...
+ */
+ pkbuf->len += additional_header_size;
+ pkbuf->payload += additional_header_size;
+
+ return rc;
+}
+
+int
+hicn_packet_reset (hicn_packet_buffer_t *pkbuf)
+{
+ memset (pkbuf, 0, sizeof (hicn_packet_buffer_t));
+ hicn_packet_set_format (pkbuf, HICN_PACKET_FORMAT_NONE);
+ hicn_packet_set_type (pkbuf, HICN_PACKET_TYPE_UNDEFINED);
+ hicn_packet_set_len (pkbuf, 0);
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_analyze (hicn_packet_buffer_t *pkbuf)
+{
+ u8 *header = pkbuf_get_header (pkbuf);
+ u8 protocol;
+ u16 offset = 0;
+ bool has_signature;
+ size_t signature_size;
+ int rc;
+
+ /* Bootstrap: assume IP packet, and get version from header */
+ switch (HICN_IP_VERSION (pkbuf_get_header (pkbuf)))
+ {
+ case 4:
+ protocol = IPPROTO_IP;
+ break;
+ case 6:
+ protocol = IPPROTO_IPV6;
+ break;
+ case 9:
+ protocol = IPPROTO_ENCAP; // new
+ break;
+ default:
+ goto ERR;
+ }
+
+ hicn_packet_format_t *format = &pkbuf->format;
+ for (unsigned i = 0; i < HICN_PACKET_FORMAT_SIZE; i++)
+ {
+ HICN_PACKET_FORMAT_SET (*format, i, protocol);
+
+ /* Next protocol + increment offset */
+ switch (protocol)
+ {
+
+ /*
+ * All packets either start with IPv4 or IPv6, so we take the
+ * opportunity to update packet length there
+ */
+ case IPPROTO_IP:
+ {
+ if (i > 0)
+ goto ERR;
+#ifdef OPAQUE_IP
+ pkbuf->ipv4 = offset;
+#else
+ assert (offset == 0);
+#endif /* OPAQUE_IP */
+ _ipv4_header_t *ipv4 = (_ipv4_header_t *) (header + offset);
+ protocol = ipv4->protocol;
+ offset += IPV4_HDRLEN;
+
+ // hicn_packet_set_len (pkbuf, htons (ipv4->len));
+ if (hicn_packet_get_len (pkbuf) != htons (ipv4->len))
+ {
+ ERROR ("Invalid packet size in IPv4 header %d != %d",
+ htons (ipv4->len), hicn_packet_get_len (pkbuf));
+ goto ERR;
+ }
+ break;
+ }
+ case IPPROTO_IPV6:
+ {
+ if (i > 0)
+ goto ERR;
+#ifdef OPAQUE_IP
+ pkbuf->ipv6 = offset;
+#else
+ assert (offset == 0);
+#endif /* OPAQUE_IP */
+ _ipv6_header_t *ipv6 = (_ipv6_header_t *) (header + offset);
+ protocol = ipv6->nxt;
+ offset += IPV6_HDRLEN;
+ // hicn_packet_set_len (pkbuf, IPV6_HDRLEN + htons (ipv6->len));
+ if (hicn_packet_get_len (pkbuf) != IPV6_HDRLEN + htons (ipv6->len))
+ {
+ ERROR ("Invalid packet size in IPv6 header %d != %d",
+ IPV6_HDRLEN + htons (ipv6->len),
+ hicn_packet_get_len (pkbuf));
+ goto ERR;
+ }
+ break;
+ }
+ case IPPROTO_TCP:
+ pkbuf->tcp = offset;
+ /* After TCP, we might eventually have a AH header */
+ rc = CALL_CHILD (has_signature, pkbuf, i - 1, &has_signature);
+ if (rc < 0)
+ goto ERR;
+ protocol = has_signature ? IPPROTO_AH : IPPROTO_NONE;
+ offset += TCP_HDRLEN;
+ break;
+ case IPPROTO_UDP:
+ pkbuf->udp = offset;
+ protocol = IPPROTO_ENCAP;
+ offset += UDP_HDRLEN;
+ break;
+ case IPPROTO_ICMP:
+ case IPPROTO_ICMPV6:
+ pkbuf->icmp = offset;
+ /* After ICMP, we might eventually have a AH header */
+ // CALL_CHILD (has_signature, pkbuf, i - 1, &has_signature);
+ protocol = /* has_signature ? IPPROTO_AH : */ IPPROTO_NONE;
+ offset += ICMP_HDRLEN;
+ break;
+
+ case IPPROTO_ENCAP:
+ pkbuf->newhdr = offset;
+ /* After ENCAP, we might eventually have a AH header */
+ rc = CALL_CHILD (has_signature, pkbuf, i - 1, &has_signature);
+ if (rc < 0)
+ goto ERR;
+ protocol = has_signature ? IPPROTO_AH : IPPROTO_NONE;
+ offset += NEW_HDRLEN;
+ break;
+
+ case IPPROTO_AH:
+ pkbuf->ah = offset;
+ protocol = IPPROTO_NONE;
+ offset += AH_HDRLEN;
+
+ rc = CALL_CHILD (get_signature_size, pkbuf, i - 1, &signature_size);
+ if (rc < 0)
+ goto ERR;
+ offset += signature_size;
+ break;
+
+ case IPPROTO_NONE:
+ /* NONE until we terminate the list of protocols */
+ break;
+
+ default:
+ goto ERR;
+ }
+ }
+ pkbuf->payload = offset;
+
+ rc = CALL (get_type, pkbuf, (hicn_packet_type_t *) (&pkbuf->type));
+ if (rc < 0)
+ goto ERR;
+
+ return HICN_LIB_ERROR_NONE;
+
+ERR:
+ pkbuf->format = HICN_PACKET_FORMAT_NONE;
+ pkbuf->type = HICN_PACKET_TYPE_UNDEFINED;
+ return HICN_LIB_ERROR_UNEXPECTED;
+}
+
+int
+hicn_packet_set_buffer (hicn_packet_buffer_t *pkbuf, u8 *buffer,
+ uint16_t buffer_size, uint16_t len)
+{
+ pkbuf_set_header (pkbuf, buffer);
+ pkbuf->buffer_size = buffer_size;
+ pkbuf->len = len;
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_get_buffer (const hicn_packet_buffer_t *pkbuf, u8 **buffer,
+ uint16_t *buffer_size, uint16_t *len)
+{
+ *buffer = pkbuf_get_header (pkbuf);
+ *buffer_size = pkbuf->buffer_size;
+ *len = pkbuf->len;
+ return HICN_LIB_ERROR_NONE;
+}
+
+size_t
+hicn_packet_get_len (const hicn_packet_buffer_t *pkbuf)
+{
+ return pkbuf->len;
+}
+
+int
+hicn_packet_set_len (hicn_packet_buffer_t *pkbuf, size_t len)
+{
+ pkbuf->len = len;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_get_header_len (const hicn_packet_buffer_t *pkbuf, size_t *len)
+{
+ *len = pkbuf->payload;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_get_payload_len (const hicn_packet_buffer_t *pkbuf, size_t *len)
+{
+ *len = hicn_packet_get_len (pkbuf) - pkbuf->payload;
+ return HICN_LIB_ERROR_NONE;
+}
+
+// XXX this fails with chained membufs in libtransport
+int
+hicn_packet_set_payload (const hicn_packet_buffer_t *pkbuf, const u8 *payload,
+ u16 payload_len)
+{
+ memcpy (pkbuf_get_header (pkbuf) + pkbuf->payload, payload, payload_len);
+
+ return CALL (set_payload_len, pkbuf, payload_len);
+}
+
+int
+hicn_packet_get_payload (const hicn_packet_buffer_t *pkbuf, u8 **payload,
+ size_t *payload_size, bool hard_copy)
+{
+ *payload_size = hicn_packet_get_len (pkbuf) - pkbuf->payload;
+
+ if (hard_copy)
+ {
+ memcpy (payload, pkbuf_get_header (pkbuf) + pkbuf->payload,
+ *payload_size);
+ }
+ else
+ {
+ *payload = pkbuf_get_header (pkbuf) + pkbuf->payload;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+/* Header fields manipulation */
+
+int
+hicn_packet_get_header_length_from_format (hicn_packet_format_t format,
+ size_t *header_length)
+{
+ *header_length = 0;
+ HICN_PACKET_FORMAT_ENUMERATE (format, i, protocol, {
+ *header_length += hicn_ops_vft[protocol]->header_len;
+ });
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_compute_checksum (const hicn_packet_buffer_t *pkbuf)
+{
+ return CALL (update_checksums, pkbuf, 0, ~0);
+}
+
+int
+hicn_packet_compute_header_checksum (const hicn_packet_buffer_t *pkbuf,
+ u16 init_sum)
+{
+ /* payload_len == 0: ignore payload */
+ return CALL (update_checksums, pkbuf, init_sum, 0);
+}
+
+int
+hicn_packet_check_integrity_no_payload (const hicn_packet_buffer_t *pkbuf,
+ u16 init_sum)
+{
+ return CALL (verify_checksums, pkbuf, init_sum, 0);
+}
+
+int
+hicn_packet_set_payload_length (const hicn_packet_buffer_t *pkbuf,
+ const size_t payload_len)
+{
+ return CALL (set_payload_len, pkbuf, payload_len);
+}
+
+int
+hicn_packet_compare (const hicn_packet_buffer_t *pkbuf1,
+ const hicn_packet_buffer_t *pkbuf2)
+{
+ hicn_packet_format_t format1 = hicn_packet_get_format (pkbuf1);
+ hicn_packet_format_t format2 = hicn_packet_get_format (pkbuf2);
+
+ if (format1 != format2)
+ return HICN_LIB_ERROR_UNEXPECTED;
+
+ size_t len1 = hicn_packet_get_len (pkbuf1);
+ size_t len2 = hicn_packet_get_len (pkbuf2);
+
+ if (len1 != len2)
+ return HICN_LIB_ERROR_UNEXPECTED;
+
+ return memcmp (pkbuf_get_header (pkbuf1), pkbuf_get_header (pkbuf2), len1);
+}
+
+int
+hicn_packet_get_name (const hicn_packet_buffer_t *pkbuf, hicn_name_t *name)
+{
+ switch (pkbuf->type)
+ {
+ case HICN_PACKET_TYPE_INTEREST:
+ return hicn_interest_get_name (pkbuf, name);
+ case HICN_PACKET_TYPE_DATA:
+ return hicn_data_get_name (pkbuf, name);
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+}
+
+int
+hicn_packet_set_name (const hicn_packet_buffer_t *pkbuf,
+ const hicn_name_t *name)
+{
+ switch (pkbuf->type)
+ {
+ case HICN_PACKET_TYPE_INTEREST:
+ return hicn_interest_set_name (pkbuf, name);
+ case HICN_PACKET_TYPE_DATA:
+ return hicn_data_set_name (pkbuf, name);
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+}
+
+int
+hicn_packet_get_locator (const hicn_packet_buffer_t *pkbuf,
+ hicn_ip_address_t *address)
+{
+ switch (pkbuf->type)
+ {
+ case HICN_PACKET_TYPE_INTEREST:
+ return hicn_interest_get_locator (pkbuf, address);
+ case HICN_PACKET_TYPE_DATA:
+ return hicn_data_get_locator (pkbuf, address);
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+}
+
+int
+hicn_packet_set_locator (const hicn_packet_buffer_t *pkbuf,
+ const hicn_ip_address_t *address)
+{
+ switch (pkbuf->type)
+ {
+ case HICN_PACKET_TYPE_INTEREST:
+ return hicn_interest_set_locator (pkbuf, address);
+ case HICN_PACKET_TYPE_DATA:
+ return hicn_data_set_locator (pkbuf, address);
+ default:
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+}
+
+int
+hicn_packet_get_signature_size (const hicn_packet_buffer_t *pkbuf,
+ size_t *bytes)
+{
+ return CALL (get_signature_size, pkbuf, bytes);
+}
+
+int
+hicn_packet_set_signature_size (const hicn_packet_buffer_t *pkbuf,
+ size_t bytes)
+{
+ return CALL (set_signature_size, pkbuf, bytes);
+}
+
+int
+hicn_packet_get_signature_padding (const hicn_packet_buffer_t *pkbuf,
+ size_t *bytes)
+{
+ return CALL (get_signature_padding, pkbuf, bytes);
+}
+
+int
+hicn_packet_set_signature_padding (const hicn_packet_buffer_t *pkbuf,
+ size_t bytes)
+{
+ return CALL (set_signature_padding, pkbuf, bytes);
+}
+
+int
+hicn_packet_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf,
+ uint64_t signature_timestamp)
+{
+ return CALL (set_signature_timestamp, pkbuf, signature_timestamp);
+}
+
+int
+hicn_packet_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf,
+ uint64_t *signature_timestamp)
+{
+ return CALL (get_signature_timestamp, pkbuf, signature_timestamp);
+}
+
+int
+hicn_packet_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf,
+ uint8_t validation_algorithm)
+{
+ return CALL (set_validation_algorithm, pkbuf, validation_algorithm);
+}
+
+int
+hicn_packet_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf,
+ uint8_t *validation_algorithm)
+{
+ return CALL (get_validation_algorithm, pkbuf, validation_algorithm);
+}
+
+int
+hicn_packet_set_key_id (const hicn_packet_buffer_t *pkbuf, uint8_t *key_id,
+ size_t key_len)
+{
+ return CALL (set_key_id, pkbuf, key_id, key_len);
+}
+
+int
+hicn_packet_get_key_id (const hicn_packet_buffer_t *pkbuf, uint8_t **key_id,
+ uint8_t *key_id_len)
+{
+ return CALL (get_key_id, pkbuf, key_id, key_id_len);
+}
+
+int
+hicn_packet_get_lifetime (const hicn_packet_buffer_t *pkbuf,
+ hicn_lifetime_t *lifetime)
+{
+ return CALL (get_lifetime, pkbuf, lifetime);
+}
+
+int
+hicn_packet_set_lifetime (const hicn_packet_buffer_t *pkbuf,
+ hicn_lifetime_t lifetime)
+{
+ return CALL (set_lifetime, pkbuf, lifetime);
+}
+
+int
+hicn_packet_get_payload_type (const hicn_packet_buffer_t *pkbuf,
+ hicn_payload_type_t *payload_type)
+{
+ return CALL (get_payload_type, pkbuf, payload_type);
+}
+
+int
+hicn_packet_set_payload_type (const hicn_packet_buffer_t *pkbuf,
+ hicn_payload_type_t payload_type)
+{
+ return CALL (set_payload_type, pkbuf, payload_type);
+}
+
+int
+hicn_packet_save_header (const hicn_packet_buffer_t *pkbuf, u8 *header,
+ size_t *header_len, bool copy_ah)
+{
+ hicn_packet_format_t format = hicn_packet_get_format (pkbuf);
+ if (copy_ah || !HICN_PACKET_FORMAT_IS_AH (format))
+ {
+ int rc = hicn_packet_get_header_len (pkbuf, header_len);
+ if (HICN_LIB_IS_ERROR (rc))
+ return rc;
+ }
+ else
+ {
+ /* Copy up until the ah header (which we assume is last) */
+ *header_len = pkbuf->ah;
+ }
+
+ memcpy (header, pkbuf_get_header (pkbuf), *header_len);
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+hicn_packet_load_header (const hicn_packet_buffer_t *pkbuf, const u8 *header,
+ size_t header_len)
+{
+ memcpy (pkbuf_get_header (pkbuf), header, header_len);
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+/* Interest */
+
+int
+hicn_interest_get_name (const hicn_packet_buffer_t *pkbuf, hicn_name_t *name)
+{
+ return CALL (get_interest_name, pkbuf, name);
+}
+
+int
+hicn_interest_set_name (const hicn_packet_buffer_t *pkbuf,
+ const hicn_name_t *name)
+{
+ return CALL (set_interest_name, pkbuf, name);
+}
+
+int
+hicn_interest_get_locator (const hicn_packet_buffer_t *pkbuf,
+ hicn_ip_address_t *address)
+{
+ return CALL (get_interest_locator, pkbuf, address);
+}
+
+int
+hicn_interest_set_locator (const hicn_packet_buffer_t *pkbuf,
+ const hicn_ip_address_t *address)
+{
+ return CALL (set_interest_locator, pkbuf, address);
+}
+
+int
+hicn_interest_compare (const hicn_packet_buffer_t *pkbuf1,
+ const hicn_packet_buffer_t *pkbuf2)
+{
+ return hicn_packet_compare (pkbuf1, pkbuf2);
+}
+
+int
+hicn_interest_get_lifetime (const hicn_packet_buffer_t *pkbuf,
+ hicn_lifetime_t *lifetime)
+{
+ return hicn_packet_get_lifetime (pkbuf, lifetime);
+}
+
+int
+hicn_interest_set_lifetime (const hicn_packet_buffer_t *pkbuf,
+ hicn_lifetime_t lifetime)
+{
+ return hicn_packet_set_lifetime (pkbuf, lifetime);
+}
+
+int
+hicn_interest_get_payload (const hicn_packet_buffer_t *pkbuf, u8 **payload,
+ size_t *payload_size, bool hard_copy)
+{
+ return hicn_packet_get_payload (pkbuf, payload, payload_size, hard_copy);
+}
+
+int
+hicn_interest_set_payload (const hicn_packet_buffer_t *pkbuf,
+ const u8 *payload, size_t payload_len)
+{
+ return hicn_packet_set_payload (pkbuf, payload, (u16) payload_len);
+}
+
+int
+hicn_interest_reset_for_hash (hicn_packet_buffer_t *pkbuf)
+{
+ return CALL (reset_interest_for_hash, pkbuf);
+}
+
+/* Data */
+
+int
+hicn_data_get_name (const hicn_packet_buffer_t *pkbuf, hicn_name_t *name)
+{
+ return CALL (get_data_name, pkbuf, name);
+}
+
+int
+hicn_data_set_name (const hicn_packet_buffer_t *pkbuf, const hicn_name_t *name)
+{
+ return CALL (set_data_name, pkbuf, name);
+}
+
+int
+hicn_data_get_locator (const hicn_packet_buffer_t *pkbuf,
+ hicn_ip_address_t *address)
+{
+ return CALL (get_data_locator, pkbuf, address);
+}
+
+int
+hicn_data_set_locator (const hicn_packet_buffer_t *pkbuf,
+ const hicn_ip_address_t *address)
+{
+ return CALL (set_data_locator, pkbuf, address);
+}
+
+int
+hicn_data_compare (const hicn_packet_buffer_t *pkbuf1,
+ const hicn_packet_buffer_t *pkbuf2)
+{
+ return hicn_packet_compare (pkbuf1, pkbuf2);
+}
+
+int
+hicn_data_get_expiry_time (const hicn_packet_buffer_t *pkbuf,
+ hicn_lifetime_t *expiry_time)
+{
+ return hicn_packet_get_lifetime (pkbuf, expiry_time);
+}
+
+int
+hicn_data_set_expiry_time (const hicn_packet_buffer_t *pkbuf,
+ hicn_lifetime_t expiry_time)
+{
+ return hicn_packet_set_lifetime (pkbuf, expiry_time);
+}
+
+/* Path label */
+
+int
+hicn_data_get_path_label (const hicn_packet_buffer_t *pkbuf,
+ hicn_path_label_t *path_label)
+{
+ return CALL (get_data_path_label, pkbuf, path_label);
+}
+
+int
+hicn_get_path_label (const hicn_packet_buffer_t *pkbuf,
+ hicn_path_label_t *path_label)
+{
+ if (!hicn_packet_is_data (pkbuf))
+ return INVALID_PATH_LABEL;
+ return hicn_data_get_path_label (pkbuf, path_label);
+}
+
+int
+hicn_data_set_path_label (const hicn_packet_buffer_t *pkbuf,
+ hicn_path_label_t path_label)
+{
+ return CALL (set_data_path_label, pkbuf, path_label);
+}
+
+int
+hicn_data_set_payload (const hicn_packet_buffer_t *pkbuf, const u8 *payload,
+ size_t payload_len)
+{
+ return hicn_packet_set_payload (pkbuf, payload, (u16) payload_len);
+}
+
+int
+hicn_data_get_payload (const hicn_packet_buffer_t *pkbuf, u8 **payload,
+ size_t *payload_size, bool hard_copy)
+{
+ return hicn_packet_get_payload (pkbuf, payload, payload_size, hard_copy);
+}
+
+int
+hicn_data_reset_for_hash (hicn_packet_buffer_t *pkbuf)
+{
+ return CALL (reset_data_for_hash, pkbuf);
+}
+
+int
+hicn_data_is_last (const hicn_packet_buffer_t *pkbuf, int *is_last)
+{
+ return CALL (is_last_data, pkbuf, is_last);
+}
+
+int
+hicn_data_set_last (const hicn_packet_buffer_t *pkbuf)
+{
+ return CALL (set_last_data, pkbuf);
+}
+
+int
+hicn_packet_get_signature (const hicn_packet_buffer_t *pkbuf,
+ uint8_t **sign_buf)
+{
+ return CALL (get_signature, pkbuf, sign_buf);
+}
+
+int
+hicn_interest_rewrite (const hicn_packet_buffer_t *pkbuf,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old)
+{
+ return CALL (rewrite_interest, pkbuf, addr_new, addr_old);
+}
+
+int
+hicn_data_rewrite (const hicn_packet_buffer_t *pkbuf,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old, const hicn_faceid_t face_id,
+ u8 reset_pl)
+{
+ return CALL (rewrite_data, pkbuf, addr_new, addr_old, face_id, reset_pl);
+}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/policy.c b/lib/src/policy.c
index 694f0ea5e..4a4b9fa89 100644
--- a/lib/src/policy.c
+++ b/lib/src/policy.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -21,41 +21,53 @@
#include <stdio.h>
#include <hicn/policy.h>
-const char * policy_tag_str[] = {
- #define _(x, y) [POLICY_TAG_ ## x] = STRINGIZE(x),
- foreach_policy_tag
- #undef _
+const char *policy_tag_str[] = {
+#define _(x, y) [POLICY_TAG_##x] = STRINGIZE (x),
+ foreach_policy_tag
+#undef _
};
const char policy_tag_short_str[] = {
- #define _(x, y) [POLICY_TAG_ ## x] = y,
- foreach_policy_tag
- #undef _
+#define _(x, y) [POLICY_TAG_##x] = y,
+ foreach_policy_tag
+#undef _
};
-const char * policy_state_str[] = {
- #define _(x) [POLICY_STATE_ ## x] = STRINGIZE(x),
- foreach_policy_state
- #undef _
+const char *policy_state_str[] = {
+#define _(x) [POLICY_STATE_##x] = STRINGIZE (x),
+ foreach_policy_state
+#undef _
};
+policy_state_t
+policy_state_from_str (const char *str)
+{
+#define _(x) \
+ if (strcasecmp (str, #x) == 0) \
+ return POLICY_STATE_##x; \
+ else
+ foreach_policy_state
+#undef _
+ return POLICY_STATE_N;
+}
+
int
-policy_tag_state_snprintf(char * s, size_t size, const policy_tag_state_t * tag_state)
+policy_tag_state_snprintf (char *s, size_t size,
+ const policy_tag_state_t *tag_state)
{
- char *cur = s;
- int rc;
-
- if (tag_state->disabled > 1)
- return -1;
-
- rc = snprintf(cur, s + size - cur, "%s%s", (tag_state->disabled == 1) ? "!" : "", policy_state_str[tag_state->state]);
- if (rc >= (int)(s + size - cur))
- return (int)(s + size - cur);
- if (rc < 0)
- return rc;
- cur += rc;
- if (size != 0 && cur >= s + size)
- return (int)(cur - s);
-
- return (int)(cur - s);
+ char *cur = s;
+ int rc;
+
+ if (tag_state->disabled > 1)
+ return -1;
+
+ rc = snprintf (cur, s + size - cur, "%s%s",
+ (tag_state->disabled == 1) ? "!" : "",
+ policy_state_str[tag_state->state]);
+ if (rc >= (int) (s + size - cur))
+ return (int) (s + size - cur);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ return (int) (cur - s);
}
diff --git a/lib/includes/hicn/protocol.h b/lib/src/protocol.h
index a97cc99cf..58bbb2ac2 100644
--- a/lib/includes/hicn/protocol.h
+++ b/lib/src/protocol.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -27,18 +27,7 @@
#include "protocol/icmprd.h"
#include "protocol/tcp.h"
#include "protocol/udp.h"
-
-typedef union
-{
- _ipv4_header_t ipv4;
- _ipv6_header_t ipv6;
- _tcp_header_t tcp;
- _udp_header_t udp;
- _icmp_header_t icmp;
- _icmprd_header_t icmprd;
- _ah_header_t ah;
- void *bytes;
-} hicn_protocol_t;
+#include "protocol/new.h"
#endif /* HICN_PROTOCOL_H */
diff --git a/lib/src/protocol/ah.c b/lib/src/protocol/ah.c
index 13340eae1..ea028d559 100644
--- a/lib/src/protocol/ah.c
+++ b/lib/src/protocol/ah.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -18,12 +18,12 @@
* @brief hICN operations for AH header
*/
-#include <string.h> // memcpy
#include <hicn/common.h>
#include <hicn/error.h>
-#include <hicn/header.h>
-#include <hicn/ops.h>
-#include <hicn/protocol/ah.h>
+#include <string.h> // memcpy
+
+#include "../ops.h"
+#include "ah.h"
DECLARE_get_interest_locator (ah, UNEXPECTED);
DECLARE_set_interest_locator (ah, UNEXPECTED);
@@ -31,206 +31,242 @@ DECLARE_get_interest_name (ah, UNEXPECTED);
DECLARE_set_interest_name (ah, UNEXPECTED);
DECLARE_get_interest_name_suffix (ah, UNEXPECTED);
DECLARE_set_interest_name_suffix (ah, UNEXPECTED);
-DECLARE_mark_packet_as_interest (ah, UNEXPECTED);
-DECLARE_mark_packet_as_data (ah, UNEXPECTED);
+DECLARE_get_type (ah, UNEXPECTED);
+DECLARE_set_type (ah, UNEXPECTED);
DECLARE_get_data_locator (ah, UNEXPECTED);
DECLARE_set_data_locator (ah, UNEXPECTED);
DECLARE_get_data_name (ah, UNEXPECTED);
DECLARE_set_data_name (ah, UNEXPECTED);
DECLARE_get_data_name_suffix (ah, UNEXPECTED);
DECLARE_set_data_name_suffix (ah, UNEXPECTED);
-DECLARE_get_data_pathlabel (ah, UNEXPECTED);
-DECLARE_set_data_pathlabel (ah, UNEXPECTED);
-DECLARE_update_data_pathlabel (ah, UNEXPECTED);
+DECLARE_get_data_path_label (ah, UNEXPECTED);
+DECLARE_set_data_path_label (ah, UNEXPECTED);
+DECLARE_update_data_path_label (ah, UNEXPECTED);
DECLARE_get_lifetime (ah, UNEXPECTED);
DECLARE_set_lifetime (ah, UNEXPECTED);
-DECLARE_get_payload_length (ah, UNEXPECTED);
-DECLARE_set_payload_length (ah, UNEXPECTED);
+// DECLARE_get_payload_len (ah, UNEXPECTED);
+DECLARE_set_payload_len (ah, UNEXPECTED);
+DECLARE_get_payload_type (ah, UNEXPECTED);
+DECLARE_set_payload_type (ah, UNEXPECTED);
+DECLARE_is_last_data (ah, UNEXPECTED);
+DECLARE_set_last_data (ah, UNEXPECTED);
int
-ah_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
+ah_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos)
{
- /* *INDENT-OFF* */
- h->ah = (_ah_header_t){
+ pkbuf->ah = pkbuf->len;
+ if (AH_HDRLEN > pkbuf->buffer_size - pkbuf->len)
+ return -1;
+ pkbuf->len += AH_HDRLEN;
+
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
+ /* clang-format off */
+ *ah = (_ah_header_t){
.nh = (u8) 0,
.payloadlen = (u8) 0,
.reserved = (u16) 0,
};
- /* *INDENT-ON* */
- return CHILD_OPS (init_packet_header, type, h);
+ /* clang-format on */
+ return CALL_CHILD (init_packet_header, pkbuf, pos);
}
int
-ah_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
+ah_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
{
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
size_t signature_size;
- int rc =
- hicn_ops_vft[type.l1]->get_signature_size (type, h, &signature_size);
+ int rc = CALL (get_signature_size, pkbuf, &signature_size);
if (rc < 0)
return rc;
- memset (&(h->ah.validationPayload), 0, signature_size);
- return CHILD_OPS (reset_interest_for_hash, type, h);
+ memset (&(ah->validationPayload), 0, signature_size);
+ ah->signaturePadding = 0;
+ return CALL_CHILD (reset_interest_for_hash, pkbuf, pos);
}
int
-ah_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
+ah_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
{
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
size_t signature_size;
- int rc =
- hicn_ops_vft[type.l1]->get_signature_size (type, h, &signature_size);
+ int rc = CALL (get_signature_size, pkbuf, &signature_size);
if (rc < 0)
return rc;
- memset (&(h->ah.validationPayload), 0, signature_size);
- return CHILD_OPS (reset_interest_for_hash, type, h);
+ memset (&(ah->validationPayload), 0, signature_size);
+ ah->signaturePadding = 0;
+ return CALL_CHILD (reset_interest_for_hash, pkbuf, pos);
}
int
-ah_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
- size_t payload_length)
+ah_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
{
/* Nothing to do as there is no checksum in AH */
return HICN_LIB_ERROR_NONE;
}
int
-ah_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
- size_t payload_length)
+ah_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 *old_val, u16 *new_val, u8 size,
+ bool skip_first)
{
- /* Nothing to do as there is no checksum in AH */
- return HICN_LIB_ERROR_NONE;
+ return CALL_CHILD (update_checksums_incremental, pkbuf, pos, old_val,
+ new_val, size, false);
}
int
-ah_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old)
+ah_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
{
- /* Nothing to do on signature */
+ /* Nothing to do as there is no checksum in AH */
return HICN_LIB_ERROR_NONE;
}
int
-ah_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old,
- const hicn_faceid_t face_id, u8 reset_pl)
+ah_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old)
{
/* Nothing to do on signature */
return HICN_LIB_ERROR_NONE;
}
int
-ah_get_length (hicn_type_t type, const hicn_protocol_t *h, size_t *length)
-{
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
-}
-
-int
-ah_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+ah_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old, const hicn_faceid_t face_id,
+ u8 reset_pl)
{
- *header_length = AH_HDRLEN + (h->ah.payloadlen << 2);
+ /* Nothing to do on signature */
return HICN_LIB_ERROR_NONE;
}
int
-ah_get_header_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+ah_get_signature (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t **signature)
{
- size_t child_header_length = 0;
- int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
- if (rc < 0)
- return rc;
- *header_length = AH_HDRLEN + (h->ah.payloadlen << 2) + child_header_length;
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
+ *signature = ah->validationPayload;
return HICN_LIB_ERROR_NONE;
}
int
-ah_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
+ah_has_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, bool *flag)
{
- *signature = h->ah.validationPayload;
+ *flag = true;
return HICN_LIB_ERROR_NONE;
}
int
-ah_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
+ah_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
size_t *signature_size)
{
- *signature_size = h->ah.payloadlen << 2;
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
+ *signature_size = ah->payloadlen << 2;
return HICN_LIB_ERROR_NONE;
}
int
-ah_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
- const size_t signature_size)
+ah_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t signature_size)
{
- h->ah.payloadlen = (u8) (signature_size >> 2);
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
+ ah->payloadlen = signature_size >> 2;
return HICN_LIB_ERROR_NONE;
}
int
-ah_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h,
+ah_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
uint64_t signature_timestamp)
{
- uint64_t netwok_order_timestamp = htonll (signature_timestamp);
- memcpy (h->ah.timestamp_as_u8, &netwok_order_timestamp, sizeof (uint64_t));
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
+ uint64_t netwok_order_timestamp = hicn_net_to_host_64 (signature_timestamp);
+ memcpy (ah->timestamp_as_u8, &netwok_order_timestamp, sizeof (uint64_t));
return HICN_LIB_ERROR_NONE;
}
int
-ah_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h,
+ah_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
uint64_t *signature_timestamp)
{
- memcpy (signature_timestamp, h->ah.timestamp_as_u8, sizeof (uint64_t));
- *signature_timestamp = ntohll (*signature_timestamp);
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
+ memcpy (signature_timestamp, ah->timestamp_as_u8, sizeof (uint64_t));
+ *signature_timestamp = hicn_host_to_net_64 (*signature_timestamp);
return HICN_LIB_ERROR_NONE;
}
int
-ah_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h,
+ah_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
uint8_t validation_algorithm)
{
- h->ah.validationAlgorithm = validation_algorithm;
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
+ ah->validationAlgorithm = validation_algorithm;
return HICN_LIB_ERROR_NONE;
}
int
-ah_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
+ah_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
uint8_t *validation_algorithm)
{
- *validation_algorithm = h->ah.validationAlgorithm;
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
+ *validation_algorithm = ah->validationAlgorithm;
return HICN_LIB_ERROR_NONE;
}
int
-ah_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+ah_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t padding)
{
- h->ah.signatureGap = gap;
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
+ ah->signaturePadding = padding;
return HICN_LIB_ERROR_NONE;
}
int
-ah_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h, uint8_t *gap)
+ah_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t *padding)
{
- *gap = h->ah.signatureGap;
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
+ *padding = ah->signaturePadding;
return HICN_LIB_ERROR_NONE;
}
int
-ah_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id)
+ah_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t *key_id,
+ size_t size)
{
- memcpy (h->ah.keyId, key_id, sizeof (h->ah.keyId));
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
+ if (size != sizeof (ah->keyId))
+ return HICN_LIB_ERROR_INVALID_PARAMETER;
+
+ memcpy (ah->keyId, key_id, sizeof (ah->keyId));
return HICN_LIB_ERROR_NONE;
}
int
-ah_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
+ah_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t **key_id,
uint8_t *key_id_size)
{
- *key_id = h->ah.keyId;
- *key_id_size = sizeof (h->ah.keyId);
+ _ah_header_t *ah = pkbuf_get_ah (pkbuf);
+
+ *key_id = ah->keyId;
+ *key_id_size = sizeof (ah->keyId);
return HICN_LIB_ERROR_NONE;
}
-DECLARE_HICN_OPS (ah);
+DECLARE_HICN_OPS (ah, AH_HDRLEN);
/*
* fd.io coding-style-patch-verification: ON
diff --git a/lib/src/protocol/ah.h b/lib/src/protocol/ah.h
new file mode 100644
index 000000000..ee124f92a
--- /dev/null
+++ b/lib/src/protocol/ah.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file protocol/ah.h
+ * @brief AH packet header
+ */
+#ifndef HICN_PROTOCOL_AH_H
+#define HICN_PROTOCOL_AH_H
+
+#include <hicn/common.h>
+
+/*
+ * The TCP PSH flag is set to indicate TCP payload in fact contains a AH header
+ * with signature information for the packet
+ */
+#define AH_FLAG 0x10
+
+/*
+ * The length of the AH struct must be 44 bytes.
+ */
+#define EXPECTED_AH_HDRLEN 44
+
+typedef struct
+{
+ u8 nh; // To match with reserved in IPSEC AH
+ // Length of the signature field. Note that the signature might be smaller
+ // than the field: the actual size is computed from the field size and
+ // signaturePadding.
+ u8 payloadlen;
+ union
+ {
+ u16 reserved;
+
+ struct
+ {
+ u8 validationAlgorithm;
+ u8 signaturePadding;
+ };
+ };
+ union
+ {
+ struct
+ {
+ u32 spi;
+ u32 seq;
+ };
+ // Unix timestamp indicating when the signature has been calculated
+ u8 timestamp_as_u8[8];
+ u16 timestamp_as_u16[4];
+ u32 timestamp_as_u32[2];
+ };
+ // ICV would follow
+ u8 keyId[32]; // Hash of pub key
+ /* 44 B + validationPayload */
+ u8 validationPayload[0]; // Holds the signature
+} _ah_header_t;
+
+#define AH_HDRLEN sizeof (_ah_header_t)
+static_assert (EXPECTED_AH_HDRLEN == AH_HDRLEN,
+ "Size of AH Struct does not match its expected size.");
+
+#endif /* HICN_PROTOCOL_AH_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/icmp.c b/lib/src/protocol/icmp.c
index 5783cf52c..add871bcf 100644
--- a/lib/src/protocol/icmp.c
+++ b/lib/src/protocol/icmp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2023 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:
@@ -13,10 +13,11 @@
* limitations under the License.
*/
-#include <string.h>
-#include <hicn/protocol/icmp.h>
#include <hicn/error.h>
-#include <hicn/ops.h>
+#include <string.h>
+
+#include "icmp.h"
+#include "../ops.h"
DECLARE_get_interest_locator (icmp, UNEXPECTED);
DECLARE_set_interest_locator (icmp, UNEXPECTED);
@@ -24,81 +25,104 @@ DECLARE_get_interest_name (icmp, UNEXPECTED);
DECLARE_set_interest_name (icmp, UNEXPECTED);
DECLARE_get_interest_name_suffix (icmp, UNEXPECTED);
DECLARE_set_interest_name_suffix (icmp, UNEXPECTED);
-DECLARE_mark_packet_as_interest (icmp, UNEXPECTED);
-DECLARE_mark_packet_as_data (icmp, UNEXPECTED);
DECLARE_get_data_locator (icmp, UNEXPECTED);
DECLARE_set_data_locator (icmp, UNEXPECTED);
DECLARE_get_data_name (icmp, UNEXPECTED);
DECLARE_set_data_name (icmp, UNEXPECTED);
DECLARE_get_data_name_suffix (icmp, UNEXPECTED);
DECLARE_set_data_name_suffix (icmp, UNEXPECTED);
-DECLARE_get_data_pathlabel (icmp, UNEXPECTED);
-DECLARE_set_data_pathlabel (icmp, UNEXPECTED);
-DECLARE_update_data_pathlabel (icmp, UNEXPECTED);
+DECLARE_get_data_path_label (icmp, UNEXPECTED);
+DECLARE_set_data_path_label (icmp, UNEXPECTED);
+DECLARE_update_data_path_label (icmp, UNEXPECTED);
DECLARE_get_lifetime (icmp, UNEXPECTED);
DECLARE_set_lifetime (icmp, UNEXPECTED);
-DECLARE_get_length (icmp, UNEXPECTED);
-DECLARE_get_payload_length (icmp, UNEXPECTED);
-DECLARE_set_payload_length (icmp, UNEXPECTED);
+// DECLARE_get_payload_len (icmp, UNEXPECTED);
+DECLARE_set_payload_len (icmp, UNEXPECTED);
+DECLARE_get_payload_type (icmp, UNEXPECTED);
+DECLARE_set_payload_type (icmp, UNEXPECTED);
DECLARE_get_signature (icmp, UNEXPECTED);
+DECLARE_has_signature (icmp, UNEXPECTED);
+DECLARE_is_last_data (icmp, UNEXPECTED);
+DECLARE_set_last_data (icmp, UNEXPECTED);
int
-icmp_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
+icmp_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos)
{
- h->icmp = (_icmp_header_t){
+ pkbuf->icmp = pkbuf->len;
+ if (ICMP_HDRLEN > pkbuf->buffer_size - pkbuf->len)
+ return -1;
+ pkbuf->len += ICMP_HDRLEN;
+
+ _icmp_header_t *icmp = pkbuf_get_icmp (pkbuf);
+
+ *icmp = (_icmp_header_t){
.type = 0,
.code = 0,
.csum = 0,
};
- return HICN_LIB_ERROR_NONE; // CHILD_OPS(init_packet_header, type, h->icmp);
+ return CALL_CHILD (init_packet_header, pkbuf, pos);
}
int
-icmp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
+icmp_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
{
- h->icmp.csum = 0;
+ _icmp_header_t *icmp = pkbuf_get_icmp (pkbuf);
+
+ icmp->csum = 0;
- return CHILD_OPS (reset_interest_for_hash, type, h);
+ return CALL_CHILD (reset_interest_for_hash, pkbuf, pos);
}
int
-icmp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
+icmp_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
{
- h->icmp.csum = 0;
+ _icmp_header_t *icmp = pkbuf_get_icmp (pkbuf);
+
+ icmp->csum = 0;
- return CHILD_OPS (reset_data_for_hash, type, h);
+ return CALL_CHILD (reset_data_for_hash, pkbuf, pos);
}
int
-icmp_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
- size_t payload_length)
+icmp_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- // h->icmp.csum = 0;
- // h->icmp.csum = csum(h->bytes, TCP_HDRLEN + payload_length,
+ // icmp->csum = 0;
+ // icmp->csum = csum(h->bytes, TCP_HDRLEN + payload_len,
// ~partial_csum);
//
- // return CHILD_OPS(update_checksums, type, h->icmp, 0, payload_length);
+ // return CALL_CHILD(update_checksums, pkbuf, pos->icmp, 0,
+ // payload_len);
}
int
-icmp_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
- size_t payload_length)
+icmp_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf,
+ size_t pos, u16 *old_val, u16 *new_val,
+ u8 size, bool skip_first)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- // if (csum(h->bytes, TCP_HDRLEN + payload_length, ~partial_csum) != 0)
+}
+
+int
+icmp_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
+{
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ // if (csum(h->bytes, TCP_HDRLEN + payload_len, ~partial_csum) != 0)
// return HICN_LIB_ERROR_CORRUPTED_PACKET;
- // return CHILD_OPS(verify_checksums, type, h->icmp, 0, payload_length);
+ // return CALL_CHILD(verify_checksums, pkbuf, pos->icmp, 0,
+ // payload_len);
}
int
-icmp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new,
- ip46_address_t *addr_old)
+icmp_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- // u16 *icmp_checksum = &(h->icmp.csum);
+ // u16 *icmp_checksum = &(icmp->csum);
//
// /*
// * Padding fields are set to zero so we can apply checksum on the
@@ -119,12 +143,13 @@ icmp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
}
int
-icmp_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old,
- const hicn_faceid_t face_id, u8 reset_pl)
+icmp_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old, const hicn_faceid_t face_id,
+ u8 reset_pl)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- // u16 *icmp_checksum = &(h->icmp.csum);
+ // u16 *icmp_checksum = &(icmp->csum);
//
// /*
// * Padding fields are set to zero so we can apply checksum on the
@@ -139,9 +164,9 @@ icmp_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
// csum = ip_csum_add_even (csum, addr_new->ip6.as_u64[0]);
// csum = ip_csum_add_even (csum, addr_new->ip6.as_u64[1]);
//
- // csum = ip_csum_sub_even (csum, h->icmp.pathlabel);
- // icmp_update_data_pathlabel(type, h, face_id);
- // csum = ip_csum_add_even (csum, h->icmp.pathlabel);
+ // csum = ip_csum_sub_even (csum, icmp->path_label);
+ // icmp_update_data_path_label(pkbuf, pos, face_id);
+ // csum = ip_csum_add_even (csum, icmp->path_label);
//
// *icmp_checksum = ip_csum_fold (csum);
//
@@ -149,95 +174,93 @@ icmp_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
}
int
-icmp_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+icmp_get_type (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ hicn_packet_type_t *type)
{
- *header_length = ICMP_HDRLEN;
+ *type = HICN_PACKET_TYPE_MAPME;
return HICN_LIB_ERROR_NONE;
}
int
-icmp_get_header_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+icmp_set_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_packet_type_t type)
{
- size_t child_header_length = 0;
- int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
- if (rc < 0)
- return rc;
-
- *header_length = ICMP_HDRLEN + child_header_length;
- return HICN_LIB_ERROR_NONE;
+ return CALL_CHILD (set_type, pkbuf, pos, type);
}
int
-icmp_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
+icmp_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
size_t *signature_size)
{
- return CHILD_OPS (get_signature_size, type, h, signature_size);
+ return CALL_CHILD (get_signature_size, pkbuf, pos, signature_size);
}
int
-icmp_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
+icmp_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
size_t signature_size)
{
- return CHILD_OPS (set_signature_size, type, h, signature_size);
+ return CALL_CHILD (set_signature_size, pkbuf, pos, signature_size);
}
int
-icmp_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+icmp_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t padding)
{
- return CHILD_OPS (set_signature_gap, type, h, gap);
+ return CALL_CHILD (set_signature_padding, pkbuf, pos, padding);
}
int
-icmp_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *gap)
+icmp_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t *padding)
{
- return CHILD_OPS (get_signature_gap, type, h, gap);
+ return CALL_CHILD (get_signature_padding, pkbuf, pos, padding);
}
int
-icmp_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h,
+icmp_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
uint64_t signature_timestamp)
{
- return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
+ return CALL_CHILD (set_signature_timestamp, pkbuf, pos, signature_timestamp);
}
int
-icmp_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h,
+icmp_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
uint64_t *signature_timestamp)
{
- return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
+ return CALL_CHILD (get_signature_timestamp, pkbuf, pos, signature_timestamp);
}
int
-icmp_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h,
+icmp_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
uint8_t validation_algorithm)
{
- return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
+ return CALL_CHILD (set_validation_algorithm, pkbuf, pos,
+ validation_algorithm);
}
int
-icmp_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
+icmp_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
uint8_t *validation_algorithm)
{
- return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
+ return CALL_CHILD (get_validation_algorithm, pkbuf, pos,
+ validation_algorithm);
}
int
-icmp_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id)
+icmp_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t *key_id, size_t key_len)
{
- return CHILD_OPS (set_key_id, type, h, key_id);
+ return CALL_CHILD (set_key_id, pkbuf, pos, key_id, key_len);
}
int
-icmp_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
- uint8_t *key_id_size)
+icmp_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t **key_id, uint8_t *key_id_size)
{
- return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
+ return CALL_CHILD (get_key_id, pkbuf, pos, key_id, key_id_size);
}
-DECLARE_HICN_OPS (icmp);
+DECLARE_HICN_OPS (icmp, ICMP_HDRLEN);
/*
* fd.io coding-style-patch-verification: ON
diff --git a/lib/src/protocol/icmp.h b/lib/src/protocol/icmp.h
new file mode 100644
index 000000000..6cbba6398
--- /dev/null
+++ b/lib/src/protocol/icmp.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file protocol/icmp.h
+ * @brief ICMP packet header
+ */
+#ifndef HICN_PROTOCOL_ICMP_H
+#define HICN_PROTOCOL_ICMP_H
+
+#include <hicn/common.h>
+
+/*
+ * The length of the ICMP header struct must be 4 bytes.
+ */
+#define EXPECTED_ICMP_HDRLEN 4
+
+typedef struct
+{
+ u8 type;
+ u8 code;
+ u16 csum;
+} _icmp_header_t;
+
+#define ICMP_HDRLEN sizeof (_icmp_header_t)
+static_assert (EXPECTED_ICMP_HDRLEN == ICMP_HDRLEN,
+ "Size of ICMP struct does not match its expected size.");
+
+/*
+ * The length of the ICMPWLDR header struct must be 4 bytes.
+ */
+#define EXPECTED_ICMPWLDR_HDRLEN 8
+
+typedef struct
+{
+ u8 type;
+ u8 code;
+ u16 csum;
+ union
+ {
+ struct
+ {
+ u16 id;
+ u16 sequence;
+ } echo; /* echo datagram */
+ u32 gateway; /* gateway address */
+ struct
+ {
+ u16 _unused;
+ u16 mtu;
+ } frag; /* path mtu discovery */
+ struct
+ {
+ u16 expected_lbl;
+ u16 received_lbl;
+ } wldr_notification_lbl;
+ };
+} _icmp_wldr_header_t;
+
+#define ICMPWLDR_HDRLEN sizeof (_icmp_wldr_header_t)
+static_assert (EXPECTED_ICMPWLDR_HDRLEN == ICMPWLDR_HDRLEN,
+ "Size of ICMPWLDR struct does not match its expected size.");
+
+#endif /* HICN_PROTOCOL_ICMP_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/icmprd.h b/lib/src/protocol/icmprd.h
new file mode 100644
index 000000000..7edff8111
--- /dev/null
+++ b/lib/src/protocol/icmprd.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file protocol/icmp-rd.c
+ * @brief hICN operations for ICMP Redirect header
+ */
+#ifndef HICN_PROTOCOL_ICMPRD_H
+#define HICN_PROTOCOL_ICMPRD_H
+
+#include <hicn/common.h>
+#include "ipv4.h"
+
+/*
+ * The length of the ICMPRD4 header struct must be 92 bytes.
+ */
+#define EXPECTED_ICMPRD4_HDRLEN 92
+
+typedef struct
+{
+ u8 type;
+ u8 code;
+ u16 csum;
+ ipv4_address_t ip;
+ _ipv4_header_t iph;
+ u8 data[64];
+} _icmprd4_header_t;
+
+#define ICMPRD4_HDRLEN sizeof (_icmprd4_header_t)
+static_assert (EXPECTED_ICMPRD4_HDRLEN == ICMPRD4_HDRLEN,
+ "Size of ICMPWLDR struct does not match its expected size.");
+
+/*
+ * The length of the ICMPRD header struct must be 40 bytes.
+ */
+#define EXPECTED_ICMPRD_HDRLEN 40
+
+typedef struct
+{
+ u8 type;
+ u8 code;
+ u16 csum;
+ u32 res;
+ ipv6_address_t tgt;
+ ipv6_address_t dst;
+} _icmprd_header_t;
+
+#define ICMPRD_HDRLEN sizeof (_icmprd_header_t)
+static_assert (EXPECTED_ICMPRD_HDRLEN == ICMPRD_HDRLEN,
+ "Size of ICMPWLDR struct does not match its expected size.");
+
+#endif /* HICN_PROTOCOL_ICMPRD_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/ipv4.c b/lib/src/protocol/ipv4.c
index cf50f9996..daa5a706a 100644
--- a/lib/src/protocol/ipv4.c
+++ b/lib/src/protocol/ipv4.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -14,7 +14,7 @@
*/
/**
- * @file protocol/ipv4.c
+ * @file protocol/ipv4->c
* @brief hICN operations for IPv4 header
*
* NOTE: IPv4 options (affecting the header size) are currently not supported.
@@ -28,241 +28,262 @@
#include <string.h>
#include <hicn/error.h>
-#include <hicn/ops.h>
#include <hicn/common.h>
-#include <hicn/header.h>
-#include <hicn/protocol/ipv4.h>
-typedef unsigned short u_short;
-int ipv4_get_payload_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *payload_length);
+#include "../ops.h"
+#include "ipv4.h"
+
+#define UINT16_T_MASK 0x0000ffff // 1111 1111 1111 1111
+
+#define ipv4_get_payload_len(pkbuf, ipv4) htons (ipv4->len - pkbuf->payload)
int
-ipv4_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
+ipv4_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos)
{
- size_t total_header_length;
- int rc =
- hicn_ops_vft[type.l1]->get_header_length (type, h, &total_header_length);
- if (rc < 0)
- return rc;
+ assert (pkbuf->len == 0);
+ if (IPV4_HDRLEN > pkbuf->buffer_size - pkbuf->len)
+ return -1;
+ pkbuf->len += IPV4_HDRLEN;
- h->ipv4 = (_ipv4_header_t){
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
+ hicn_packet_format_t format = hicn_packet_get_format (pkbuf);
+
+ size_t header_len;
+ hicn_packet_get_header_length_from_format (pkbuf->format, &header_len);
+
+ /* We initialize the len considering an empty payload */
+ *ipv4 = (_ipv4_header_t){
.version_ihl = (IPV4_DEFAULT_VERSION << 4) | (0x0f & IPV4_DEFAULT_IHL),
.tos = IPV4_DEFAULT_TOS,
- .len = htons ((u16) total_header_length),
+ .len = htons (header_len),
.id = htons (IPV4_DEFAULT_ID),
.frag_off = htons (IPV4_DEFAULT_FRAG_OFF),
.ttl = HICN_DEFAULT_TTL,
- .protocol = type.l2,
+ .protocol = HICN_PACKET_FORMAT_GET (format, pos + 1),
.csum = 0,
.saddr.as_u32 = 0,
.daddr.as_u32 = 0,
};
- return CHILD_OPS (init_packet_header, type, h);
+ return CALL_CHILD (init_packet_header, pkbuf, pos);
}
int
-ipv4_get_interest_locator (hicn_type_t type, const hicn_protocol_t *h,
- ip46_address_t *ip_address)
+ipv4_get_interest_locator (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_ip_address_t *ip_address)
{
- ip_address->ip4 = h->ipv4.saddr;
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
+ ip_address->v4 = ipv4->saddr;
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_set_interest_locator (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *ip_address)
+ipv4_set_interest_locator (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *ip_address)
{
- h->ipv4.saddr = ip_address->ip4;
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
+ ipv4->saddr = ip_address->v4;
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_get_interest_name (hicn_type_t type, const hicn_protocol_t *h,
+ipv4_get_interest_name (const hicn_packet_buffer_t *pkbuf, size_t pos,
hicn_name_t *name)
{
- name->ip4.prefix_as_ip4 = h->ipv4.daddr;
-#ifndef HICN_VPP_PLUGIN
- name->type = HNT_CONTIGUOUS_V4;
- name->len = HICN_V4_NAME_LEN;
-#endif /* HICN_VPP_PLUGIN */
- return CHILD_OPS (get_interest_name_suffix, type, h, &(name->ip4.suffix));
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
+ name->prefix.v4 = ipv4->daddr;
+ return CALL_CHILD (get_interest_name_suffix, pkbuf, pos, &(name->suffix));
}
int
-ipv4_set_interest_name (hicn_type_t type, hicn_protocol_t *h,
+ipv4_set_interest_name (const hicn_packet_buffer_t *pkbuf, size_t pos,
const hicn_name_t *name)
{
- h->ipv4.daddr = name->ip4.prefix_as_ip4;
- return CHILD_OPS (set_interest_name_suffix, type, h, &(name->ip4.suffix));
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
+ ipv4->daddr = name->prefix.v4;
+ return CALL_CHILD (set_interest_name_suffix, pkbuf, pos, &(name->suffix));
}
int
-ipv4_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ipv4_get_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
hicn_name_suffix_t *suffix)
{
- return CHILD_OPS (get_interest_name_suffix, type, h, suffix);
+ return CALL_CHILD (get_interest_name_suffix, pkbuf, pos, suffix);
}
int
-ipv4_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ipv4_set_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
const hicn_name_suffix_t *suffix)
{
- return CHILD_OPS (set_interest_name_suffix, type, h, suffix);
+ return CALL_CHILD (set_interest_name_suffix, pkbuf, pos, suffix);
}
int
-ipv4_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h)
+ipv4_get_type (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ hicn_packet_type_t *type)
{
- return CHILD_OPS (mark_packet_as_interest, type, h);
+ return CALL_CHILD (get_type, pkbuf, pos, type);
}
int
-ipv4_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h)
+ipv4_set_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_packet_type_t type)
{
- return CHILD_OPS (mark_packet_as_data, type, h);
+ return CALL_CHILD (set_type, pkbuf, pos, type);
}
int
-ipv4_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
+ipv4_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
{
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
/* Sets everything to 0 up to IP destination address */
- memset (&(h->ipv4), 0, 16);
+ memset (ipv4, 0, 16);
- return CHILD_OPS (reset_interest_for_hash, type, h);
+ return CALL_CHILD (reset_interest_for_hash, pkbuf, pos);
}
int
-ipv4_get_data_locator (hicn_type_t type, const hicn_protocol_t *h,
- ip46_address_t *ip_address)
+ipv4_get_data_locator (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_ip_address_t *ip_address)
{
- ip_address->ip4 = h->ipv4.daddr;
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
+ ip_address->v4 = ipv4->daddr;
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_set_data_locator (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *ip_address)
+ipv4_set_data_locator (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *ip_address)
{
- h->ipv4.daddr = ip_address->ip4;
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
+ ipv4->daddr = ip_address->v4;
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_get_data_name (hicn_type_t type, const hicn_protocol_t *h,
+ipv4_get_data_name (const hicn_packet_buffer_t *pkbuf, size_t pos,
hicn_name_t *name)
{
- name->ip4.prefix_as_ip4 = h->ipv4.saddr;
-#ifndef HICN_VPP_PLUGIN
- name->type = HNT_CONTIGUOUS_V4;
- name->len = HICN_V4_NAME_LEN;
-#endif /* HICN_VPP_PLUGIN */
- return CHILD_OPS (get_data_name_suffix, type, h, &(name->ip4.suffix));
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
+ name->prefix.v4 = ipv4->saddr;
+ return CALL_CHILD (get_data_name_suffix, pkbuf, pos, &(name->suffix));
}
int
-ipv4_set_data_name (hicn_type_t type, hicn_protocol_t *h,
+ipv4_set_data_name (const hicn_packet_buffer_t *pkbuf, size_t pos,
const hicn_name_t *name)
{
- h->ipv4.saddr = name->ip4.prefix_as_ip4;
- return CHILD_OPS (set_data_name_suffix, type, h, &(name->ip4.suffix));
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
+ ipv4->saddr = name->prefix.v4;
+ return CALL_CHILD (set_data_name_suffix, pkbuf, pos, &(name->suffix));
}
int
-ipv4_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ipv4_get_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
hicn_name_suffix_t *suffix)
{
- return CHILD_OPS (get_data_name_suffix, type, h, suffix);
+ return CALL_CHILD (get_data_name_suffix, pkbuf, pos, suffix);
}
int
-ipv4_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ipv4_set_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
const hicn_name_suffix_t *suffix)
{
- return CHILD_OPS (set_data_name_suffix, type, h, suffix);
+ return CALL_CHILD (set_data_name_suffix, pkbuf, pos, suffix);
}
int
-ipv4_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h,
- u32 *pathlabel)
+ipv4_get_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_path_label_t *path_label)
{
- return CHILD_OPS (get_data_pathlabel, type, h, pathlabel);
+ return CALL_CHILD (get_data_path_label, pkbuf, pos, path_label);
}
int
-ipv4_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
- const u32 pathlabel)
+ipv4_set_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_path_label_t path_label)
{
- return CHILD_OPS (set_data_pathlabel, type, h, pathlabel);
+ return CALL_CHILD (set_data_path_label, pkbuf, pos, path_label);
}
int
-ipv4_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
- const hicn_faceid_t face_id)
+ipv4_update_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_faceid_t face_id)
{
- return CHILD_OPS (update_data_pathlabel, type, h, face_id);
+ return CALL_CHILD (update_data_path_label, pkbuf, pos, face_id);
}
int
-ipv4_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
+ipv4_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
{
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
/* Sets everything to 0 up to source address */
- memset (&h->ipv4, 0, 12);
+ memset (ipv4, 0, 12);
/* Clears destination address */
- memset (&(h->ipv4.daddr), 0, 4);
+ memset (&(ipv4->daddr), 0, 4);
- return CHILD_OPS (reset_data_for_hash, type, h);
+ return CALL_CHILD (reset_data_for_hash, pkbuf, pos);
}
int
-ipv4_get_lifetime (hicn_type_t type, const hicn_protocol_t *h,
+ipv4_get_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos,
hicn_lifetime_t *lifetime)
{
- return CHILD_OPS (get_lifetime, type, h, lifetime);
+ return CALL_CHILD (get_lifetime, pkbuf, pos, lifetime);
}
int
-ipv4_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
+ipv4_set_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos,
const hicn_lifetime_t lifetime)
{
- return CHILD_OPS (set_lifetime, type, h, lifetime);
+ return CALL_CHILD (set_lifetime, pkbuf, pos, lifetime);
}
int
-ipv4_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
- size_t payload_length)
+ipv4_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
{
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
/*
* Checksum field is not accounted for in lower layers, so we can compute
* them in any order. Note that it is only a header checksum.
*/
- h->ipv4.csum = 0;
- h->ipv4.csum = csum (h, IPV4_HDRLEN, 0);
+ ipv4->csum = 0;
+ ipv4->csum = csum (pkbuf_get_header (pkbuf), IPV4_HDRLEN, 0);
- /* Retrieve payload length if not specified, as it is not available later */
- if (payload_length == 0)
+ /* Retrieve payload len if not specified, as it is not available later */
+ if (payload_len == 0)
{
- int rc = ipv4_get_payload_length (type, h, &payload_length);
- if (rc < 0)
- return rc;
+ payload_len = ipv4_get_payload_len (pkbuf, ipv4);
}
- /* Ignore the payload if payload_length = ~0 */
- if (payload_length == ~0)
+ /* Ignore the payload if payload_len = ~0 */
+ if (payload_len == ~0)
{
- payload_length = 0;
+ payload_len = 0;
}
/* Build pseudo-header */
ipv4_pseudo_header_t psh;
- psh.ip_src = h->ipv4.saddr;
- psh.ip_dst = h->ipv4.daddr;
+ psh.ip_src = ipv4->saddr;
+ psh.ip_dst = ipv4->daddr;
/* Size is u32 and not u16, we cannot copy and need to care about endianness
*/
- psh.size = htons (ntohs (h->ipv4.len) - (u16) IPV4_HDRLEN);
+ psh.size = htons (ntohs (ipv4->len) - (u16) IPV4_HDRLEN);
psh.zero = 0;
- psh.protocol = (u8) h->ipv4.protocol;
+ psh.protocol = (u8) ipv4->protocol;
/* Compute partial checksum based on pseudo-header */
if (partial_csum != 0)
@@ -271,217 +292,245 @@ ipv4_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
}
partial_csum = csum (&psh, IPV4_PSHDRLEN, partial_csum);
- return CHILD_OPS (update_checksums, type, h, partial_csum, payload_length);
+ return CALL_CHILD (update_checksums, pkbuf, pos, partial_csum, payload_len);
+}
+
+int
+ipv4_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf,
+ size_t pos, u16 *old_val, u16 *new_val,
+ u8 size, bool skip_first)
+{
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
+ /* We update the child first */
+ int rc = CALL_CHILD (update_checksums_incremental, pkbuf, pos, old_val,
+ new_val, size, false);
+ if (rc < 0)
+ return rc;
+
+ if (!skip_first)
+ {
+ for (uint8_t i = 0; i < size; i++)
+ {
+ uint16_t old_csum = ~ipv4->csum;
+ uint16_t not_old_val = ~(*old_val);
+ uint32_t sum = (uint32_t) old_csum + not_old_val + *new_val;
+
+ while (sum >> 16)
+ {
+ sum = (sum >> 16) + (sum & UINT16_T_MASK);
+ }
+
+ ipv4->csum = ~sum;
+ ++old_val;
+ ++new_val;
+ }
+ }
+
+ return HICN_LIB_ERROR_NONE;
}
int
-ipv4_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
- size_t payload_length)
+ipv4_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
{
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
/*
* Checksum field is not accounted for in lower layers, so we can compute
* them in any order. Note that it is only a header checksum.
*/
- if (csum (h, IPV4_HDRLEN, 0) != 0)
+ if (csum (pkbuf_get_header (pkbuf), IPV4_HDRLEN, 0) != 0)
return HICN_LIB_ERROR_CORRUPTED_PACKET;
- /* Retrieve payload length if not specified, as it is not available later */
- if (payload_length == 0)
+ /* Retrieve payload len if not specified, as it is not available later */
+ if (payload_len == 0)
{
- int rc = ipv4_get_payload_length (type, h, &payload_length);
- if (rc < 0)
- return rc;
+ payload_len = ipv4_get_payload_len (pkbuf, ipv4);
}
/* Build pseudo-header */
ipv4_pseudo_header_t psh;
- psh.ip_src = h->ipv4.saddr;
- psh.ip_dst = h->ipv4.daddr;
+ psh.ip_src = ipv4->saddr;
+ psh.ip_dst = ipv4->daddr;
/* Size is u32 and not u16, we cannot copy and need to care about endianness
*/
- psh.size = htons (ntohs (h->ipv4.len) - (u16) IPV4_HDRLEN);
+ psh.size = htons (ntohs (ipv4->len) - (u16) IPV4_HDRLEN);
psh.zero = 0;
- psh.protocol = (u8) h->ipv4.protocol;
+ psh.protocol = (u8) ipv4->protocol;
/* Compute partial checksum based on pseudo-header */
partial_csum = csum (&psh, IPV4_PSHDRLEN, 0);
- return CHILD_OPS (update_checksums, type, h, partial_csum, payload_length);
+ return CALL_CHILD (verify_checksums, pkbuf, pos, partial_csum, payload_len);
}
int
-ipv4_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new,
- ip46_address_t *addr_old)
+ipv4_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old)
{
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
// ASSERT(addr_old == NULL);
- addr_old->ip4 = h->ipv4.saddr;
+ addr_old->v4 = ipv4->saddr;
addr_old->pad[0] = 0;
addr_old->pad[1] = 0;
addr_old->pad[2] = 0;
- h->ipv4.saddr = addr_new->ip4;
- h->ipv4.csum = 0;
- h->ipv4.csum = csum (&h->ipv4, IPV4_HDRLEN, 0);
+ ipv4->saddr = addr_new->v4;
+ ipv4->csum = 0;
+ ipv4->csum = csum (&ipv4, IPV4_HDRLEN, 0);
- return CHILD_OPS (rewrite_interest, type, h, addr_new, addr_old);
+ return CALL_CHILD (rewrite_interest, pkbuf, pos, addr_new, addr_old);
}
int
-ipv4_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old,
- const hicn_faceid_t face_id, u8 reset_pl)
+ipv4_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old, const hicn_faceid_t face_id,
+ u8 reset_pl)
{
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
// ASSERT(addr_old == NULL);
- addr_old->ip4 = h->ipv4.daddr;
+ addr_old->v4 = ipv4->daddr;
addr_old->pad[0] = 0;
addr_old->pad[1] = 0;
addr_old->pad[2] = 0;
- h->ipv4.daddr = addr_new->ip4;
- h->ipv4.csum = 0;
- h->ipv4.csum = csum (&h->ipv4, IPV4_HDRLEN, 0);
+ ipv4->daddr = addr_new->v4;
+ ipv4->csum = 0;
+ ipv4->csum = csum (&ipv4, IPV4_HDRLEN, 0);
- return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id,
- reset_pl);
+ return CALL_CHILD (rewrite_data, pkbuf, pos, addr_new, addr_old, face_id,
+ reset_pl);
}
int
-ipv4_get_current_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+ipv4_set_payload_len (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t payload_len)
{
- *header_length = IPV4_HDRLEN;
+ _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf);
+
+ size_t child_header_len = hicn_ops_vft[pos + 1]->header_len;
+
+ ipv4->len = htons ((u16) (payload_len + IPV4_HDRLEN + child_header_len));
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_get_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+ipv4_get_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_payload_type_t *payload_type)
{
- *header_length = h->ipv4.len;
- return HICN_LIB_ERROR_NONE;
+ return CALL_CHILD (get_payload_type, pkbuf, pos, payload_type);
}
int
-ipv4_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+ipv4_set_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_payload_type_t payload_type)
{
- *header_length = IPV4_HDRLEN;
- return HICN_LIB_ERROR_NONE;
+ return CALL_CHILD (set_payload_type, pkbuf, pos, payload_type);
}
int
-ipv4_get_header_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+ipv4_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t *signature_size)
{
- size_t child_header_length = 0;
- int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
- if (rc < 0)
- return rc;
- *header_length = IPV4_HDRLEN + child_header_length;
- return HICN_LIB_ERROR_NONE;
+ return CALL_CHILD (get_signature_size, pkbuf, pos, signature_size);
}
int
-ipv4_get_payload_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *payload_length)
+ipv4_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t signature_size)
{
- size_t child_header_length;
- int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
- if (rc < 0)
- return rc;
- *payload_length = htons (h->ipv4.len) - IPV4_HDRLEN - child_header_length;
- return HICN_LIB_ERROR_NONE;
+ return CALL_CHILD (set_signature_size, pkbuf, pos, signature_size);
}
int
-ipv4_set_payload_length (hicn_type_t type, hicn_protocol_t *h,
- size_t payload_length)
+ipv4_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t padding)
{
- size_t child_header_length;
- int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
- if (rc < 0)
- return rc;
- h->ipv4.len =
- htons ((u_short) (payload_length + IPV4_HDRLEN + child_header_length));
- return HICN_LIB_ERROR_NONE;
+ return CALL_CHILD (set_signature_padding, pkbuf, pos, padding);
}
int
-ipv4_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
- size_t *signature_size)
+ipv4_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t *padding)
{
- return CHILD_OPS (get_signature_size, type, h, signature_size);
+ return CALL_CHILD (get_signature_padding, pkbuf, pos, padding);
}
int
-ipv4_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
- size_t signature_size)
+ipv4_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint64_t signature_timestamp)
{
- return CHILD_OPS (set_signature_size, type, h, signature_size);
+ return CALL_CHILD (set_signature_timestamp, pkbuf, pos, signature_timestamp);
}
int
-ipv4_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+ipv4_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint64_t *signature_timestamp)
{
- return CHILD_OPS (set_signature_gap, type, h, gap);
+ return CALL_CHILD (get_signature_timestamp, pkbuf, pos, signature_timestamp);
}
int
-ipv4_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *gap)
+ipv4_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t validation_algorithm)
{
- return CHILD_OPS (get_signature_gap, type, h, gap);
+ return CALL_CHILD (set_validation_algorithm, pkbuf, pos,
+ validation_algorithm);
}
int
-ipv4_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h,
- uint64_t signature_timestamp)
+ipv4_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t *validation_algorithm)
{
- return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
+ return CALL_CHILD (get_validation_algorithm, pkbuf, pos,
+ validation_algorithm);
}
int
-ipv4_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h,
- uint64_t *signature_timestamp)
+ipv4_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t *key_id, size_t key_len)
{
- return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
+ return CALL_CHILD (set_key_id, pkbuf, pos, key_id, key_len);
}
int
-ipv4_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h,
- uint8_t validation_algorithm)
+ipv4_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t **key_id, uint8_t *key_id_size)
{
- return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
+ return CALL_CHILD (get_key_id, pkbuf, pos, key_id, key_id_size);
}
int
-ipv4_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *validation_algorithm)
+ipv4_get_signature (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t **signature)
{
- return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
+ return CALL_CHILD (get_signature, pkbuf, pos, signature);
}
int
-ipv4_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id)
+ipv4_has_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, bool *flag)
{
- return CHILD_OPS (set_key_id, type, h, key_id);
+ return CALL_CHILD (has_signature, pkbuf, pos, flag);
}
int
-ipv4_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
- uint8_t *key_id_size)
+ipv4_is_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos, int *is_last)
{
- return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
+ return CALL_CHILD (is_last_data, pkbuf, pos, is_last);
}
int
-ipv4_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
+ipv4_set_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos)
{
- return CHILD_OPS (get_signature, type, h, signature);
+ return CALL_CHILD (set_last_data, pkbuf, pos);
}
-DECLARE_HICN_OPS (ipv4);
+DECLARE_HICN_OPS (ipv4, IPV4_HDRLEN);
/*
* fd.io coding-style-patch-verification: ON
diff --git a/lib/src/protocol/ipv4.h b/lib/src/protocol/ipv4.h
new file mode 100644
index 000000000..5d729b955
--- /dev/null
+++ b/lib/src/protocol/ipv4.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HICN_PROTOCOL_IPV4
+#define HICN_PROTOCOL_IPV4
+
+#include <hicn/util/ip_address.h>
+
+#include <hicn/base.h>
+#include <hicn/common.h>
+
+/* Headers were adapted from linux' definitions in netinet/ip.h */
+
+/*
+ * The length of the IPV4 header struct must be 20 bytes.
+ */
+#define EXPECTED_IPV4_HDRLEN 20
+
+typedef struct
+{
+ union
+ {
+ struct
+ {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ u8 ihl : 4;
+ u8 version : 4;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ u8 version : 4;
+ u8 ihl : 4;
+#else
+#error "Unsupported endianness"
+#endif
+ };
+
+ u8 version_ihl;
+ };
+ u8 tos;
+
+ /*
+ * This is the total length of the IP packet, including the IP header.
+ * NOTE: vriable len header size is currently not supported by the lib.
+ */
+ u16 len;
+
+ u16 id;
+ u16 frag_off;
+ u8 ttl;
+ u8 protocol;
+ u16 csum;
+ ipv4_address_t saddr;
+ ipv4_address_t daddr;
+} _ipv4_header_t;
+
+#define ipv4_header_bytes(ipv4_header) \
+ (sizeof (u32) * (ipv4_header->version_ihl & 0xf))
+
+#define IPV4_HDRLEN sizeof (_ipv4_header_t)
+static_assert (EXPECTED_IPV4_HDRLEN == IPV4_HDRLEN,
+ "Size of IPV4 struct does not match its expected size.");
+
+/*
+ * The length of the IPV4 pseudo header struct must be 12 bytes.
+ */
+#define EXPECTED_IPV4_PSHDRLEN 12
+
+typedef struct
+{
+ ipv4_address_t ip_src;
+ ipv4_address_t ip_dst;
+ u8 zero;
+ u8 protocol;
+ u16 size;
+} ipv4_pseudo_header_t;
+
+#define IPV4_PSHDRLEN sizeof (ipv4_pseudo_header_t)
+static_assert (EXPECTED_IPV4_PSHDRLEN == IPV4_PSHDRLEN,
+ "Size of IPV4_PSHDR struct does not match its expected size.");
+
+/* Default field values */
+#define IPV4_DEFAULT_VERSION 4
+#define IPV4_DEFAULT_IHL 5
+#define IPV4_DEFAULT_TOS 0
+#define IPV4_DEFAULT_PAYLOAD_LENGTH 0
+#define IPV4_DEFAULT_ID 300
+#define IPV4_DEFAULT_FRAG_OFF 0x000
+#define IPV4_DEFAULT_TTL 64
+#define IPV4_DEFAULT_PROTOCOL IPPROTO_TCP
+#define IPV4_DEFAULT_SRC_IP 0, 0, 0, 0
+#define IPV4_DEFAULT_DST_IP 0, 0, 0, 0
+
+#endif /* HICN_PROTOCOL_IPV4 */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/ipv6.c b/lib/src/protocol/ipv6.c
index 7ac55b2be..c5fa643aa 100644
--- a/lib/src/protocol/ipv6.c
+++ b/lib/src/protocol/ipv6.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -17,224 +17,252 @@
#include <string.h>
#include <hicn/common.h>
#include <hicn/error.h>
-#include <hicn/ops.h>
+
+#include "ipv6.h"
+#include "../ops.h"
typedef unsigned short u_short;
-int ipv6_get_payload_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *payload_length);
+
+#ifdef OPAQUE_IP
+#define GET_IPV6_HEADER(pkbuf) \
+ (_ipv6_header_t *) ((pkbuf)->header + (pkbuf)->ipv6)
+#else
+#define GET_IPV6_HEADER(pkbuf) (_ipv6_header_t *) ((pkbuf)->header)
+#endif /* OPAQUE_IP */
int
-ipv6_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
+ipv6_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos)
{
- size_t total_header_length;
- int rc = CHILD_OPS (get_header_length, type, h, &total_header_length);
- if (rc < 0)
- return rc;
+ assert (pkbuf->len == 0);
+ if (IPV6_HDRLEN > pkbuf->buffer_size - pkbuf->len)
+ return -1;
+ pkbuf->len += IPV6_HDRLEN;
+
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
- /* *INDENT-OFF* */
- h->ipv6 = (_ipv6_header_t){
- .saddr = { { 0 } },
- .daddr = { { 0 } },
+ hicn_packet_format_t format = hicn_packet_get_format (pkbuf);
+
+ size_t header_len;
+ hicn_packet_get_header_length_from_format (pkbuf->format, &header_len);
+
+ /* clang-format off */
+ *ipv6 = (_ipv6_header_t){
+ .saddr = IP6_ADDRESS_EMPTY,
+ .daddr = IP6_ADDRESS_EMPTY,
.version_class_flow = htonl ((IPV6_DEFAULT_VERSION << 28) |
(IPV6_DEFAULT_TRAFFIC_CLASS << 20) |
(IPV6_DEFAULT_FLOW_LABEL & 0xfffff)),
- .len = htons ((u16) total_header_length),
- .nxt = type.l2,
+ .len = htons(header_len - IPV6_HDRLEN),
+ .nxt = HICN_PACKET_FORMAT_GET(format, pos+1),
.hlim = HICN_DEFAULT_TTL,
};
- /* *INDENT-ON* */
- return CHILD_OPS (init_packet_header, type, h);
+ /* clang-format on */
+ return CALL_CHILD (init_packet_header, pkbuf, pos);
}
int
-ipv6_get_interest_locator (hicn_type_t type, const hicn_protocol_t *h,
- ip46_address_t *ip_address)
+ipv6_get_interest_locator (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_ip_address_t *ip_address)
{
- ip_address->ip6 = h->ipv6.saddr;
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
+ ip_address->v6 = ipv6->saddr;
return HICN_LIB_ERROR_NONE;
}
int
-ipv6_set_interest_locator (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *ip_address)
+ipv6_set_interest_locator (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *ip_address)
{
- h->ipv6.saddr = ip_address->ip6;
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
+ ipv6->saddr = ip_address->v6;
return HICN_LIB_ERROR_NONE;
}
int
-ipv6_get_interest_name (hicn_type_t type, const hicn_protocol_t *h,
+ipv6_get_interest_name (const hicn_packet_buffer_t *pkbuf, size_t pos,
hicn_name_t *name)
{
- name->ip6.prefix_as_ip6 = h->ipv6.daddr;
-#ifndef HICN_VPP_PLUGIN
- name->type = HNT_CONTIGUOUS_V6;
- name->len = HICN_V6_NAME_LEN;
-#endif /* HICN_VPP_PLUGIN */
- return CHILD_OPS (get_interest_name_suffix, type, h, &(name->ip6.suffix));
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
+ name->prefix.v6 = ipv6->daddr;
+ return CALL_CHILD (get_interest_name_suffix, pkbuf, pos, &(name->suffix));
}
int
-ipv6_set_interest_name (hicn_type_t type, hicn_protocol_t *h,
+ipv6_set_interest_name (const hicn_packet_buffer_t *pkbuf, size_t pos,
const hicn_name_t *name)
{
- h->ipv6.daddr = name->ip6.prefix_as_ip6;
- return CHILD_OPS (set_interest_name_suffix, type, h, &(name->ip6.suffix));
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
+ ipv6->daddr = name->prefix.v6;
+ return CALL_CHILD (set_interest_name_suffix, pkbuf, pos, &(name->suffix));
}
int
-ipv6_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ipv6_get_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
hicn_name_suffix_t *suffix)
{
- return CHILD_OPS (get_interest_name_suffix, type, h, suffix);
+ return CALL_CHILD (get_interest_name_suffix, pkbuf, pos, suffix);
}
int
-ipv6_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ipv6_set_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
const hicn_name_suffix_t *suffix)
{
- return CHILD_OPS (set_interest_name_suffix, type, h, suffix);
+ return CALL_CHILD (set_interest_name_suffix, pkbuf, pos, suffix);
}
int
-ipv6_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h)
+ipv6_get_type (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ hicn_packet_type_t *type)
{
- return CHILD_OPS (mark_packet_as_interest, type, h);
+ return CALL_CHILD (get_type, pkbuf, pos, type);
}
int
-ipv6_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h)
+ipv6_set_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_packet_type_t type)
{
- return CHILD_OPS (mark_packet_as_data, type, h);
+ return CALL_CHILD (set_type, pkbuf, pos, type);
}
int
-ipv6_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
+ipv6_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
{
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
/* Sets everything to 0 up to IP destination address */
- memset (&(h->ipv6), 0, 24);
+ memset (ipv6, 0, 24);
- return CHILD_OPS (reset_interest_for_hash, type, h);
+ return CALL_CHILD (reset_interest_for_hash, pkbuf, pos);
}
int
-ipv6_get_data_locator (hicn_type_t type, const hicn_protocol_t *h,
- ip46_address_t *ip_address)
+ipv6_get_data_locator (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_ip_address_t *ip_address)
{
- ip_address->ip6 = h->ipv6.daddr;
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
+ ip_address->v6 = ipv6->daddr;
return HICN_LIB_ERROR_NONE;
}
int
-ipv6_set_data_locator (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *ip_address)
+ipv6_set_data_locator (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *ip_address)
{
- h->ipv6.daddr = ip_address->ip6;
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
+ ipv6->daddr = ip_address->v6;
return HICN_LIB_ERROR_NONE;
}
int
-ipv6_get_data_name (hicn_type_t type, const hicn_protocol_t *h,
+ipv6_get_data_name (const hicn_packet_buffer_t *pkbuf, size_t pos,
hicn_name_t *name)
{
- name->ip6.prefix_as_ip6 = h->ipv6.saddr;
-#ifndef HICN_VPP_PLUGIN
- name->type = HNT_CONTIGUOUS_V6;
- name->len = HICN_V6_NAME_LEN;
-#endif /* HICN_VPP_PLUGIN */
- return CHILD_OPS (get_data_name_suffix, type, h, &(name->ip6.suffix));
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
+ name->prefix.v6 = ipv6->saddr;
+ return CALL_CHILD (get_data_name_suffix, pkbuf, pos, &(name->suffix));
}
int
-ipv6_set_data_name (hicn_type_t type, hicn_protocol_t *h,
+ipv6_set_data_name (const hicn_packet_buffer_t *pkbuf, size_t pos,
const hicn_name_t *name)
{
- h->ipv6.saddr = name->ip6.prefix_as_ip6;
- return CHILD_OPS (set_data_name_suffix, type, h, &(name->ip6.suffix));
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
+ ipv6->saddr = name->prefix.v6;
+ return CALL_CHILD (set_data_name_suffix, pkbuf, pos, &(name->suffix));
}
int
-ipv6_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ipv6_get_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
hicn_name_suffix_t *suffix)
{
- return CHILD_OPS (get_data_name_suffix, type, h, suffix);
+ return CALL_CHILD (get_data_name_suffix, pkbuf, pos, suffix);
}
int
-ipv6_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ipv6_set_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
const hicn_name_suffix_t *suffix)
{
- return CHILD_OPS (set_data_name_suffix, type, h, suffix);
+ return CALL_CHILD (set_data_name_suffix, pkbuf, pos, suffix);
}
int
-ipv6_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h,
- u32 *pathlabel)
+ipv6_get_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_path_label_t *path_label)
{
- return CHILD_OPS (get_data_pathlabel, type, h, pathlabel);
+ return CALL_CHILD (get_data_path_label, pkbuf, pos, path_label);
}
int
-ipv6_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
- const u32 pathlabel)
+ipv6_set_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_path_label_t path_label)
{
- return CHILD_OPS (set_data_pathlabel, type, h, pathlabel);
+ return CALL_CHILD (set_data_path_label, pkbuf, pos, path_label);
}
int
-ipv6_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
- const hicn_faceid_t face_id)
+ipv6_update_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_faceid_t face_id)
{
- return CHILD_OPS (update_data_pathlabel, type, h, face_id);
+ return CALL_CHILD (update_data_path_label, pkbuf, pos, face_id);
}
int
-ipv6_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
+ipv6_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
{
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
/* IP: Set everithing to 0 up to destination address */
- memset (&h->ipv6, 0, 8);
+ memset (ipv6, 0, 8);
/* Clears destination address */
- memset (&(h->ipv6.daddr), 0, 16);
+ memset (&(ipv6->daddr), 0, 16);
- return CHILD_OPS (reset_data_for_hash, type, h);
+ return CALL_CHILD (reset_data_for_hash, pkbuf, pos);
}
int
-ipv6_get_lifetime (hicn_type_t type, const hicn_protocol_t *h,
+ipv6_get_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos,
hicn_lifetime_t *lifetime)
{
- return CHILD_OPS (get_lifetime, type, h, lifetime);
+ return CALL_CHILD (get_lifetime, pkbuf, pos, lifetime);
}
int
-ipv6_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
+ipv6_set_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos,
const hicn_lifetime_t lifetime)
{
- return CHILD_OPS (set_lifetime, type, h, lifetime);
+ return CALL_CHILD (set_lifetime, pkbuf, pos, lifetime);
}
int
-ipv6_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
- size_t payload_length)
+ipv6_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
{
- /* Retrieve payload length if not specified */
- if (payload_length == ~0)
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
+ /* Retrieve payload len if not specified */
+ if (payload_len == ~0)
{
- int rc = ipv6_get_payload_length (type, h, &payload_length);
- if (rc < 0)
- return rc;
+ payload_len = hicn_packet_get_len (pkbuf) - pkbuf->payload;
}
/* Build pseudo-header */
ipv6_pseudo_header_t psh;
- psh.ip_src = h->ipv6.saddr;
- psh.ip_dst = h->ipv6.daddr;
+ psh.ip_src = ipv6->saddr;
+ psh.ip_dst = ipv6->daddr;
/* Size is u32 and not u16, we cannot copy and need to care about endianness
*/
- psh.size = htonl (ntohs (h->ipv6.len));
+ psh.size = htonl (ntohs (ipv6->len));
psh.zeros = 0;
psh.zero = 0;
- psh.protocol = h->ipv6.nxt;
+ psh.protocol = ipv6->nxt;
/* Compute partial checksum based on pseudo-header */
if (partial_csum != 0)
@@ -243,31 +271,41 @@ ipv6_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
}
partial_csum = csum (&psh, IPV6_PSHDRLEN, partial_csum);
- return CHILD_OPS (update_checksums, type, h, partial_csum, payload_length);
+ return CALL_CHILD (update_checksums, pkbuf, pos, partial_csum, payload_len);
}
int
-ipv6_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
- size_t payload_length)
+ipv6_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf,
+ size_t pos, u16 *old_val, u16 *new_val,
+ u8 size, bool skip_first)
{
- /* Retrieve payload length if not specified */
- if (payload_length == ~0)
+ /* We update the child only */
+ return CALL_CHILD (update_checksums_incremental, pkbuf, pos, old_val,
+ new_val, size, false);
+}
+
+int
+ipv6_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
+{
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
+ /* Retrieve payload len if not specified */
+ if (payload_len == ~0)
{
- int rc = ipv6_get_payload_length (type, h, &payload_length);
- if (rc < 0)
- return rc;
+ payload_len = hicn_packet_get_len (pkbuf) - pkbuf->payload;
}
/* Build pseudo-header */
ipv6_pseudo_header_t pseudo;
- pseudo.ip_src = h->ipv6.saddr;
- pseudo.ip_dst = h->ipv6.daddr;
+ pseudo.ip_src = ipv6->saddr;
+ pseudo.ip_dst = ipv6->daddr;
/* Size is u32 and not u16, we cannot copy and need to care about endianness
*/
- pseudo.size = htonl (ntohs (h->ipv6.len));
+ pseudo.size = htonl (ntohs (ipv6->len));
pseudo.zeros = 0;
pseudo.zero = 0;
- pseudo.protocol = h->ipv6.nxt;
+ pseudo.protocol = ipv6->nxt;
/* Compute partial checksum based on pseudo-header */
if (partial_csum != 0)
@@ -276,161 +314,161 @@ ipv6_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
}
partial_csum = csum (&pseudo, IPV6_PSHDRLEN, partial_csum);
- return CHILD_OPS (verify_checksums, type, h, partial_csum, payload_length);
+ return CALL_CHILD (verify_checksums, pkbuf, pos, partial_csum, payload_len);
}
int
-ipv6_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new,
- ip46_address_t *addr_old)
+ipv6_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old)
{
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
// ASSERT(addr_old == NULL);
- addr_old->ip6 = h->ipv6.saddr;
- h->ipv6.saddr = addr_new->ip6;
+ addr_old->v6 = ipv6->saddr;
+ ipv6->saddr = addr_new->v6;
- return CHILD_OPS (rewrite_interest, type, h, addr_new, addr_old);
+ return CALL_CHILD (rewrite_interest, pkbuf, pos, addr_new, addr_old);
}
int
-ipv6_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old,
- const hicn_faceid_t face_id, u8 reset_pl)
+ipv6_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old, const hicn_faceid_t face_id,
+ u8 reset_pl)
{
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
// ASSERT(addr_old == NULL);
- addr_old->ip6 = h->ipv6.daddr;
- h->ipv6.daddr = addr_new->ip6;
+ addr_old->v6 = ipv6->daddr;
+ ipv6->daddr = addr_new->v6;
- return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id,
- reset_pl);
+ return CALL_CHILD (rewrite_data, pkbuf, pos, addr_new, addr_old, face_id,
+ reset_pl);
}
int
-ipv6_get_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+ipv6_set_payload_len (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t payload_len)
{
- *header_length = IPV6_HDRLEN + ntohs (h->ipv6.len);
+ _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf);
+
+ ipv6->len = htons ((u_short) (payload_len + pkbuf->payload - IPV6_HDRLEN));
return HICN_LIB_ERROR_NONE;
}
int
-ipv6_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+ipv6_get_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_payload_type_t *payload_type)
{
- *header_length = IPV6_HDRLEN;
- return HICN_LIB_ERROR_NONE;
+ return CALL_CHILD (get_payload_type, pkbuf, pos, payload_type);
}
int
-ipv6_get_header_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+ipv6_set_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_payload_type_t payload_type)
{
- size_t child_header_length = 0;
- int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
- if (rc < 0)
- return rc;
- *header_length = IPV6_HDRLEN + child_header_length;
- return HICN_LIB_ERROR_NONE;
+ return CALL_CHILD (set_payload_type, pkbuf, pos, payload_type);
}
int
-ipv6_get_payload_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *payload_length)
+ipv6_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t *signature_size)
{
- size_t child_header_length;
- int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
- if (rc < 0)
- return rc;
- *payload_length = ntohs (h->ipv6.len) - child_header_length;
- return HICN_LIB_ERROR_NONE;
+ return CALL_CHILD (get_signature_size, pkbuf, pos, signature_size);
}
int
-ipv6_set_payload_length (hicn_type_t type, hicn_protocol_t *h,
- size_t payload_length)
+ipv6_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t signature_size)
{
- size_t child_header_length;
- int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
- if (rc < 0)
- return rc;
- h->ipv6.len = htons ((u_short) (payload_length + child_header_length));
- return HICN_LIB_ERROR_NONE;
+ return CALL_CHILD (set_signature_size, pkbuf, pos, signature_size);
}
int
-ipv6_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
- size_t *signature_size)
+ipv6_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t padding)
{
- return CHILD_OPS (get_signature_size, type, h, signature_size);
+ return CALL_CHILD (set_signature_padding, pkbuf, pos, padding);
}
int
-ipv6_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
- size_t signature_size)
+ipv6_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t *padding)
+{
+ return CALL_CHILD (get_signature_padding, pkbuf, pos, padding);
+}
+
+int
+ipv6_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint64_t signature_timestamp)
{
- return CHILD_OPS (set_signature_size, type, h, signature_size);
+ return CALL_CHILD (set_signature_timestamp, pkbuf, pos, signature_timestamp);
}
int
-ipv6_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+ipv6_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint64_t *signature_timestamp)
{
- return CHILD_OPS (set_signature_gap, type, h, gap);
+ return CALL_CHILD (get_signature_timestamp, pkbuf, pos, signature_timestamp);
}
int
-ipv6_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *gap)
+ipv6_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t validation_algorithm)
{
- return CHILD_OPS (get_signature_gap, type, h, gap);
+ return CALL_CHILD (set_validation_algorithm, pkbuf, pos,
+ validation_algorithm);
}
int
-ipv6_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h,
- uint64_t signature_timestamp)
+ipv6_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t *validation_algorithm)
{
- return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
+ return CALL_CHILD (get_validation_algorithm, pkbuf, pos,
+ validation_algorithm);
}
int
-ipv6_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h,
- uint64_t *signature_timestamp)
+ipv6_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t *key_id, size_t key_len)
{
- return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
+ return CALL_CHILD (set_key_id, pkbuf, pos, key_id, key_len);
}
int
-ipv6_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h,
- uint8_t validation_algorithm)
+ipv6_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t **key_id, uint8_t *key_id_size)
{
- return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
+ return CALL_CHILD (get_key_id, pkbuf, pos, key_id, key_id_size);
}
int
-ipv6_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *validation_algorithm)
+ipv6_get_signature (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t **signature)
{
- return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
+ return CALL_CHILD (get_signature, pkbuf, pos, signature);
}
int
-ipv6_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id)
+ipv6_has_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, bool *flag)
{
- return CHILD_OPS (set_key_id, type, h, key_id);
+ return CALL_CHILD (has_signature, pkbuf, pos, flag);
}
int
-ipv6_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
- uint8_t *key_id_size)
+ipv6_is_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos, int *is_last)
{
- return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
+ return CALL_CHILD (is_last_data, pkbuf, pos, is_last);
}
int
-ipv6_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
+ipv6_set_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos)
{
- return CHILD_OPS (get_signature, type, h, signature);
+ return CALL_CHILD (set_last_data, pkbuf, pos);
}
-DECLARE_HICN_OPS (ipv6);
+DECLARE_HICN_OPS (ipv6, IPV6_HDRLEN);
/*
* fd.io coding-style-patch-verification: ON
diff --git a/lib/src/protocol/ipv6.h b/lib/src/protocol/ipv6.h
new file mode 100644
index 000000000..9a51096a0
--- /dev/null
+++ b/lib/src/protocol/ipv6.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HICN_PROTOCOL_IPV6_H
+#define HICN_PROTOCOL_IPV6_H
+
+#include <hicn/util/ip_address.h>
+
+#include <hicn/common.h>
+
+/*
+ * The length of the IPV6 header struct must be 40 bytes.
+ */
+#define EXPECTED_IPV6_HDRLEN 40
+
+typedef struct
+{
+#if 0 // TEMPORARY FIX
+ union
+ {
+ struct
+ {
+#endif
+ u32 version_class_flow; /* version, traffic class and 20 bits of flow-ID */
+ u16 len; /* payload length */
+ u8 nxt; /* next header */
+ u8 hlim; /* hop limit */
+#if 0
+ };
+ u8 vfc; /* 4 bits version, top 4 bits class */
+ };
+#endif
+ ipv6_address_t saddr; /* source address */
+ ipv6_address_t daddr; /* destination address */
+} _ipv6_header_t;
+
+#define IPV6_HDRLEN sizeof (_ipv6_header_t)
+static_assert (EXPECTED_IPV6_HDRLEN == IPV6_HDRLEN,
+ "Size of IPV6 struct does not match its expected size.");
+
+/*
+ * The length of the IPV6 pseudo header struct must be 40 bytes.
+ */
+#define EXPECTED_IPV6_PSHDRLEN 40
+
+typedef struct
+{
+ ipv6_address_t ip_src;
+ ipv6_address_t ip_dst;
+ u32 size;
+ u16 zeros;
+ u8 zero;
+ u8 protocol;
+} ipv6_pseudo_header_t;
+
+#define IPV6_PSHDRLEN sizeof (ipv6_pseudo_header_t)
+static_assert (EXPECTED_IPV6_PSHDRLEN == IPV6_PSHDRLEN,
+ "Size of IPV6_PSHDR struct does not match its expected size.");
+
+/* Default field values */
+#define IPV6_DEFAULT_VERSION 6
+#define IPV6_DEFAULT_TRAFFIC_CLASS 0
+#define IPV6_DEFAULT_FLOW_LABEL 0
+#define IPV6_DEFAULT_PAYLOAD_LENGTH 0
+
+#endif
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/new.c b/lib/src/protocol/new.c
new file mode 100644
index 000000000..e86ce4753
--- /dev/null
+++ b/lib/src/protocol/new.c
@@ -0,0 +1,563 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <hicn/common.h>
+#include <hicn/error.h>
+
+#include "udp.h"
+#include "../ops.h"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+
+int
+new_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos)
+{
+ pkbuf->newhdr = pkbuf->len;
+ if (NEW_HDRLEN > pkbuf->buffer_size - pkbuf->len)
+ return -1;
+ pkbuf->len += NEW_HDRLEN;
+
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ hicn_packet_format_t format = hicn_packet_get_format (pkbuf);
+
+ memset (new, 0, sizeof (_new_header_t));
+ _set_new_header_version (new);
+ uint8_t ah_flag = (HICN_PACKET_FORMAT_GET (format, pos + 1) == IPPROTO_AH) ?
+ HICN_NEW_FLAG_SIG :
+ 0;
+ new->flags |= ah_flag;
+
+ return CALL_CHILD (init_packet_header, pkbuf, pos);
+}
+
+int
+new_get_type (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ hicn_packet_type_t *type)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ /* Interest packets have the INT bit set */
+ if (new->flags & HICN_NEW_FLAG_INT)
+ *type = HICN_PACKET_TYPE_INTEREST;
+ else
+ *type = HICN_PACKET_TYPE_DATA;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_packet_type_t type)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ switch (type)
+ {
+ case HICN_PACKET_TYPE_INTEREST:
+ new->flags |= HICN_NEW_FLAG_INT;
+ break;
+ case HICN_PACKET_TYPE_DATA:
+ new->flags &= ~HICN_NEW_FLAG_INT;
+ break;
+ default:
+ return -1;
+ }
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_interest_locator (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_ip_address_t *ip_address)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+ _unused (new);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_INTEREST);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_interest_locator (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *ip_address)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+ _unused (new);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_INTEREST);
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_interest_name (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_name_t *name)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_INTEREST);
+
+ name->prefix = new->prefix;
+ name->suffix = ntohl (new->suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+// XXX never called and thus packet is never initialized as interest
+// DECLARE_set_interest_name (udp, UNEXPECTED);
+int
+new_set_interest_name (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_name_t *name)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ int rc = new_set_type (pkbuf, pos, HICN_PACKET_TYPE_INTEREST);
+ if (rc)
+ return rc;
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_INTEREST);
+
+ new->prefix = name->prefix;
+ new->suffix = htonl (name->suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_name_suffix_t *suffix)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_INTEREST);
+
+ *suffix = ntohl (new->suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_name_suffix_t *suffix)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_INTEREST);
+
+ new->suffix = htonl (*suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+ _unused (new);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_INTEREST);
+
+ return CALL_CHILD (init_packet_header, pkbuf, pos);
+}
+
+int
+new_get_data_locator (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_ip_address_t *ip_address)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+ _unused (new);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_INTEREST);
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_data_locator (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *ip_address)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+ _unused (new);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_DATA);
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_data_name (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_name_t *name)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_DATA);
+
+ name->prefix = new->prefix;
+ name->suffix = ntohl (new->suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_data_name (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_name_t *name)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ int rc = new_set_type (pkbuf, pos, HICN_PACKET_TYPE_DATA);
+ if (rc)
+ return rc;
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_DATA);
+
+ new->prefix = name->prefix;
+ new->suffix = htonl (name->suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_name_suffix_t *suffix)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_DATA);
+
+ *suffix = ntohl (new->suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_name_suffix_t *suffix)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_DATA);
+
+ new->suffix = htonl (*suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_path_label_t *path_label)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_DATA);
+
+ *path_label = ntohl (new->path_label);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_path_label_t path_label)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_DATA);
+
+ new->path_label = htonl (path_label);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_update_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_faceid_t face_id)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ hicn_path_label_t new_pl;
+ update_path_label (new->path_label, face_id, &new_pl);
+ new->path_label = new_pl;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
+{
+ return CALL_CHILD (reset_data_for_hash, pkbuf, pos);
+}
+
+int
+new_get_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_lifetime_t *lifetime)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ *lifetime = ntohl (new->lifetime);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_lifetime_t lifetime)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ new->lifetime = htonl (lifetime);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
+{
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf,
+ size_t pos, u16 *old_val, u16 *new_val,
+ u8 size, bool skip_first)
+{
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
+{
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+ _unused (new);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_INTEREST);
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old, const hicn_faceid_t face_id,
+ u8 reset_pl)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+ _unused (new);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_DATA);
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_payload_len (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t payload_len)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ /*
+ * The value we have to store in the header is the sum of headers following
+ * the current header + the new payload size
+ */
+
+ size_t child_header_len =
+ (pkbuf->payload - pkbuf->newhdr) - sizeof (_new_header_t);
+ new->payload_len = htons ((u16) child_header_len + payload_len);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t *signature_size)
+{
+ return CALL_CHILD (get_signature_size, pkbuf, pos, signature_size);
+}
+
+int
+new_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t signature_size)
+{
+ return CALL_CHILD (set_signature_size, pkbuf, pos, signature_size);
+}
+
+int
+new_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t padding)
+{
+ return CALL_CHILD (set_signature_padding, pkbuf, pos, padding);
+}
+
+int
+new_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t *padding)
+{
+ return CALL_CHILD (get_signature_padding, pkbuf, pos, padding);
+}
+
+int
+new_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint64_t signature_timestamp)
+{
+ return CALL_CHILD (set_signature_timestamp, pkbuf, pos, signature_timestamp);
+}
+
+int
+new_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint64_t *signature_timestamp)
+{
+ return CALL_CHILD (get_signature_timestamp, pkbuf, pos, signature_timestamp);
+}
+
+int
+new_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t validation_algorithm)
+{
+ return CALL_CHILD (set_validation_algorithm, pkbuf, pos,
+ validation_algorithm);
+}
+
+int
+new_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t *validation_algorithm)
+{
+ return CALL_CHILD (get_validation_algorithm, pkbuf, pos,
+ validation_algorithm);
+}
+
+int
+new_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t *key_id,
+ size_t key_len)
+{
+ return CALL_CHILD (set_key_id, pkbuf, pos, key_id, key_len);
+}
+
+int
+new_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t **key_id, uint8_t *key_id_size)
+{
+ return CALL_CHILD (get_key_id, pkbuf, pos, key_id, key_id_size);
+}
+
+int
+new_get_signature (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t **signature)
+{
+ return CALL_CHILD (get_signature, pkbuf, pos, signature);
+}
+
+int
+new_has_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, bool *flag)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ return new->flags &HICN_NEW_FLAG_SIG;
+}
+
+int
+new_get_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_payload_type_t *payload_type)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ *payload_type = ((new->flags &HICN_NEW_FLAG_MAN) == HICN_NEW_FLAG_MAN);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_payload_type_t payload_type)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ if (payload_type != HPT_DATA && payload_type != HPT_MANIFEST)
+ return HICN_LIB_ERROR_INVALID_PARAMETER;
+
+ if (payload_type)
+ new->flags |= HICN_NEW_FLAG_MAN;
+ else
+ new->flags &= ~HICN_NEW_FLAG_MAN;
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_is_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos, int *is_last)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_DATA);
+
+ *is_last = new->flags &HICN_NEW_FLAG_LST;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos)
+{
+ _new_header_t *new = pkbuf_get_new (pkbuf);
+
+ hicn_packet_type_t type;
+ _ASSERT (new_get_type (pkbuf, pos, &type) == 0);
+ _ASSERT (type == HICN_PACKET_TYPE_DATA);
+
+ new->flags |= HICN_NEW_FLAG_LST;
+ return HICN_LIB_ERROR_NONE;
+}
+
+DECLARE_HICN_OPS (new, NEW_HDRLEN);
+
+#pragma GCC diagnostic pop
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/new.h b/lib/src/protocol/new.h
new file mode 100644
index 000000000..7679910f4
--- /dev/null
+++ b/lib/src/protocol/new.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file protocol/ah.h
+ * @brief AH packet header
+ */
+#ifndef HICN_PROTOCOL_NEW_H
+#define HICN_PROTOCOL_NEW_H
+
+#include <hicn/common.h>
+#include <hicn/name.h>
+
+/*
+ * The length of the new header struct must be 28 bytes.
+ */
+#define EXPECTED_NEW_HDRLEN 32
+
+typedef struct
+{
+ u8 version_reserved;
+ u8 flags;
+
+ /* Size of the payload direcly after the new header */
+ u16 payload_len;
+
+ u32 lifetime;
+
+ /* Name prefix and suffix */
+ hicn_ip_address_t prefix;
+ u32 suffix;
+
+ /* We reserve 32 bits for the path label */
+ u32 path_label;
+} _new_header_t;
+
+#define NEW_HDRLEN sizeof (_new_header_t)
+static_assert (EXPECTED_NEW_HDRLEN == NEW_HDRLEN,
+ "Size of new_header Struct does not match its expected size.");
+
+/* TCP flags bit 0 first. */
+#define foreach_hicn_new_flag \
+ _ (SIG) /**< Signature header after. */ \
+ _ (MAN) /**< Payload type is manifest. */ \
+ _ (INT) /**< Packet is interest. */ \
+ _ (LST) /**< Last data. */
+
+enum
+{
+#define _(f) HICN_NEW_FLAG_BIT_##f,
+ foreach_hicn_new_flag
+#undef _
+ HICN_NEW_N_FLAG_BITS,
+};
+
+enum
+{
+#define _(f) HICN_NEW_FLAG_##f = 1 << HICN_NEW_FLAG_BIT_##f,
+ foreach_hicn_new_flag
+#undef _
+};
+
+static inline int
+_get_new_header_version (const _new_header_t *new_hdr)
+{
+ return ((new_hdr->version_reserved >> 4) & 0x0F);
+}
+
+static inline void
+_set_new_header_version (_new_header_t *new_hdr)
+{
+ new_hdr->version_reserved = (0x9 << 4) & 0xF0;
+}
+
+#endif /* HICN_PROTOCOL_NEW_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/tcp.c b/lib/src/protocol/tcp.c
index cfeac1907..e09495ecd 100644
--- a/lib/src/protocol/tcp.c
+++ b/lib/src/protocol/tcp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -14,9 +14,12 @@
*/
#include <string.h>
-#include <hicn/protocol/tcp.h>
+
+#include <hicn/base.h>
#include <hicn/error.h>
-#include <hicn/ops.h>
+
+#include "tcp.h"
+#include "../ops.h"
#define TCP_DEFAULT_SRC_PORT 0x8000
#define TCP_DEFAULT_DST_PORT 0x0080
@@ -32,6 +35,8 @@
#define TCP_DEFAULT_SYN 1
#define TCP_DEFAULT_FIN 0
+#define UINT16_T_MASK 0x0000ffff // 1111 1111 1111 1111
+
DECLARE_get_interest_locator (tcp, UNEXPECTED);
DECLARE_set_interest_locator (tcp, UNEXPECTED);
DECLARE_get_interest_name (tcp, UNEXPECTED);
@@ -40,11 +45,27 @@ DECLARE_get_data_locator (tcp, UNEXPECTED);
DECLARE_set_data_locator (tcp, UNEXPECTED);
DECLARE_get_data_name (tcp, UNEXPECTED);
DECLARE_set_data_name (tcp, UNEXPECTED);
-DECLARE_get_length (tcp, UNEXPECTED);
-DECLARE_get_payload_length (tcp, UNEXPECTED);
-DECLARE_set_payload_length (tcp, UNEXPECTED);
+DECLARE_set_payload_len (tcp, UNEXPECTED);
-always_inline int
+int tcp_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf,
+ size_t pos, u16 *old_val, u16 *new_val,
+ u8 size, bool skip_first);
+
+static inline void
+reset_for_hash (hicn_packet_buffer_t *pkbuf)
+{
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ tcp->sport = 0;
+ tcp->dport = 0;
+ tcp->seq_ack = 0;
+ tcp->data_offset_and_reserved = 0;
+ tcp->flags = 0;
+ tcp->window = 0;
+ tcp->csum = 0;
+ tcp->urg_ptr = 0;
+}
+
+static inline int
check_tcp_checksum (u16 csum)
{
/* As per RFC1624
@@ -67,9 +88,17 @@ check_tcp_checksum (u16 csum)
}
int
-tcp_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
+tcp_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos)
{
- h->tcp = (_tcp_header_t){
+ pkbuf->tcp = pkbuf->len;
+ if (TCP_HDRLEN > pkbuf->buffer_size - pkbuf->len)
+ return -1;
+ pkbuf->len += TCP_HDRLEN;
+
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ hicn_packet_format_t format = hicn_packet_get_format (pkbuf);
+
+ *tcp = (_tcp_header_t){
.sport = htons (TCP_DEFAULT_SRC_PORT),
.dport = htons (TCP_DEFAULT_DST_PORT),
.seq = 0,
@@ -84,131 +113,170 @@ tcp_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
.urg_ptr = 65000,
};
- uint8_t ah_flag = type.l2 == IPPROTO_AH ? AH_FLAG : 0;
+ uint8_t ah_flag =
+ (HICN_PACKET_FORMAT_GET (format, pos + 1) == IPPROTO_AH) ? AH_FLAG : 0;
- h->tcp.flags |= ah_flag;
+ tcp->flags |= ah_flag;
- return CHILD_OPS (init_packet_header, type, h);
+ return CALL_CHILD (init_packet_header, pkbuf, pos);
}
int
-tcp_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
- hicn_name_suffix_t *suffix)
-{
- *suffix = ntohl (h->tcp.name_suffix);
+tcp_get_type (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ hicn_packet_type_t *type)
+{
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ /* Data packets have the ECE bit set */
+ if (tcp->flags & HICN_TCP_FLAG_ECE)
+ *type = HICN_PACKET_TYPE_DATA;
+ else
+ *type = HICN_PACKET_TYPE_INTEREST;
return HICN_LIB_ERROR_NONE;
}
int
-tcp_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h,
- const hicn_name_suffix_t *suffix)
+tcp_set_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_packet_type_t type)
{
- h->tcp.name_suffix = htonl (*suffix);
-
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ switch (type)
+ {
+ case HICN_PACKET_TYPE_INTEREST:
+ tcp->flags &= ~HICN_TCP_FLAG_ECE;
+ break;
+ case HICN_PACKET_TYPE_DATA:
+ tcp->flags |= HICN_TCP_FLAG_ECE;
+ break;
+ default:
+ return HICN_LIB_ERROR_INVALID_PARAMETER;
+ }
return HICN_LIB_ERROR_NONE;
}
int
-tcp_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h)
+tcp_get_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_name_suffix_t *suffix)
{
- h->tcp.flags &= ~HICN_TCP_FLAG_ECE;
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ *suffix = ntohl (tcp->name_suffix);
return HICN_LIB_ERROR_NONE;
}
int
-tcp_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h)
+tcp_set_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_name_suffix_t *suffix)
{
- h->tcp.flags |= HICN_TCP_FLAG_ECE;
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ int rc = tcp_set_type (pkbuf, pos, HICN_PACKET_TYPE_INTEREST);
+ if (rc)
+ return rc;
+
+ tcp->name_suffix = htonl (*suffix);
+
return HICN_LIB_ERROR_NONE;
}
int
-tcp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
+tcp_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
{
- memset (&(h->tcp), 0, 4);
- memset (&(h->tcp.seq_ack), 0, 12);
-
- return CHILD_OPS (reset_interest_for_hash, type, h);
+ reset_for_hash (pkbuf);
+ return CALL_CHILD (reset_interest_for_hash, pkbuf, pos);
}
int
-tcp_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+tcp_get_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
hicn_name_suffix_t *suffix)
{
- *suffix = ntohl (h->tcp.name_suffix);
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ *suffix = ntohl (tcp->name_suffix);
return HICN_LIB_ERROR_NONE;
}
int
-tcp_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+tcp_set_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
const hicn_name_suffix_t *suffix)
{
- h->tcp.name_suffix = htonl (*suffix);
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ int rc = tcp_set_type (pkbuf, pos, HICN_PACKET_TYPE_DATA);
+ if (rc)
+ return rc;
+
+ tcp->name_suffix = htonl (*suffix);
return HICN_LIB_ERROR_NONE;
}
int
-tcp_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h,
- u32 *pathlabel)
+tcp_get_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_path_label_t *path_label)
{
- *pathlabel = h->tcp.seq_ack;
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ *path_label =
+ (hicn_path_label_t) (tcp->seq_ack >> (32 - HICN_PATH_LABEL_SIZE_BITS));
return HICN_LIB_ERROR_NONE;
}
int
-tcp_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
- const u32 pathlabel)
+tcp_set_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_path_label_t path_label)
{
- h->tcp.seq_ack = pathlabel;
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ hicn_path_label_t old_path_label;
+ tcp_get_data_path_label (pkbuf, pos, &old_path_label);
+
+ tcp->seq_ack = (path_label << (32 - HICN_PATH_LABEL_SIZE_BITS));
+
+ tcp_update_checksums_incremental (
+ pkbuf, pos, (uint16_t *) &old_path_label, (uint16_t *) &path_label,
+ sizeof (hicn_path_label_t) / sizeof (uint16_t), true);
+
return HICN_LIB_ERROR_NONE;
}
int
-tcp_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
- const hicn_faceid_t face_id)
+tcp_update_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_faceid_t face_id)
{
- hicn_pathlabel_t pl =
- (hicn_pathlabel_t) (h->tcp.seq_ack >> (32 - HICN_PATH_LABEL_SIZE));
+ assert (sizeof (hicn_path_label_t) == 1);
- hicn_pathlabel_t new_pl;
+ hicn_path_label_t old_path_label;
+ hicn_path_label_t new_path_label;
- update_pathlabel (pl, face_id, &new_pl);
- h->tcp.seq_ack = (new_pl << (32 - HICN_PATH_LABEL_SIZE));
+ tcp_get_data_path_label (pkbuf, pos, &old_path_label);
+ update_path_label (old_path_label, face_id, &new_path_label);
+ tcp_set_data_path_label (pkbuf, pos, new_path_label);
return HICN_LIB_ERROR_NONE;
}
int
-tcp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
+tcp_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
{
- memset (&(h->tcp), 0, 4);
- memset (&(h->tcp.seq_ack), 0, 12);
-
- return CHILD_OPS (reset_data_for_hash, type, h);
+ reset_for_hash (pkbuf);
+ return CALL_CHILD (reset_data_for_hash, pkbuf, pos);
}
int
-tcp_get_lifetime (hicn_type_t type, const hicn_protocol_t *h,
+tcp_get_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos,
hicn_lifetime_t *lifetime)
{
- *lifetime = ntohs (h->tcp.urg_ptr)
- << (h->tcp.data_offset_and_reserved & 0xF);
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ *lifetime = ntohs (tcp->urg_ptr) << (tcp->data_offset_and_reserved & 0xF);
return HICN_LIB_ERROR_NONE;
}
int
-tcp_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
+tcp_set_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos,
const hicn_lifetime_t lifetime)
{
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
u8 multiplier = 0;
u32 lifetime_scaled = lifetime;
- if (PREDICT_FALSE (lifetime >= HICN_MAX_LIFETIME))
+ if (HICN_EXPECT_FALSE (lifetime >= HICN_MAX_LIFETIME))
{
- h->tcp.urg_ptr = htons (HICN_MAX_LIFETIME_SCALED);
- h->tcp.data_offset_and_reserved =
- (h->tcp.data_offset_and_reserved & ~0x0F) |
- HICN_MAX_LIFETIME_MULTIPLIER;
+ tcp->urg_ptr = htons (HICN_MAX_LIFETIME_SCALED);
+ tcp->data_offset_and_reserved =
+ (tcp->data_offset_and_reserved & ~0x0F) | HICN_MAX_LIFETIME_MULTIPLIER;
return HICN_LIB_ERROR_NONE;
}
@@ -219,41 +287,76 @@ tcp_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
lifetime_scaled = lifetime_scaled >> 1;
}
- h->tcp.urg_ptr = htons (lifetime_scaled);
- h->tcp.data_offset_and_reserved =
- (h->tcp.data_offset_and_reserved & ~0x0F) | multiplier;
+ tcp->urg_ptr = htons (lifetime_scaled);
+ tcp->data_offset_and_reserved =
+ (tcp->data_offset_and_reserved & ~0x0F) | multiplier;
return HICN_LIB_ERROR_NONE;
}
int
-tcp_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
- size_t payload_length)
+tcp_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
{
- h->tcp.csum = 0;
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ /* TODO bound checks for payload_len based on pkbuf size */
+ assert (payload_len != ~0);
- if (PREDICT_TRUE (partial_csum != 0))
+ tcp->csum = 0;
+
+ if (HICN_EXPECT_TRUE (partial_csum != 0))
{
partial_csum = ~partial_csum;
}
- h->tcp.csum = csum (h, TCP_HDRLEN + payload_length, partial_csum);
+ tcp->csum =
+ csum (pkbuf_get_header (pkbuf), TCP_HDRLEN + payload_len, partial_csum);
+
+ return CALL_CHILD (update_checksums, pkbuf, pos, 0, payload_len);
+}
+
+int
+tcp_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf,
+ size_t pos, u16 *old_val, u16 *new_val,
+ u8 size, bool skip_first)
+{
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ if (skip_first)
+ return HICN_LIB_ERROR_INVALID_PARAMETER;
+
+ for (uint8_t i = 0; i < size; i++)
+ {
+ uint16_t old_csum = ~tcp->csum;
+ uint16_t not_old_val = ~(*old_val);
+ uint32_t sum = (uint32_t) old_csum + not_old_val + *new_val;
+
+ while (sum >> 16)
+ {
+ sum = (sum >> 16) + (sum & UINT16_T_MASK);
+ }
+
+ tcp->csum = ~sum;
+ ++old_val;
+ ++new_val;
+ }
- return CHILD_OPS (update_checksums, type, h, 0, payload_length);
+ return CALL_CHILD (update_checksums_incremental, pkbuf, pos, old_val,
+ new_val, size, false);
}
int
-tcp_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
- size_t payload_length)
+tcp_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
{
- if (PREDICT_TRUE (partial_csum != 0))
+ if (HICN_EXPECT_TRUE (partial_csum != 0))
{
partial_csum = ~partial_csum;
}
- if (csum (h, TCP_HDRLEN + payload_length, partial_csum) != 0)
+ if (csum (pkbuf_get_header (pkbuf), TCP_HDRLEN + payload_len,
+ partial_csum) != 0)
return HICN_LIB_ERROR_CORRUPTED_PACKET;
- return CHILD_OPS (verify_checksums, type, h, 0, payload_length);
+ return CALL_CHILD (verify_checksums, pkbuf, pos, 0, payload_len);
}
#define TCP_OFFSET_MASK 13
@@ -278,10 +381,14 @@ tcp_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
#define TCP_DEFAULT_FIN 0
int
-tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old)
+tcp_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old)
{
- u16 *tcp_checksum = &(h->tcp.csum);
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ _ipv6_header_t *ip6 = pkbuf_get_ipv6 (pkbuf);
+
+ u16 *tcp_checksum = &(tcp->csum);
int ret = check_tcp_checksum (*tcp_checksum);
if (ret)
@@ -294,14 +401,14 @@ tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
* whole struct by interpreting it as IPv6 in all cases
*
* v4 code would be:
- * csum = ip_csum_sub_even (*tcp_checksum, h->ipv4.saddr.as_u32);
- * csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
+ * csum = ip_csum_sub_even (*tcp_checksum, h->tcp.saddr.as_u32);
+ * csum = ip_csum_add_even (csum, h->tcp.saddr.as_u32);
*/
- ip_csum_t csum =
- ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (h->ipv6.saddr.as_u64[0]));
- csum = ip_csum_sub_even (csum, (ip_csum_t) (h->ipv6.saddr.as_u64[1]));
- csum = ip_csum_add_even (csum, (ip_csum_t) (h->ipv6.saddr.as_u64[0]));
- csum = ip_csum_add_even (csum, (ip_csum_t) (h->ipv6.saddr.as_u64[1]));
+ hicn_ip_csum_t csum =
+ ip_csum_sub_even (*tcp_checksum, (hicn_ip_csum_t) (ip6->saddr.as_u64[0]));
+ csum = ip_csum_sub_even (csum, (hicn_ip_csum_t) (ip6->saddr.as_u64[1]));
+ csum = ip_csum_add_even (csum, (hicn_ip_csum_t) (ip6->saddr.as_u64[0]));
+ csum = ip_csum_add_even (csum, (hicn_ip_csum_t) (ip6->saddr.as_u64[1]));
*tcp_checksum = ip_csum_fold (csum);
@@ -309,21 +416,22 @@ tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
}
int
-tcp_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old,
- const hicn_faceid_t face_id, u8 reset_pl)
+tcp_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old, const hicn_faceid_t face_id,
+ u8 reset_pl)
{
-
- u16 *tcp_checksum = &(h->tcp.csum);
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ u16 *tcp_checksum = &(tcp->csum);
int ret = check_tcp_checksum (*tcp_checksum);
/*
* update path label
*/
- u16 old_pl = h->tcp.seq_ack;
+ u16 old_pl = tcp->seq_ack;
if (reset_pl)
- h->tcp.seq_ack = 0;
- tcp_update_data_pathlabel (type, h, face_id);
+ tcp->seq_ack = 0;
+ tcp_update_data_path_label (pkbuf, pos, face_id);
if (ret)
{
@@ -335,18 +443,18 @@ tcp_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
* whole struct by interpreting it as IPv6 in all cases
*
* v4 code would be:
- * csum = ip_csum_sub_even (*tcp_checksum, h->ipv4.saddr.as_u32);
- * csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
+ * csum = ip_csum_sub_even (*tcp_checksum, h->tcp.saddr.as_u32);
+ * csum = ip_csum_add_even (csum, h->tcp.saddr.as_u32);
*/
- ip_csum_t csum =
- ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (addr_old->ip6.as_u64[0]));
- csum =
- ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (addr_old->ip6.as_u64[1]));
- csum = ip_csum_add_even (csum, (ip_csum_t) (addr_new->ip6.as_u64[0]));
- csum = ip_csum_add_even (csum, (ip_csum_t) (addr_new->ip6.as_u64[1]));
+ hicn_ip_csum_t csum = ip_csum_sub_even (
+ *tcp_checksum, (hicn_ip_csum_t) (addr_old->v6.as_u64[0]));
+ csum = ip_csum_sub_even (*tcp_checksum,
+ (hicn_ip_csum_t) (addr_old->v6.as_u64[1]));
+ csum = ip_csum_add_even (csum, (hicn_ip_csum_t) (addr_new->v6.as_u64[0]));
+ csum = ip_csum_add_even (csum, (hicn_ip_csum_t) (addr_new->v6.as_u64[1]));
csum = ip_csum_sub_even (csum, old_pl);
- csum = ip_csum_add_even (csum, h->tcp.seq_ack);
+ csum = ip_csum_add_even (csum, tcp->seq_ack);
*tcp_checksum = ip_csum_fold (csum);
@@ -354,101 +462,134 @@ tcp_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
}
int
-tcp_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+tcp_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t *signature_size)
{
- *header_length = TCP_HDRLEN;
- return HICN_LIB_ERROR_NONE;
+ return CALL_CHILD (get_signature_size, pkbuf, pos, signature_size);
}
int
-tcp_get_header_length (hicn_type_t type, const hicn_protocol_t *h,
- size_t *header_length)
+tcp_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t signature_size)
{
- size_t child_header_length = 0;
- int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
- if (rc < 0)
- return rc;
+ return CALL_CHILD (set_signature_size, pkbuf, pos, signature_size);
+}
- *header_length = TCP_HDRLEN + child_header_length;
- return HICN_LIB_ERROR_NONE;
+int
+tcp_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t padding)
+{
+ return CALL_CHILD (set_signature_padding, pkbuf, pos, padding);
}
int
-tcp_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
- size_t *signature_size)
+tcp_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t *padding)
{
- return CHILD_OPS (get_signature_size, type, h, signature_size);
+ return CALL_CHILD (get_signature_padding, pkbuf, pos, padding);
}
int
-tcp_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
- size_t signature_size)
+tcp_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint64_t signature_timestamp)
{
- return CHILD_OPS (set_signature_size, type, h, signature_size);
+ return CALL_CHILD (set_signature_timestamp, pkbuf, pos, signature_timestamp);
}
int
-tcp_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+tcp_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint64_t *signature_timestamp)
{
- return CHILD_OPS (set_signature_gap, type, h, gap);
+ return CALL_CHILD (get_signature_timestamp, pkbuf, pos, signature_timestamp);
}
int
-tcp_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *gap)
+tcp_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t validation_algorithm)
{
- return CHILD_OPS (get_signature_gap, type, h, gap);
+ return CALL_CHILD (set_validation_algorithm, pkbuf, pos,
+ validation_algorithm);
}
int
-tcp_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h,
- uint64_t signature_timestamp)
+tcp_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t *validation_algorithm)
{
- return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
+ return CALL_CHILD (get_validation_algorithm, pkbuf, pos,
+ validation_algorithm);
}
int
-tcp_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h,
- uint64_t *signature_timestamp)
+tcp_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t *key_id,
+ size_t key_len)
{
- return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
+ return CALL_CHILD (set_key_id, pkbuf, pos, key_id, key_len);
}
int
-tcp_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h,
- uint8_t validation_algorithm)
+tcp_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t **key_id, uint8_t *key_id_size)
{
- return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
+ return CALL_CHILD (get_key_id, pkbuf, pos, key_id, key_id_size);
}
int
-tcp_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *validation_algorithm)
+tcp_get_signature (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t **signature)
{
- return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
+ return CALL_CHILD (get_signature, pkbuf, pos, signature);
}
int
-tcp_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id)
+tcp_has_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, bool *flag)
{
- return CHILD_OPS (set_key_id, type, h, key_id);
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ *flag = tcp->flags & AH_FLAG;
+ return HICN_LIB_ERROR_NONE;
}
int
-tcp_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
- uint8_t *key_id_size)
+tcp_get_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_payload_type_t *payload_type)
{
- return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ *payload_type = ((tcp->flags & HICN_TCP_FLAG_URG) == HICN_TCP_FLAG_URG);
+ return HICN_LIB_ERROR_NONE;
}
int
-tcp_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
+tcp_set_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_payload_type_t payload_type)
{
- return CHILD_OPS (get_signature, type, h, signature);
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ if (payload_type != HPT_DATA && payload_type != HPT_MANIFEST)
+ return HICN_LIB_ERROR_INVALID_PARAMETER;
+
+ if (payload_type)
+ tcp->flags |= HICN_TCP_FLAG_URG;
+ else
+ tcp->flags &= ~HICN_TCP_FLAG_URG;
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_is_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos, int *is_last)
+{
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ *is_last = (tcp->flags & HICN_TCP_FLAG_RST) == HICN_TCP_FLAG_RST;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_set_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos)
+{
+ _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf);
+ tcp->flags |= HICN_TCP_FLAG_RST;
+ return HICN_LIB_ERROR_NONE;
}
-DECLARE_HICN_OPS (tcp);
+DECLARE_HICN_OPS (tcp, TCP_HDRLEN);
/*
* fd.io coding-style-patch-verification: ON
diff --git a/lib/src/protocol/tcp.h b/lib/src/protocol/tcp.h
new file mode 100644
index 000000000..e563372d0
--- /dev/null
+++ b/lib/src/protocol/tcp.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HICN_PROTOCOL_TCP_H
+#define HICN_PROTOCOL_TCP_H
+
+#include <hicn/base.h>
+#include <hicn/common.h>
+#include <hicn/name.h>
+
+/*
+ * The length of the TCP header struct must be 20 bytes.
+ */
+#define EXPECTED_TCP_HDRLEN 20
+
+/*
+ * NOTE: bitfields are problematic for portability reasons. There are provided
+ * here for reference and documentation purposes, we might just provide a macro
+ * to disable and use it instead of __BYTE_ORDER__.
+ */
+typedef struct
+{
+ u16 sport;
+ u16 dport;
+ union
+ {
+ u32 seq;
+ hicn_name_suffix_t name_suffix;
+ };
+ union
+ {
+ u32 seq_ack;
+ struct
+ {
+ hicn_path_label_t pathlabel;
+ u8 pad[3];
+ };
+ };
+
+ union
+ {
+ struct
+ {
+ u8 data_offset_and_reserved;
+ u8 flags;
+ };
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ struct
+ {
+ u16 reserved : 4;
+ u16 doff : 4;
+ u16 fin : 1;
+ u16 syn : 1;
+ u16 rst : 1;
+ u16 psh : 1;
+ u16 ack : 1;
+ u16 urg : 1;
+ u16 ece : 1;
+ u16 cwr : 1;
+ };
+ struct
+ { /* __ denotes unchanged bitfields */
+ u16 timescale : 4;
+ u16 __doff : 4;
+ u16 __fin : 1;
+ u16 __syn : 1;
+ u16 __rst : 1;
+ u16 sig : 1;
+ u16 __ack : 1;
+ u16 man : 1;
+ u16 id : 1;
+ u16 __cwr : 1;
+ };
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ struct
+ {
+ u16 doff : 4;
+ u16 reserved : 4;
+ u16 cwr : 1;
+ u16 ece : 1;
+ u16 urg : 1;
+ u16 ack : 1;
+ u16 psh : 1;
+ u16 rst : 1;
+ u16 syn : 1;
+ u16 fin : 1;
+ };
+ struct
+ {
+ u16 __doff : 4;
+ u16 timescale : 4;
+ u16 __cwr : 1;
+ u16 id : 1 u16 man : 1;
+ u16 __ack : 1;
+ u16 sig : 1;
+ u16 __rst : 1;
+ u16 __syn : 1;
+ u16 __fin : 1;
+ };
+#endif
+ };
+ union
+ {
+ u16 window;
+ u16 ldr;
+ };
+ u16 csum;
+ union
+ {
+ u16 urg_ptr;
+ u16 lifetime;
+ };
+} _tcp_header_t;
+
+#define TCP_HDRLEN sizeof (_tcp_header_t)
+static_assert (EXPECTED_TCP_HDRLEN == TCP_HDRLEN,
+ "Size of TCP struct does not match its expected size.");
+
+/* TCP flags bit 0 first. */
+#define foreach_tcp_flag \
+ _ (FIN) /**< No more data from sender. */ \
+ _ (SYN) /**< Synchronize sequence numbers. */ \
+ _ (RST) /**< Reset the connection. */ \
+ _ (PSH) /**< Push function. */ \
+ _ (ACK) /**< Ack field significant. */ \
+ _ (URG) /**< Urgent pointer field significant. */ \
+ _ (ECE) /**< ECN-echo. Receiver got CE packet */ \
+ _ (CWR) /**< Sender reduced congestion window */
+
+enum
+{
+#define _(f) HICN_TCP_FLAG_BIT_##f,
+ foreach_tcp_flag
+#undef _
+ HICN_TCP_N_FLAG_BITS,
+};
+
+enum
+{
+#define _(f) HICN_TCP_FLAG_##f = 1 << HICN_TCP_FLAG_BIT_##f,
+ foreach_tcp_flag
+#undef _
+};
+
+#endif /* HICN_PROTOCOL_TCP_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/udp.c b/lib/src/protocol/udp.c
new file mode 100644
index 000000000..56de0065f
--- /dev/null
+++ b/lib/src/protocol/udp.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <hicn/common.h>
+#include <hicn/error.h>
+
+#include "udp.h"
+#include "../ops.h"
+
+DECLARE_get_interest_locator (udp, UNEXPECTED);
+DECLARE_set_interest_locator (udp, UNEXPECTED);
+DECLARE_get_interest_name (udp, UNEXPECTED);
+DECLARE_set_interest_name (udp, UNEXPECTED);
+DECLARE_get_data_locator (udp, UNEXPECTED);
+DECLARE_set_data_locator (udp, UNEXPECTED);
+DECLARE_get_data_name (udp, UNEXPECTED);
+DECLARE_set_data_name (udp, UNEXPECTED);
+DECLARE_set_payload_len (udp, UNEXPECTED);
+
+int
+udp_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos)
+{
+ pkbuf->udp = pkbuf->len;
+ if (UDP_HDRLEN > pkbuf->buffer_size - pkbuf->len)
+ return -1;
+ pkbuf->len += UDP_HDRLEN;
+
+ _udp_header_t *udp = pkbuf_get_udp (pkbuf);
+
+ size_t len = hicn_packet_get_len (pkbuf) -
+ ((u8 *) udp - pkbuf_get_header (pkbuf)) -
+ sizeof (_udp_header_t);
+
+ // clang-format off
+ *udp = (_udp_header_t){
+ .src_port = 0,
+ .dst_port = 0,
+ .len = htons ((u16) len),
+ .checksum = 0
+ };
+ // clang-format on
+ return CALL_CHILD (init_packet_header, pkbuf, pos);
+}
+
+int
+udp_get_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_name_suffix_t *suffix)
+{
+ return CALL_CHILD (get_interest_name_suffix, pkbuf, pos, suffix);
+}
+
+int
+udp_set_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_name_suffix_t *suffix)
+{
+ return CALL_CHILD (set_interest_name_suffix, pkbuf, pos, suffix);
+}
+
+int
+udp_get_type (const hicn_packet_buffer_t *pkbuf, const size_t pos,
+ hicn_packet_type_t *type)
+{
+ return CALL_CHILD (get_type, pkbuf, pos, type);
+}
+
+int
+udp_set_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_packet_type_t type)
+{
+ return CALL_CHILD (set_type, pkbuf, pos, type);
+}
+
+int
+udp_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
+{
+ return CALL_CHILD (reset_interest_for_hash, pkbuf, pos);
+}
+
+int
+udp_get_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_name_suffix_t *suffix)
+{
+ return CALL_CHILD (get_data_name_suffix, pkbuf, pos, suffix);
+}
+
+int
+udp_set_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_name_suffix_t *suffix)
+{
+ return CALL_CHILD (set_data_name_suffix, pkbuf, pos, suffix);
+}
+
+int
+udp_get_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_path_label_t *path_label)
+{
+ return CALL_CHILD (get_data_path_label, pkbuf, pos, path_label);
+}
+
+int
+udp_set_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_path_label_t path_label)
+{
+ return CALL_CHILD (set_data_path_label, pkbuf, pos, path_label);
+}
+
+int
+udp_update_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_faceid_t face_id)
+{
+ return CALL_CHILD (update_data_path_label, pkbuf, pos, face_id);
+}
+
+int
+udp_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos)
+{
+ return CALL_CHILD (reset_data_for_hash, pkbuf, pos);
+}
+
+int
+udp_get_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_lifetime_t *lifetime)
+{
+ return CALL_CHILD (get_lifetime, pkbuf, pos, lifetime);
+}
+
+int
+udp_set_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_lifetime_t lifetime)
+{
+ return CALL_CHILD (set_lifetime, pkbuf, pos, lifetime);
+}
+
+int
+udp_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
+{
+ return CALL_CHILD (update_checksums, pkbuf, pos, partial_csum, payload_len);
+}
+
+int
+udp_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf,
+ size_t pos, u16 *old_val, u16 *new_val,
+ u8 size, bool skip_first)
+{
+ return CALL_CHILD (update_checksums_incremental, pkbuf, pos, old_val,
+ new_val, size, false);
+}
+
+int
+udp_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ u16 partial_csum, size_t payload_len)
+{
+ return CALL_CHILD (verify_checksums, pkbuf, pos, partial_csum, payload_len);
+}
+
+int
+udp_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old)
+{
+ return CALL_CHILD (rewrite_interest, pkbuf, pos, addr_new, addr_old);
+}
+
+int
+udp_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ const hicn_ip_address_t *addr_new,
+ hicn_ip_address_t *addr_old, const hicn_faceid_t face_id,
+ u8 reset_pl)
+{
+ return CALL_CHILD (rewrite_data, pkbuf, pos, addr_new, addr_old, face_id,
+ reset_pl);
+}
+
+int
+udp_get_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_payload_type_t *payload_type)
+{
+ return CALL_CHILD (get_payload_type, pkbuf, pos, payload_type);
+}
+
+int
+udp_set_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ hicn_payload_type_t payload_type)
+{
+ return CALL_CHILD (set_payload_type, pkbuf, pos, payload_type);
+}
+
+int
+udp_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t *signature_size)
+{
+ return CALL_CHILD (get_signature_size, pkbuf, pos, signature_size);
+}
+
+int
+udp_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t signature_size)
+{
+ return CALL_CHILD (set_signature_size, pkbuf, pos, signature_size);
+}
+
+int
+udp_has_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, bool *flag)
+{
+ return CALL_CHILD (has_signature, pkbuf, pos, flag);
+}
+
+int
+udp_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t padding)
+{
+ return CALL_CHILD (set_signature_padding, pkbuf, pos, padding);
+}
+
+int
+udp_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ size_t *padding)
+{
+ return CALL_CHILD (get_signature_padding, pkbuf, pos, padding);
+}
+
+int
+udp_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint64_t signature_timestamp)
+{
+ return CALL_CHILD (set_signature_timestamp, pkbuf, pos, signature_timestamp);
+}
+
+int
+udp_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint64_t *signature_timestamp)
+{
+ return CALL_CHILD (get_signature_timestamp, pkbuf, pos, signature_timestamp);
+}
+
+int
+udp_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t validation_algorithm)
+{
+ return CALL_CHILD (set_validation_algorithm, pkbuf, pos,
+ validation_algorithm);
+}
+
+int
+udp_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t *validation_algorithm)
+{
+ return CALL_CHILD (get_validation_algorithm, pkbuf, pos,
+ validation_algorithm);
+}
+
+int
+udp_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t *key_id,
+ size_t key_len)
+{
+ return CALL_CHILD (set_key_id, pkbuf, pos, key_id, key_len);
+}
+
+int
+udp_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t **key_id, uint8_t *key_id_size)
+{
+ return CALL_CHILD (get_key_id, pkbuf, pos, key_id, key_id_size);
+}
+
+int
+udp_get_signature (const hicn_packet_buffer_t *pkbuf, size_t pos,
+ uint8_t **signature)
+{
+ return CALL_CHILD (get_signature, pkbuf, pos, signature);
+}
+
+int
+udp_is_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos, int *is_last)
+{
+ return CALL_CHILD (is_last_data, pkbuf, pos, is_last);
+}
+
+int
+udp_set_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos)
+{
+ return CALL_CHILD (set_last_data, pkbuf, pos);
+}
+
+DECLARE_HICN_OPS (udp, UDP_HDRLEN);
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/udp.h b/lib/src/protocol/udp.h
new file mode 100644
index 000000000..23f5317b3
--- /dev/null
+++ b/lib/src/protocol/udp.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HICN_PROTOCOL_UDP_H
+#define HICN_PROTOCOL_UDP_H
+
+/*
+ * The len of the UDP header struct must be 8 bytes.
+ */
+#define EXPECTED_UDP_HDRLEN 8
+
+typedef struct
+{
+ u16 src_port;
+ u16 dst_port;
+ u16 len;
+ u16 checksum;
+} _udp_header_t;
+
+#define UDP_HDRLEN sizeof (_udp_header_t)
+static_assert (EXPECTED_UDP_HDRLEN == UDP_HDRLEN,
+ "Size of UDP struct does not match its expected size.");
+
+#endif /* HICN_PROTOCOL_UDP_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/strategy.c b/lib/src/strategy.c
new file mode 100644
index 000000000..3b797664a
--- /dev/null
+++ b/lib/src/strategy.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/strategy.h>
+
+const char *strategy_str[] = {
+#define _(x) [STRATEGY_TYPE_##x] = #x,
+ foreach_strategy_type
+#undef _
+}; \ No newline at end of file
diff --git a/lib/src/test/CMakeLists.txt b/lib/src/test/CMakeLists.txt
new file mode 100644
index 000000000..8cf4359d2
--- /dev/null
+++ b/lib/src/test/CMakeLists.txt
@@ -0,0 +1,55 @@
+# Copyright (c) 2021-2022 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+find_package(Threads REQUIRED)
+
+##############################################################
+# Test sources
+##############################################################
+list(APPEND TESTS_SRC
+ main.cc
+ test_name.cc
+ test_new_header.cc
+ test_udp_header.cc
+ test_validation.cc
+ test_bitmap.cc
+ test_interest_manifest.cc
+ test_ip_address.cc
+ test_khash.cc
+ test_pool.cc
+ test_ring.cc
+ test_slab.cc
+ test_vector.cc
+)
+
+##############################################################
+# Build single unit test executable and add it to test list
+##############################################################
+build_executable(lib_tests
+ NO_INSTALL
+ SOURCES ${TESTS_SRC}
+ LINK_LIBRARIES
+ PRIVATE ${LIBHICN_STATIC}
+ PRIVATE ${GTEST_LIBRARIES}
+ PRIVATE ${CMAKE_THREAD_LIBS_INIT}
+ INCLUDE_DIRS
+ PRIVATE ${Libhicn_INCLUDE_DIRS}
+ PRIVATE ${GTEST_INCLUDE_DIRS}
+ DEPENDS gtest ${LIBHICN_SHARED}
+ COMPONENT ${LIBHICN_COMPONENT}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${DEFAULT_COMPILER_OPTIONS}
+ LINK_FLAGS ${LINK_FLAGS}
+)
+
+add_test_internal(lib_tests)
diff --git a/lib/src/test/main.cc b/lib/src/test/main.cc
new file mode 100644
index 000000000..042fcd6c0
--- /dev/null
+++ b/lib/src/test/main.cc
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+int
+main (int argc, char **argv)
+{
+ ::testing::InitGoogleTest (&argc, argv);
+ return RUN_ALL_TESTS ();
+}
diff --git a/lib/src/test/test_bitmap.cc b/lib/src/test/test_bitmap.cc
new file mode 100644
index 000000000..7fc8eef71
--- /dev/null
+++ b/lib/src/test/test_bitmap.cc
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <netinet/in.h>
+
+extern "C"
+{
+#define WITH_TESTS
+#include <hicn/util/bitmap.h>
+}
+
+#define DEFAULT_SIZE 10
+
+class BitmapTest : public ::testing::Test
+{
+protected:
+ BitmapTest () {}
+
+ virtual ~BitmapTest () {}
+
+ bitmap_t *bitmap;
+};
+
+/*
+ * TEST: bitmap allocation
+ */
+TEST_F (BitmapTest, BitmapAllocation)
+{
+ int rc;
+
+ /*
+ * 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);
+
+ /*
+ * Bitmap should have been allocated with a size rounded to the next power
+ * of 2
+ */
+ EXPECT_EQ (bitmap_get_alloc_size (bitmap), 1UL);
+
+ /* 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), 1UL);
+
+ 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), 1UL);
+
+ /* 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), 1UL);
+
+ /* 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), 2UL);
+
+ rc = bitmap_set (bitmap, sizeof (bitmap[0]) * 8 + 1);
+ EXPECT_GE (rc, 0);
+ EXPECT_EQ (bitmap_get_alloc_size (bitmap), 2UL);
+
+ 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), 1UL);
+
+ bitmap_free (bitmap);
+}
+
+TEST_F (BitmapTest, BitmapSet)
+{
+ 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));
+
+ // Test edge cases (i.e. start and end of block)
+ off_t start_position = 0;
+ bitmap_set (bitmap, start_position);
+ EXPECT_TRUE (bitmap_is_set (bitmap, start_position));
+ EXPECT_FALSE (bitmap_is_unset (bitmap, start_position));
+
+ off_t end_position = BITMAP_WIDTH (bitmap) - 1;
+ bitmap_set (bitmap, end_position);
+ EXPECT_TRUE (bitmap_is_set (bitmap, end_position));
+ EXPECT_FALSE (bitmap_is_unset (bitmap, end_position));
+
+ bitmap_free (bitmap);
+}
+
+TEST_F (BitmapTest, BitmapUnSet)
+{
+ 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_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);
+}
+
+TEST_F (BitmapTest, BitmapFirstSet)
+{
+ bitmap_init (bitmap, DEFAULT_SIZE, 0);
+
+ // Get first set bit. It should be INVALID_INDEX
+ EXPECT_EQ (bitmap_first_set (bitmap), BITMAP_INVALID_INDEX);
+
+ // set bit 40
+ bitmap_set (bitmap, 40);
+ EXPECT_TRUE (bitmap_is_set (bitmap, 40));
+
+ // Get first set bit. It should be bit 40 (surprise):)
+ EXPECT_EQ (bitmap_first_set (bitmap), hicn_uword (40));
+
+ // set bit 3
+ bitmap_set (bitmap, 3);
+ EXPECT_TRUE (bitmap_is_set (bitmap, 3));
+
+ // The first set bit now should be bit #3
+ EXPECT_EQ (bitmap_first_set (bitmap), hicn_uword (3));
+
+ bitmap_free (bitmap);
+}
+
+TEST_F (BitmapTest, BitmapFirstUnSet)
+{
+ bitmap_init (bitmap, DEFAULT_SIZE, 0);
+
+ // Get first unset bit. It should be 0
+ EXPECT_EQ (bitmap_first_unset (bitmap), hicn_uword (0));
+
+ // set bit 0
+ bitmap_set (bitmap, 0);
+ EXPECT_TRUE (bitmap_is_set (bitmap, 0));
+
+ // Get first unset bit. It should be bit 1
+ EXPECT_EQ (bitmap_first_unset (bitmap), hicn_uword (1));
+
+ // set bit 3
+ bitmap_set (bitmap, 3);
+ EXPECT_TRUE (bitmap_is_set (bitmap, 3));
+
+ // The first set bit now should be still 1
+ EXPECT_EQ (bitmap_first_unset (bitmap), hicn_uword (1));
+
+ bitmap_free (bitmap);
+}
+
+TEST_F (BitmapTest, BitmapNextSet)
+{
+ bitmap_init (bitmap, DEFAULT_SIZE, 0);
+
+ // Get next unset bit >= 0. It should be INVALID
+ EXPECT_EQ (bitmap_next_set (bitmap, 0), BITMAP_INVALID_INDEX);
+
+ // set bit 0
+ bitmap_set (bitmap, 0);
+ EXPECT_TRUE (bitmap_is_set (bitmap, 0));
+
+ // Get next set bit >= 0. It should be bit 0
+ EXPECT_EQ (bitmap_next_set (bitmap, 0), hicn_uword (0));
+
+ // set bit 3
+ bitmap_set (bitmap, 3);
+ EXPECT_TRUE (bitmap_is_set (bitmap, 3));
+
+ // Get next set bit >= 1. It should be 3
+ EXPECT_EQ (bitmap_next_set (bitmap, 1), hicn_uword (3));
+
+ // set (N-2)th bit
+ bitmap_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 2);
+ EXPECT_TRUE (bitmap_is_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 2));
+ EXPECT_EQ (bitmap_next_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 3),
+ DEFAULT_SIZE * WORD_WIDTH - 2);
+
+ // set (N-1)th bit
+ bitmap_unset (bitmap, DEFAULT_SIZE * WORD_WIDTH - 2);
+ bitmap_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 1);
+ EXPECT_TRUE (bitmap_is_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 1));
+ EXPECT_EQ (bitmap_next_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 2),
+ DEFAULT_SIZE * WORD_WIDTH - 1);
+ EXPECT_EQ (bitmap_next_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 1),
+ DEFAULT_SIZE * WORD_WIDTH - 1);
+
+ bitmap_free (bitmap);
+}
+
+TEST_F (BitmapTest, BitmapNextUnSet)
+{
+ bitmap_init (bitmap, DEFAULT_SIZE, 0);
+
+ // Get next unset bit >= 0. It should be 0
+ EXPECT_EQ (bitmap_next_unset (bitmap, 0), hicn_uword (0));
+
+ // set bit 0
+ bitmap_set (bitmap, 0);
+ EXPECT_TRUE (bitmap_is_set (bitmap, 0));
+
+ // Get next set bit >= 0. It should be bit 1
+ EXPECT_EQ (bitmap_next_unset (bitmap, 0), hicn_uword (1));
+
+ // set bit 3
+ bitmap_set (bitmap, 3);
+ EXPECT_TRUE (bitmap_is_set (bitmap, 3));
+
+ // Get next unset bit after 3. It should be 4
+ EXPECT_EQ (bitmap_next_unset (bitmap, 3), hicn_uword (4));
+
+ bitmap_free (bitmap);
+}
diff --git a/lib/src/test/test_interest_manifest.cc b/lib/src/test/test_interest_manifest.cc
new file mode 100644
index 000000000..25ac83728
--- /dev/null
+++ b/lib/src/test/test_interest_manifest.cc
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+extern "C"
+{
+#include <hicn/interest_manifest.h>
+}
+
+static constexpr hicn_uword WORD_SIZE = WORD_WIDTH;
+
+class InterestManifestTest : public ::testing::Test
+{
+protected:
+ static constexpr u32 n_suffixes = 0x00000014 + 1;
+ static constexpr u32 padding = 0x21232425;
+ static constexpr hicn_uword bitmap_word = ~0ULL;
+ static inline std::vector<uint32_t> values = { 10, 22, 23, 43, 54, 65, 66,
+ 4, 33, 2, 44, 99, 87, 67,
+ 78, 98, 76, 1, 7, 123 };
+ InterestManifestTest () {}
+ virtual ~InterestManifestTest () {}
+
+ uint8_t buffer[512];
+ hicn_uword bitmap_saved[BITMAP_SIZE];
+};
+
+TEST_F (InterestManifestTest, OneWordBitmapUpdate)
+{
+ hicn_uword initial_bitmap[1];
+ hicn_uword curr_bitmap[1] = { 0 };
+ initial_bitmap[0] =
+ 0x0000000000000b07; // ...000000000000000000000101100000111
+
+ // Consume first 4 'one' bits (i.e. suffixes), reaching position 9
+ size_t pos = 0, max_suffixes = 4;
+ pos = interest_manifest_update_bitmap (initial_bitmap, curr_bitmap, pos,
+ WORD_SIZE, max_suffixes);
+ EXPECT_EQ (pos, std::size_t (9));
+ EXPECT_EQ (curr_bitmap[0], hicn_uword (0x0000000000000107));
+
+ // Consume the remaining 2 'one' bits, reaching end of bitmap
+ hicn_uword curr_bitmap2[1] = { 0 };
+ pos = interest_manifest_update_bitmap (initial_bitmap, curr_bitmap2, pos,
+ WORD_SIZE, max_suffixes);
+ EXPECT_EQ (pos, WORD_SIZE);
+ EXPECT_EQ (curr_bitmap2[0], hicn_uword (0x00000a00));
+
+ // Consume all suffixes at once
+ hicn_uword curr_bitmap3[1] = { 0 };
+ max_suffixes = 16;
+ pos = interest_manifest_update_bitmap (initial_bitmap, curr_bitmap3, 0,
+ WORD_SIZE, max_suffixes);
+ EXPECT_EQ (pos, WORD_SIZE);
+ EXPECT_EQ (curr_bitmap3[0], initial_bitmap[0]);
+}
+
+TEST_F (InterestManifestTest, TwoWordBitmapUpdate)
+{
+ hicn_uword initial_bitmap[2];
+ initial_bitmap[0] = 0x0000000000000b07;
+ initial_bitmap[1] = 0x0000000000000b07;
+ // -> 0000000000000000000010110000011100000000000000000000101100000111
+
+ int expected_pos[] = { WORD_SIZE + 2, 2 * WORD_SIZE };
+ u32 expected_bitmap[][2] = { { 0x00000b07, 0x00000003 },
+ { 0x0, 0x00000b04 } };
+
+ // Loop to consume all suffixes
+ int pos = 0, max_suffixes = 8, i = 0, len = WORD_SIZE * 2;
+ while (pos != len)
+ {
+ hicn_uword curr_bitmap[2] = { 0 };
+ pos = interest_manifest_update_bitmap (initial_bitmap, curr_bitmap, pos,
+ len, max_suffixes);
+
+ EXPECT_EQ (pos, expected_pos[i]);
+ EXPECT_EQ (curr_bitmap[0], expected_bitmap[i][0]);
+ EXPECT_EQ (curr_bitmap[1], expected_bitmap[i][1]);
+ i++;
+ }
+}
+
+TEST_F (InterestManifestTest, SerializeDeserialize)
+{
+#if hicn_uword_bits == 64
+#define F(x) hicn_host_to_net_64 (x)
+#elif hicn_uword_bits == 32
+#define F(x) hicn_host_to_net_32 (x)
+#else
+#error "Unrecognized architecture"
+#endif
+
+ auto header = reinterpret_cast<interest_manifest_header_t *> (buffer);
+ interest_manifest_init (header, 0);
+
+ for (const auto &v : values)
+ {
+ interest_manifest_add_suffix (header, v);
+ }
+
+ EXPECT_EQ (header->n_suffixes, n_suffixes);
+
+ // Save bitmap
+ memcpy (bitmap_saved, header->request_bitmap, sizeof (bitmap_saved));
+
+ // Serialize manifest
+ interest_manifest_serialize (header);
+
+ // If architecture is little endian, bytes should be now swapped
+ EXPECT_THAT (header->n_suffixes, ::testing::Eq (hicn_host_to_net_32 (
+ n_suffixes) /* 0x14000000 */));
+
+ for (unsigned i = 0; i < BITMAP_SIZE; i++)
+ {
+ EXPECT_THAT (header->request_bitmap[i],
+ ::testing::Eq (F (bitmap_saved[i])));
+ }
+
+ hicn_name_suffix_t *suffix = (hicn_name_suffix_t *) (header + 1);
+ for (unsigned i = 0; i < n_suffixes; i++)
+ {
+ if (i == 0)
+ {
+ EXPECT_THAT (*(suffix + i), ::testing::Eq (hicn_name_suffix_t (0)));
+ }
+ else
+ {
+ EXPECT_THAT (*(suffix + i),
+ ::testing::Eq (hicn_host_to_net_32 (values[i - 1])));
+ }
+ }
+
+ // Deserialize manifest
+ interest_manifest_deserialize (header);
+
+ // Bytes should now be as before
+ EXPECT_THAT (header->n_suffixes, ::testing::Eq (n_suffixes));
+
+ int i = 0;
+ unsigned long pos;
+ interest_manifest_foreach_suffix (header, suffix, pos)
+ {
+ if (pos == 0)
+ {
+ EXPECT_THAT (*suffix, ::testing::Eq (hicn_name_suffix_t (0)));
+ }
+ else
+ {
+ EXPECT_THAT (*suffix, ::testing::Eq (values[i]));
+ i++;
+ }
+ }
+}
+
+TEST_F (InterestManifestTest, ForEach)
+{
+ unsigned long pos;
+ hicn_name_suffix_t *suffix = nullptr;
+ auto header = reinterpret_cast<interest_manifest_header_t *> (buffer);
+ interest_manifest_init (header, 0);
+
+ for (const auto &v : values)
+ {
+ interest_manifest_add_suffix (header, v);
+ }
+
+ // Iterate over interest manifest. bBbitmap should be all 1, we should be
+ // able to iterate over all suffixes.
+ interest_manifest_foreach_suffix (header, suffix, pos)
+ {
+ if (pos == 0)
+ {
+ EXPECT_EQ (*suffix, hicn_name_suffix_t (0));
+ }
+ else
+ {
+ EXPECT_EQ (*suffix, values[pos - 1]);
+ }
+ }
+
+ std::set<uint32_t> set_values (values.begin (), values.end ());
+
+ // Unset few bitmap positions
+ interest_manifest_del_suffix (header, 5 + 1);
+ set_values.erase (values[5]);
+
+ interest_manifest_del_suffix (header, 6 + 1);
+ set_values.erase (values[6]);
+
+ interest_manifest_del_suffix (header, 12 + 1);
+ set_values.erase (values[12]);
+
+ interest_manifest_del_suffix (header, 17 + 1);
+ set_values.erase (values[17]);
+
+ // Iterate over interest manifest and remove elements in manifest from set.
+ // The set should be empty at the end.
+ interest_manifest_foreach_suffix (header, suffix, pos)
+ {
+ if (pos > 0)
+ {
+ EXPECT_TRUE (set_values.find (*suffix) != set_values.end ())
+ << "The value was " << *suffix;
+ set_values.erase (*suffix);
+ }
+ }
+
+ EXPECT_TRUE (set_values.empty ());
+} \ No newline at end of file
diff --git a/lib/src/test/test_ip_address.cc b/lib/src/test/test_ip_address.cc
new file mode 100644
index 000000000..1a7efb603
--- /dev/null
+++ b/lib/src/test/test_ip_address.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern "C"
+{
+#define WITH_TESTS
+#include <hicn/util/ip_address.h>
+}
+
+#define DEFAULT_SIZE 10
+
+class IPAddressTest : public ::testing::Test
+{
+protected:
+ IPAddressTest () {}
+
+ virtual ~IPAddressTest () {}
+};
+
+TEST_F (IPAddressTest, IPAddressGetBit)
+{
+ hicn_ip_address_t a_0, a_1, a_1_0, a_1_1, a_1_48, a_1_49, a_1_63, a_1_64,
+ a_1_127;
+
+ hicn_ip_address_pton ("0::0", &a_0);
+ hicn_ip_address_pton ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", &a_1);
+
+ hicn_ip_address_pton ("8000::0", &a_1_0);
+ hicn_ip_address_pton ("4000::0", &a_1_1);
+ hicn_ip_address_pton ("0:0:0:8000::0", &a_1_48);
+ hicn_ip_address_pton ("0:0:0:4000::0", &a_1_49);
+ hicn_ip_address_pton ("0:0:0:1::0", &a_1_63);
+ hicn_ip_address_pton ("0::8000:0:0:0", &a_1_64);
+ hicn_ip_address_pton ("0::1", &a_1_127);
+
+#if 0
+ for (unsigned i = 0; i < 128; i++)
+ EXPECT_EQ (hicn_ip_address_get_bit (&a_0, i), 0);
+ for (unsigned i = 0; i < 128; i++)
+ EXPECT_EQ (hicn_ip_address_get_bit (&a_1, i), 1);
+#endif
+ for (unsigned i = 0; i < 128; i++)
+ EXPECT_EQ (hicn_ip_address_get_bit (&a_1_0, i), (i == 0) ? 1 : 0);
+ for (unsigned i = 0; i < 128; i++)
+ EXPECT_EQ (hicn_ip_address_get_bit (&a_1_1, i), (i == 1) ? 1 : 0);
+ for (unsigned i = 0; i < 128; i++)
+ EXPECT_EQ (hicn_ip_address_get_bit (&a_1_48, i), (i == 48) ? 1 : 0);
+ for (unsigned i = 0; i < 128; i++)
+ EXPECT_EQ (hicn_ip_address_get_bit (&a_1_49, i), (i == 49) ? 1 : 0);
+ for (unsigned i = 0; i < 128; i++)
+ EXPECT_EQ (hicn_ip_address_get_bit (&a_1_63, i), (i == 63) ? 1 : 0);
+ for (unsigned i = 0; i < 128; i++)
+ EXPECT_EQ (hicn_ip_address_get_bit (&a_1_64, i), (i == 64) ? 1 : 0);
+ for (unsigned i = 0; i < 128; i++)
+ EXPECT_EQ (hicn_ip_address_get_bit (&a_1_127, i), (i == 127) ? 1 : 0);
+}
diff --git a/lib/src/test/test_khash.cc b/lib/src/test/test_khash.cc
new file mode 100644
index 000000000..da6b62071
--- /dev/null
+++ b/lib/src/test/test_khash.cc
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <netinet/in.h>
+
+extern "C"
+{
+#include <hicn/util/khash.h>
+}
+
+KHASH_MAP_INIT_INT (int, unsigned char)
+
+typedef struct
+{
+ unsigned key;
+ unsigned char val;
+} int_unpack_t;
+
+typedef struct
+{
+ unsigned key;
+ unsigned char val;
+} __attribute__ ((__packed__)) int_packed_t;
+
+#define hash_eq(a, b) ((a).key == (b).key)
+#define hash_func(a) ((a).key)
+
+KHASH_INIT (iun, int_unpack_t, char, 0, hash_func, hash_eq)
+KHASH_INIT (ipk, int_packed_t, char, 0, hash_func, hash_eq)
+
+class KHashTest : public ::testing::Test
+{
+protected:
+ KHashTest () {}
+
+ virtual ~KHashTest ()
+ {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void
+ SetUp ()
+ {
+ khash = kh_init (int);
+ }
+
+ virtual void
+ TearDown ()
+ {
+ kh_destroy (int, khash);
+ }
+ khash_t (int) * khash;
+};
+
+TEST_F (KHashTest, KhashIntSize)
+{
+ int ret;
+ int k;
+ int size = kh_size (khash);
+
+ EXPECT_EQ (size, 0);
+ k = kh_put (int, khash, 10, &ret);
+ if (ret == 1)
+ {
+ kh_val (khash, k) = 10;
+ }
+ size = kh_size (khash);
+ EXPECT_EQ (size, 1);
+}
+
+TEST_F (KHashTest, KhashIntPut)
+{
+ int ret;
+ int k;
+ k = kh_put (int, khash, 10, &ret);
+ if (ret == 1)
+ {
+ kh_val (khash, k) = 10;
+ }
+ int size = kh_size (khash);
+ EXPECT_EQ (size, 1);
+ k = kh_put (int, khash, 20, &ret);
+ if (ret == 1)
+ {
+ kh_val (khash, k) = 20;
+ }
+ size = kh_size (khash);
+ EXPECT_EQ (size, 2);
+}
+
+TEST_F (KHashTest, KhashCheckValue)
+{
+ int ret;
+ int k;
+ k = kh_put (int, khash, 10, &ret);
+ if (ret == 1)
+ {
+ kh_val (khash, k) = 100;
+ }
+ k = kh_put (int, khash, 20, &ret);
+ if (ret == 1)
+ {
+ kh_val (khash, k) = 200;
+ }
+
+ k = kh_put (int, khash, 10, &ret);
+ int val = -1;
+ if (!ret)
+ val = kh_val (khash, k);
+ EXPECT_EQ (val, 100);
+
+ k = kh_put (int, khash, 20, &ret);
+ val = -1;
+ if (!ret)
+ val = kh_val (khash, k);
+ EXPECT_EQ (val, 200);
+}
+
+// Check that there are no collisions in case of same key hash
+typedef struct
+{
+ int x;
+} Key;
+#define hash_key(key) 1 // Hash is always 1 to simulate collisions
+#define key_hash_eq(a, b) (a->x == b->x) // Function used in case of collisions
+KHASH_INIT (test_map, const Key *, unsigned, 1, hash_key, key_hash_eq);
+
+TEST_F (KHashTest, Collisions)
+{
+ int ret;
+ khiter_t k;
+
+ kh_test_map_t *map = kh_init (test_map);
+ Key key1 = { .x = 10 };
+ Key key2 = { .x = 11 };
+
+ k = kh_put_test_map (map, &key1, &ret);
+ ASSERT_EQ (ret, 1);
+ kh_val (map, k) = 15u;
+
+ k = kh_put_test_map (map, &key2, &ret);
+ ASSERT_EQ (ret, 1);
+ kh_val (map, k) = 27u;
+
+ k = kh_get_test_map (map, &key1);
+ ASSERT_NE (k, kh_end (map));
+ unsigned val = kh_val (map, k);
+ EXPECT_EQ (val, 15u);
+
+ k = kh_get_test_map (map, &key2);
+ ASSERT_NE (k, kh_end (map));
+ val = kh_val (map, k);
+ EXPECT_EQ (val, 27u);
+
+ kh_destroy_test_map (map);
+}
diff --git a/lib/src/test/test_name.cc b/lib/src/test/test_name.cc
new file mode 100644
index 000000000..0cf160f70
--- /dev/null
+++ b/lib/src/test/test_name.cc
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+extern "C"
+{
+#include <hicn/name.h>
+#include <hicn/common.h>
+#include <hicn/error.h>
+}
+
+class NameTest : public ::testing::Test
+{
+protected:
+ const char *ipv6_prefix = "b001::abcd:1234:abcd:1234";
+ const char *ipv4_prefix = "12.13.14.15";
+ const uint32_t suffix = 12345;
+
+ NameTest () : name_{}, name4_{}, name6_{}
+ {
+ ipv6_prefix_bytes = {};
+ int rc = inet_pton (AF_INET6, ipv6_prefix, &ipv6_prefix_bytes.v6);
+ EXPECT_EQ (rc, 1);
+
+ ipv4_prefix_bytes = {};
+ rc = inet_pton (AF_INET, ipv4_prefix, &ipv4_prefix_bytes.v4);
+ EXPECT_EQ (rc, 1);
+
+ rc = hicn_name_create (ipv4_prefix, suffix, &name4_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_name_create (ipv6_prefix, suffix, &name6_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ }
+
+ virtual ~NameTest () {}
+
+ void
+ nameHashTest (const char *prefix)
+ {
+ // Create 2 names
+ uint32_t suffix = 13579;
+ hicn_name_t name_a, name_b;
+ int rc = hicn_name_create (prefix, suffix, &name_a);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_name_create (prefix, suffix, &name_b);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // The hash should be equal, with and without considering the suffix
+ uint32_t hash_a, hash_b;
+ hash_a = hicn_name_get_hash (&name_a);
+ hash_b = hicn_name_get_hash (&name_b);
+ EXPECT_EQ (hash_a, hash_b);
+
+ hash_a = hicn_name_get_prefix_hash (&name_a);
+ hash_b = hicn_name_get_prefix_hash (&name_b);
+ EXPECT_EQ (hash_a, hash_b);
+
+ // Now let's change the suffix
+ rc = hicn_name_set_suffix (&name_a, 97531);
+ // They should result equal if we do not consider the suffix
+ hash_a = hicn_name_get_prefix_hash (&name_a);
+ hash_b = hicn_name_get_prefix_hash (&name_b);
+ EXPECT_EQ (hash_a, hash_b);
+
+ // And different if we consider it
+ hash_a = hicn_name_get_hash (&name_a);
+ hash_b = hicn_name_get_hash (&name_b);
+ EXPECT_NE (hash_a, hash_b);
+ }
+
+ void
+ nameCopyTest (const char *prefix)
+ {
+ uint32_t suffix = 13579;
+ hicn_name_t name_a, name_b;
+ int rc = hicn_name_create (prefix, suffix, &name_a);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_name_copy (&name_b, &name_a);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_name_compare (&name_a, &name_b, 1);
+ EXPECT_EQ (rc, 0);
+ }
+
+ void
+ nameCompareTest (const char *prefix)
+ {
+ // Create 2 names
+ uint32_t suffix = 13579;
+ hicn_name_t name_a, name_b;
+ int rc = hicn_name_create (prefix, suffix, &name_a);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_name_create (prefix, suffix, &name_b);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // They should be equal, with and without considering the suffix
+ rc = hicn_name_compare (&name_a, &name_b, 1);
+ EXPECT_EQ (rc, 0);
+ rc = hicn_name_compare (&name_a, &name_b, 0);
+ EXPECT_EQ (rc, 0);
+
+ // Now let's change the suffix
+ rc = hicn_name_set_suffix (&name_a, 97531);
+ // They should result equal if we do not consider the suffix
+ rc = hicn_name_compare (&name_a, &name_b, 0);
+ EXPECT_EQ (rc, 0);
+ // And different if we consider the suffix
+ rc = hicn_name_compare (&name_a, &name_b, 1);
+ EXPECT_NE (rc, 0);
+ }
+
+ void
+ nameFromIpPrefixTest (const hicn_ip_prefix_t &hicn_ip_prefix)
+ {
+ uint32_t suffix = 54321;
+ hicn_name_t name;
+ int rc = hicn_name_create_from_ip_prefix (&hicn_ip_prefix, suffix, &name);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = memcmp (hicn_ip_prefix.address.v6.as_u8, name.prefix.v6.as_u8,
+ sizeof (name.prefix.v6));
+ EXPECT_EQ (rc, 0);
+ EXPECT_EQ (suffix, name.suffix);
+ }
+
+ void
+ nameToIpPrefixTest (const char *prefix)
+ {
+ uint32_t suffix = 54321;
+ hicn_name_t name;
+ int rc = hicn_name_create (prefix, suffix, &name);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Get family
+ int family;
+ rc = hicn_name_get_family (&name, &family);
+
+ hicn_ip_prefix_t hicn_ip_prefix;
+ rc = hicn_name_to_hicn_ip_prefix (&name, &hicn_ip_prefix);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hicn_ip_prefix.family, family);
+ rc = hicn_ip_address_cmp (&hicn_ip_prefix.address, &name.prefix);
+ EXPECT_EQ (rc, 0);
+ }
+
+ hicn_name_t name_, name4_, name6_;
+ hicn_ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes;
+};
+
+/**
+ * Name Initialization
+ */
+TEST_F (NameTest, NameInitialization)
+{
+ EXPECT_TRUE (_is_unspec (&name_));
+ uint32_t suffix = 12345;
+
+ // Initialize ipv6 name
+ hicn_name_t name6;
+ int rc = hicn_name_create (ipv6_prefix, suffix, &name6);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check name is correctly created
+ rc = hicn_ip_address_cmp (&name6.prefix, &ipv6_prefix_bytes);
+ EXPECT_EQ (rc, 0);
+ EXPECT_EQ (name6.suffix, suffix);
+
+ // Initialize ipv4 name
+ hicn_name_t name4;
+ rc = hicn_name_create (ipv4_prefix, suffix, &name4);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check name is correctly created
+ rc = hicn_ip_address_cmp (&name4.prefix, &ipv4_prefix_bytes);
+ EXPECT_EQ (name4.prefix.pad[0], 0UL);
+ EXPECT_EQ (name4.prefix.pad[1], 0UL);
+ EXPECT_EQ (name4.prefix.pad[2], 0UL);
+ EXPECT_EQ (rc, 0);
+ EXPECT_EQ (name4.suffix, suffix);
+
+ // Try also to reuse previously initialized name
+ rc = hicn_name_create (ipv4_prefix, suffix, &name6);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check name is correctly created
+ rc = hicn_ip_address_cmp (&name6.prefix, &ipv4_prefix_bytes);
+ EXPECT_EQ (name6.prefix.pad[0], 0UL);
+ EXPECT_EQ (name6.prefix.pad[1], 0UL);
+ EXPECT_EQ (name6.prefix.pad[2], 0UL);
+ EXPECT_EQ (rc, 0);
+ EXPECT_EQ (name6.suffix, suffix);
+}
+
+/**
+ * Name from ip prefix
+ */
+TEST_F (NameTest, NameFromIpPrefix6)
+{
+ hicn_ip_prefix_t hicn_ip_prefix = { .family = AF_INET6,
+ .address = {},
+ .len = 64 };
+
+ hicn_ip_prefix.address.v6.as_u64[0] = ipv6_prefix_bytes.v6.as_u64[0];
+ hicn_ip_prefix.address.v6.as_u64[1] = ipv6_prefix_bytes.v6.as_u64[1];
+
+ nameFromIpPrefixTest (hicn_ip_prefix);
+}
+
+TEST_F (NameTest, NameFromIpPrefix4)
+{
+ hicn_ip_prefix_t hicn_ip_prefix = { .family = AF_INET,
+ .address = {},
+ .len = 64 };
+ hicn_ip_prefix.address.v4.as_u32 = ipv4_prefix_bytes.v4.as_u32;
+ hicn_ip_prefix.address.pad[0] = 0;
+ hicn_ip_prefix.address.pad[1] = 0;
+ hicn_ip_prefix.address.pad[2] = 0;
+ nameFromIpPrefixTest (hicn_ip_prefix);
+}
+
+TEST_F (NameTest, NameCompare6) { nameCompareTest (ipv6_prefix); }
+
+TEST_F (NameTest, NameCompare4) { nameCompareTest (ipv4_prefix); }
+
+TEST_F (NameTest, NameHash6) { nameHashTest (ipv6_prefix); }
+
+TEST_F (NameTest, NameHash4) { nameHashTest (ipv4_prefix); }
+
+TEST_F (NameTest, NameEmpty)
+{
+ int rc = hicn_name_empty (&name_);
+ EXPECT_EQ (rc, 1);
+
+ name_.prefix.v6 = ipv6_prefix_bytes.v6;
+ rc = hicn_name_empty (&name_);
+ EXPECT_EQ (rc, 0);
+}
+
+TEST_F (NameTest, NameCopy6) { nameCopyTest (ipv6_prefix); }
+
+TEST_F (NameTest, NameCopy4) { nameCopyTest (ipv4_prefix); }
+
+TEST_F (NameTest, NameCopyToDestination)
+{
+ ipv4_address_t dst4;
+ ipv6_address_t dst6;
+
+ // Copy names to destination
+ int rc = hicn_name_copy_prefix_to_destination (dst4.as_u8, &name4_);
+ EXPECT_EQ (rc, 0);
+ rc = hicn_name_copy_prefix_to_destination (dst6.as_u8, &name6_);
+ EXPECT_EQ (rc, 0);
+
+ // Check copy succeeded
+ EXPECT_TRUE (dst4.as_u32 == name4_.prefix.v4.as_u32);
+ EXPECT_TRUE (dst6.as_u64[0] == name6_.prefix.v6.as_u64[0]);
+ EXPECT_TRUE (dst6.as_u64[1] == name6_.prefix.v6.as_u64[1]);
+}
+
+TEST_F (NameTest, SetGetSuffix)
+{
+ uint32_t suffix2 = 55555, suffix_ret;
+
+ // Check if suffix is correct
+ int rc = hicn_name_get_seq_number (&name6_, &suffix_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (suffix, suffix_ret);
+
+ // Set new suffix
+ rc = hicn_name_set_suffix (&name6_, suffix2);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check suffix was set
+ rc = hicn_name_get_seq_number (&name6_, &suffix_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (suffix2, suffix_ret);
+}
+
+TEST_F (NameTest, NameToSockAddr)
+{
+ struct sockaddr_in saddr4;
+ struct sockaddr_in6 saddr6;
+
+ int rc =
+ hicn_name_to_sockaddr_address (&name6_, (struct sockaddr *) (&saddr6));
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = memcmp (name6_.prefix.v6.as_u8, saddr6.sin6_addr.s6_addr,
+ sizeof (name6_.prefix.v6));
+ EXPECT_EQ (rc, 0);
+
+ rc = hicn_name_to_sockaddr_address (&name4_, (struct sockaddr *) (&saddr4));
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (name4_.prefix.v4.as_u32, saddr4.sin_addr.s_addr);
+}
+
+TEST_F (NameTest, NameToIpPrefix)
+{
+ nameToIpPrefixTest (ipv4_prefix);
+ nameToIpPrefixTest (ipv6_prefix);
+}
+
+TEST_F (NameTest, NameNToP)
+{
+ char dst[128];
+
+ // V6
+ int rc = hicn_name_ntop (&name6_, dst, 128);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Build expected name
+ std::stringstream expected6;
+ expected6 << ipv6_prefix << "|" << suffix;
+
+ rc = strcmp (dst, expected6.str ().c_str ());
+ EXPECT_EQ (rc, 0);
+
+ // V4
+ rc = hicn_name_ntop (&name4_, dst, 128);
+ std::stringstream expected4;
+ expected4 << ipv4_prefix << "|" << suffix;
+
+ rc = strcmp (dst, expected4.str ().c_str ());
+ EXPECT_EQ (rc, 0);
+}
+
+class PrefixTest : public ::testing::Test
+{
+protected:
+ PrefixTest () {}
+
+ virtual ~PrefixTest () {}
+};
+
+#define HICN_PREFIX(P, STR) \
+ hicn_prefix_t P; \
+ hicn_ip_prefix_t _##P; \
+ EXPECT_EQ (hicn_ip_prefix_pton (STR, &_##P), 0); \
+ EXPECT_EQ (hicn_prefix_create_from_ip_prefix (&_##P, &P), 0);
+
+TEST_F (PrefixTest, PrefixClear)
+{
+ HICN_PREFIX (hp_all, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+
+ for (unsigned i = 0; i < 127; i++)
+ EXPECT_EQ (hicn_prefix_get_bit (&hp_all, i), 1);
+
+ hicn_prefix_truncate (&hp_all, 127);
+ EXPECT_EQ (hicn_prefix_get_len (&hp_all), 127);
+
+ for (unsigned i = 0; i < 126; i++)
+ EXPECT_EQ (hicn_prefix_get_bit (&hp_all, i), 1) << "bit[" << i << "] != 1";
+ EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 127), 0);
+
+ hicn_prefix_truncate (&hp_all, 126);
+ EXPECT_EQ (hicn_prefix_get_len (&hp_all), 126);
+
+ for (unsigned i = 0; i < 125; i++)
+ EXPECT_EQ (hicn_prefix_get_bit (&hp_all, i), 1);
+ EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 126), 0);
+ EXPECT_EQ (_hicn_prefix_get_bit (&hp_all, 127), 0);
+}
+
+TEST_F (PrefixTest, PrefixClear2)
+{
+ HICN_PREFIX (hp_all, "b002::3");
+
+ EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 125), 0);
+ EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 126), 1);
+ EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 127), 1);
+
+ hicn_prefix_truncate (&hp_all, 127);
+ EXPECT_EQ (hicn_prefix_get_len (&hp_all), 127);
+
+ EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 125), 0);
+ EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 126), 1);
+ EXPECT_EQ (_hicn_prefix_get_bit (&hp_all, 127), 0);
+}
+
+TEST_F (PrefixTest, PrefixLPM)
+{
+ HICN_PREFIX (b007, "b007::/64");
+ HICN_PREFIX (b009, "b009::/64");
+
+ EXPECT_EQ (hicn_prefix_lpm (&b007, &b009), (uint32_t) 12);
+
+ HICN_PREFIX (pfx, "1122:3344:5566:7788:9900:aabb:ccdd:eeff/128");
+ EXPECT_EQ (hicn_prefix_lpm (&pfx, &pfx), (uint32_t) 128);
+}
diff --git a/lib/src/test/test_new_header.cc b/lib/src/test/test_new_header.cc
new file mode 100644
index 000000000..c936b6910
--- /dev/null
+++ b/lib/src/test/test_new_header.cc
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+extern "C"
+{
+#include <hicn/name.h>
+#include <hicn/common.h>
+#include <hicn/error.h>
+#include <hicn/packet.h>
+
+#include "../protocol/ah.h"
+#include "../protocol/new.h"
+}
+
+class NewHeaderTest : public ::testing::Test
+{
+protected:
+ const char *ipv6_prefix = "b001::abcd:1234:abcd:1234";
+ const char *ipv4_prefix = "12.13.14.15";
+ const uint32_t suffix = 12345;
+
+ NewHeaderTest (hicn_packet_format_t format)
+ : buffer_ (new uint8_t[NEW_HDRLEN]),
+ format_ (format), name_{}, name4_{}, name6_{}
+ {
+
+ int rc = inet_pton (AF_INET6, ipv6_prefix, &ipv6_prefix_bytes.v6);
+ EXPECT_EQ (rc, 1);
+
+ rc = inet_pton (AF_INET, ipv4_prefix, &ipv4_prefix_bytes.v4);
+ EXPECT_EQ (rc, 1);
+
+ rc = hicn_name_create (ipv4_prefix, suffix, &name4_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_name_create (ipv6_prefix, suffix, &name6_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ }
+
+ NewHeaderTest () : NewHeaderTest (HICN_PACKET_FORMAT_NEW) {}
+
+ virtual ~NewHeaderTest () { delete[] buffer_; }
+
+ void
+ checkCommon ()
+ {
+ // Initialize header
+ hicn_packet_set_format (&pkbuf_, format_);
+ // pkbuf_set_type (&pkbuf_, HICN_PACKET_TYPE_UNDEFINED);
+ int rc = hicn_packet_init_header (&pkbuf_, 0);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ auto new_hdr = (_new_header_t *) buffer_;
+
+ // Check fields
+ EXPECT_EQ (new_hdr->prefix.v6.as_u64[0], 0UL);
+ EXPECT_EQ (new_hdr->prefix.v6.as_u64[1], 0UL);
+ EXPECT_EQ (new_hdr->suffix, 0UL);
+ EXPECT_EQ (new_hdr->lifetime, 0UL);
+ EXPECT_EQ (new_hdr->path_label, 0UL);
+ EXPECT_EQ (new_hdr->payload_len, 0UL);
+ EXPECT_EQ (_get_new_header_version (new_hdr), 0x9);
+ EXPECT_EQ (new_hdr->flags, 0);
+ }
+
+ virtual void
+ SetUp () override
+ {
+ checkCommon ();
+ }
+
+ uint8_t *buffer_;
+ hicn_packet_buffer_t pkbuf_;
+ hicn_packet_format_t format_;
+ hicn_name_t name_, name4_, name6_;
+ hicn_ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes;
+};
+
+#if 0
+class NewHeaderAHTest : public NewHeaderTest
+{
+protected:
+ NewHeaderAHTest () : NewHeaderTest (NEW_HDRLEN + AH_HDRLEN, HF_NEW_AH) {}
+
+ virtual void
+ SetUp () override
+ {
+ auto new_hdr = &header_->protocol.newhdr;
+ checkCommon (new_hdr);
+ EXPECT_NE (new_hdr->flags, 0);
+ }
+};
+
+/**
+ * Header Initialization
+ */
+TEST_F (NewHeaderTest, GetFormat)
+{
+ // Get format from existing packet
+ hicn_format_t format;
+ int rc = hicn_packet_get_format (header_, &format);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check it corresponds to the new header format
+ EXPECT_EQ (format, HF_NEW);
+}
+
+TEST_F (NewHeaderAHTest, GetFormat)
+{
+ // Get format from existing packet
+ hicn_format_t format;
+ int rc = hicn_packet_get_format (header_, &format);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check it corresponds to the new header format
+ EXPECT_EQ (format, HF_NEW_AH);
+}
+
+/**
+ * @brief Checksum functions are not required, but we keep them for
+ * compatibility.
+ */
+TEST_F (NewHeaderTest, Checksum)
+{
+ // Get format from existing packet
+ int rc = hicn_packet_compute_checksum (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_compute_header_checksum (format_, header_, 0);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_check_integrity_no_payload (format_, header_, 0);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+}
+
+TEST_F (NewHeaderAHTest, Checksum)
+{
+ // Get format from existing packet
+ int rc = hicn_packet_compute_checksum (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_compute_header_checksum (format_, header_, 0);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_check_integrity_no_payload (format_, header_, 0);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+}
+
+TEST_F (NewHeaderTest, GetHeaderLengthFromFormat)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length_from_format (format_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, NEW_HDRLEN);
+}
+
+TEST_F (NewHeaderAHTest, GetHeaderLengthFromFormat)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length_from_format (format_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, NEW_HDRLEN + AH_HDRLEN);
+}
+
+TEST_F (NewHeaderTest, GetHeaderLength)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length (format_, header_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, NEW_HDRLEN);
+}
+
+TEST_F (NewHeaderAHTest, GetHeaderLength)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length (format_, header_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, NEW_HDRLEN + AH_HDRLEN);
+}
+
+TEST_F (NewHeaderTest, SetGetPayloadLength)
+{
+ // Get format from existing packet
+ std::size_t payload_len = 1000, payload_len_ret;
+ int rc = hicn_packet_set_payload_length (format_, header_, payload_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_packet_get_payload_length (format_, header_, &payload_len_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (payload_len, payload_len_ret);
+}
+
+TEST_F (NewHeaderAHTest, SetGetPayloadLength)
+{
+ // Get format from existing packet
+ std::size_t payload_len = 1000, payload_len_ret;
+ int rc = hicn_packet_set_payload_length (format_, header_, payload_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_packet_get_payload_length (format_, header_, &payload_len_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (payload_len, payload_len_ret);
+}
+
+TEST_F (NewHeaderTest, SetGetName)
+{
+ // Get v6 name and set it to new_header
+ hicn_name_t name_ret;
+ int rc = hicn_packet_set_name (format_, header_, &name6_, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_name (format_, header_, &name_ret, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_name_compare (&name6_, &name_ret, 1);
+ EXPECT_EQ (rc, 0);
+}
+
+TEST_F (NewHeaderTest, SetGetLocator)
+{
+ // This function does nothing but it is set for compatibility
+ hicn_ip_address_t locator;
+ memset (&locator, 0, sizeof (locator));
+ locator.v6.as_u8[15] = 1;
+ int rc = hicn_packet_set_interest (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_set_locator (format_, header_, &locator, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_locator (format_, header_, &locator, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+}
+
+TEST_F (NewHeaderTest, SetGetSignatureSize)
+{
+ // No AH, so we should get an error
+ // FixMe no error raised here
+ size_t signature_size = 128;
+ int rc = hicn_packet_set_signature_size (format_, header_, signature_size);
+ (void) rc;
+ // EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Same for hicn_packet_get_signature_size
+ rc = hicn_packet_get_signature_size (format_, header_, &signature_size);
+ // EXPECT_NE (rc, HICN_LIB_ERROR_NONE);
+}
+
+TEST_F (NewHeaderAHTest, SetGetSignatureSize)
+{
+ // No AH, so we should get an error
+ size_t signature_size = 128, signature_size_ret;
+ int rc = hicn_packet_set_signature_size (format_, header_, signature_size);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Same for hicn_packet_get_signature_size
+ rc = hicn_packet_get_signature_size (format_, header_, &signature_size_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (signature_size, signature_size_ret);
+}
+
+TEST_F (NewHeaderTest, IsInterestIsData)
+{
+ // Mark packet as interest
+ int rc = hicn_packet_set_interest (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ int ret;
+ rc = hicn_packet_is_interest (format_, header_, &ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (ret, 1);
+
+ // Mark packet as data
+ rc = hicn_packet_set_data (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_is_interest (format_, header_, &ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (ret, 0);
+}
+
+TEST_F (NewHeaderTest, SetGetLifetime)
+{
+ // Lifetime
+ u32 lifetime = 20000, lifetime_ret; // 20 sec.
+ int rc = hicn_packet_set_lifetime (format_, header_, lifetime);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_lifetime (format_, header_, &lifetime_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (lifetime, lifetime_ret);
+}
+
+TEST_F (NewHeaderAHTest, SetGetLifetime)
+{
+ // Lifetime
+ u32 lifetime = 20000, lifetime_ret; // 20 sec.
+ int rc = hicn_packet_set_lifetime (format_, header_, lifetime);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_lifetime (format_, header_, &lifetime_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (lifetime, lifetime_ret);
+}
+
+TEST_F (NewHeaderTest, SetGetPayloadType)
+{
+ // Lifetime
+ hicn_payload_type_t payload_type = HPT_MANIFEST, payload_type_ret;
+ int rc = hicn_packet_set_payload_type (format_, header_, payload_type);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_payload_type (format_, header_, &payload_type_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (payload_type, payload_type_ret);
+
+ payload_type = HPT_DATA;
+
+ rc = hicn_packet_set_payload_type (format_, header_, payload_type);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_payload_type (format_, header_, &payload_type_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (payload_type, payload_type_ret);
+}
+#endif
diff --git a/lib/src/test/test_pool.cc b/lib/src/test/test_pool.cc
new file mode 100644
index 000000000..cbb5ce068
--- /dev/null
+++ b/lib/src/test/test_pool.cc
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <netinet/in.h>
+
+extern "C"
+{
+#define WITH_TESTS
+#include <hicn/util/pool.h>
+}
+
+/*
+ * TODO
+ * - test max_size
+ */
+
+#define DEFAULT_SIZE 10
+
+class PoolTest : public ::testing::Test
+{
+protected:
+ PoolTest () {}
+ virtual ~PoolTest () {}
+
+ int *pool;
+};
+
+TEST_F (PoolTest, PoolAllocation)
+{
+ int rc;
+
+ pool_init (pool, DEFAULT_SIZE, 0);
+
+ size_t pool_size = next_pow2 (DEFAULT_SIZE);
+
+ 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], (long) (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), 1UL);
+ EXPECT_TRUE (bitmap_is_unset (fb, pool_size - 2));
+
+ rc = pool_get (pool, elt);
+ EXPECT_GE (rc, 0);
+ EXPECT_EQ (vector_len (fi), 0UL);
+ 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);
+}
+
+TEST_F (PoolTest, PoolPut)
+{
+ pool_init (pool, DEFAULT_SIZE, 0);
+
+ int *elt;
+ pool_get (pool, elt);
+ *elt = 10;
+ pool_put (pool, elt);
+
+ pool_free (pool);
+}
+
+TEST_F (PoolTest, PoolGetForceBitmapRealloc)
+{
+ const int N = 64;
+ int *elts[N];
+ int *elt = NULL;
+ pool_init (pool, N, 0);
+
+ for (int i = 0; i < N; i++)
+ pool_get (pool, elts[i]);
+ pool_get (pool, elt);
+
+ pool_free (pool);
+}
+
+TEST_F (PoolTest, PoolGetAfterReleasing)
+{
+ int *elt1 = NULL, *elt2 = NULL, *tmp = NULL;
+ pool_init (pool, DEFAULT_SIZE, 0);
+
+ // If two elements are requested...
+ off_t id1 = pool_get (pool, elt1);
+ pool_get (pool, tmp);
+
+ // ...and the first one is released...
+ pool_put (pool, elt1);
+
+ // ...requesting a new one should return
+ // the first one (that was freed)
+ off_t id2 = pool_get (pool, elt2);
+ EXPECT_EQ (id1, id2);
+ EXPECT_EQ (elt1, elt2);
+
+ pool_free (pool);
+}
+
+TEST_F (PoolTest, PoolGetMultipleElementsAfterReleasing)
+{
+ const int N = 2;
+ int *elts[N];
+ pool_init (pool, N, 0);
+
+ for (int i = 0; i < N; i++)
+ pool_get (pool, elts[i]);
+ for (int i = 0; i < N; i++)
+ pool_put (pool, elts[i]);
+ for (int i = 0; i < N; i++)
+ pool_get (pool, elts[i]);
+
+ pool_free (pool);
+}
diff --git a/lib/src/test/test_ring.cc b/lib/src/test/test_ring.cc
new file mode 100644
index 000000000..f0b0371e8
--- /dev/null
+++ b/lib/src/test/test_ring.cc
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <netinet/in.h>
+
+extern "C"
+{
+#define WITH_TESTS
+#include <hicn/util/ring.h>
+}
+
+#define DEFAULT_SIZE 10UL
+
+class RingTest : public ::testing::Test
+{
+protected:
+ RingTest () { ring_init (ring, DEFAULT_SIZE); }
+ virtual ~RingTest () { ring_free (ring); }
+
+ int *ring = NULL;
+};
+
+/* TEST: Ring allocation and initialization */
+TEST_F (RingTest, RingAddOne)
+{
+ int val = -1;
+ /* Allocated size should be the next power of two */
+ EXPECT_EQ (ring_get_size (ring), 0UL);
+ ring_add_value (ring, 1);
+ EXPECT_EQ (ring_get_size (ring), 1UL);
+ ring_get (ring, 0, &val);
+ EXPECT_EQ (val, 1);
+ EXPECT_EQ (ring_get_size (ring), 1UL);
+ ring_advance (ring, 1);
+ EXPECT_EQ (ring_get_size (ring), 0UL);
+}
+
+TEST_F (RingTest, RingAddMany)
+{
+ size_t i = 0;
+ int val = -1;
+ size_t count = 0;
+
+ /* Allocated size should be the next power of two */
+ EXPECT_EQ (ring_get_size (ring), 0UL);
+ for (unsigned i = 0; i < DEFAULT_SIZE; i++)
+ ring_add_value (ring, i);
+ EXPECT_EQ (ring_get_size (ring), DEFAULT_SIZE);
+
+ count = 0;
+ ring_enumerate_n (ring, i, &val, 1, {
+ EXPECT_EQ (val, (int) (i));
+ count++;
+ });
+ EXPECT_EQ (count, 1UL);
+
+ count = 0;
+ ring_enumerate_n (ring, i, &val, DEFAULT_SIZE, {
+ EXPECT_EQ (val, (int) (i));
+ count++;
+ });
+ EXPECT_EQ (count, DEFAULT_SIZE);
+
+ count = 0;
+ ring_enumerate_n (ring, i, &val, DEFAULT_SIZE + 1, {
+ EXPECT_EQ (val, (int) (i));
+ count++;
+ });
+ EXPECT_EQ (count, DEFAULT_SIZE);
+
+ // Drop one
+ ring_add_value (ring, DEFAULT_SIZE);
+ EXPECT_EQ (ring_get_size (ring), DEFAULT_SIZE);
+
+ count = 0;
+ ring_enumerate_n (ring, i, &val, DEFAULT_SIZE, {
+ EXPECT_EQ (val, (int) (i + 1)); // all values shoud be shifted
+ count++;
+ });
+ EXPECT_EQ (count, DEFAULT_SIZE);
+
+ ring_advance (ring, DEFAULT_SIZE);
+ EXPECT_EQ (ring_get_size (ring), 0UL);
+}
diff --git a/lib/src/test/test_slab.cc b/lib/src/test/test_slab.cc
new file mode 100644
index 000000000..15deff3c1
--- /dev/null
+++ b/lib/src/test/test_slab.cc
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+extern "C"
+{
+#include <hicn/util/slab.h>
+}
+
+class SlabTest : public ::testing::Test
+{
+protected:
+ SlabTest () {}
+ virtual ~SlabTest () { slab_free (slab); }
+
+ slab_t *slab;
+};
+
+typedef struct
+{
+ int index;
+ int val;
+} element_t;
+
+TEST_F (SlabTest, SlabCreateAndGetSingleChunk)
+{
+ slab = slab_create (element_t, 16);
+ ASSERT_NE (slab, nullptr);
+
+ element_t *e = slab_get (element_t, slab);
+ ASSERT_NE (e, nullptr);
+ slab_put (slab, e);
+}
+
+TEST_F (SlabTest, SlabGetChunks)
+{
+ slab = slab_create (element_t, 2);
+
+ // Force creation of multiple blocks (since initial size is only 2)
+ for (int i = 0; i < 100; i++)
+ {
+ element_t *e = slab_get (element_t, slab);
+ EXPECT_NE (e, nullptr);
+ }
+}
+
+TEST_F (SlabTest, SlabGetAndPutChunksNoResize)
+{
+ constexpr int NUM_ELEMENTS = 64;
+ element_t *elements[NUM_ELEMENTS];
+ for (int i = 0; i < NUM_ELEMENTS; i++)
+ elements[i] = NULL;
+
+ // Initial size=NUM_ELEMENTS, only one block will be created
+ slab = slab_create (element_t, NUM_ELEMENTS);
+
+ for (int i = 0; i < NUM_ELEMENTS; i++)
+ {
+ elements[i] = slab_get (element_t, slab);
+ EXPECT_NE (elements[i], nullptr);
+ }
+
+ // Release all chunks
+ for (int i = 0; i < NUM_ELEMENTS; i++)
+ slab_put (slab, elements[i]);
+}
+
+TEST_F (SlabTest, SlabGetAndPutChunks)
+{
+ constexpr int NUM_ELEMENTS = 100;
+ element_t *elements[NUM_ELEMENTS];
+ for (int i = 0; i < NUM_ELEMENTS; i++)
+ elements[i] = NULL;
+
+ // Initial size=2 while NUM_ELEMENTS=100, to force creation of multiple
+ // blocks
+ slab = slab_create (sizeof (element_t), 2);
+
+ for (int i = 0; i < NUM_ELEMENTS; i++)
+ {
+ elements[i] = slab_get (element_t, slab);
+ EXPECT_NE (elements[i], nullptr);
+ }
+
+ // Release all chunks
+ for (int i = 0; i < NUM_ELEMENTS; i++)
+ slab_put (slab, elements[i]);
+}
+
+TEST_F (SlabTest, SlabGetAndPutSomeChunks)
+{
+ slab = slab_create (element_t, 2);
+
+ constexpr int NUM_ELEMENTS = 100;
+ element_t *elements[NUM_ELEMENTS];
+ for (int i = 0; i < NUM_ELEMENTS; i++)
+ elements[i] = NULL;
+
+ // Get chunks...
+ for (int i = 0; i < NUM_ELEMENTS; i++)
+ {
+ elements[i] = slab_get (element_t, slab);
+ EXPECT_NE (elements[i], nullptr);
+
+ // ...and return only some of them
+ if (i % 5 == 0)
+ slab_put (slab, elements[i]);
+ }
+}
+
+TEST_F (SlabTest, SlabGetSameChunkTwice)
+{
+ slab = slab_create (element_t, 1);
+
+ // Get chunk and update it before returning it
+ element_t *e = slab_get (element_t, slab);
+ ASSERT_NE (e, nullptr);
+ element_t *prev = e;
+ e->index = 2;
+ e->val = 3;
+ slab_put (slab, e);
+
+ // Get a chunk again: it should return the previous one
+ // without wiping its memory
+ e = slab_get (element_t, slab);
+ ASSERT_NE (e, nullptr);
+ EXPECT_EQ (e, prev);
+ EXPECT_EQ (e->index, 2);
+ EXPECT_EQ (e->val, 3);
+
+ // Try to get an additional chunk: it should return a new chunk
+ // (different from previous one)
+ e = slab_get (element_t, slab);
+ EXPECT_NE (e, prev);
+} \ No newline at end of file
diff --git a/lib/src/test/test_udp_header.cc b/lib/src/test/test_udp_header.cc
new file mode 100644
index 000000000..2856c8ebf
--- /dev/null
+++ b/lib/src/test/test_udp_header.cc
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+extern "C"
+{
+#include <hicn/name.h>
+#include <hicn/common.h>
+#include <hicn/error.h>
+#include <hicn/packet.h>
+
+#include "../protocol/ah.h"
+#include "../protocol/ipv6.h"
+#include "../protocol/udp.h"
+#include "../protocol/new.h"
+}
+
+class UdpHeaderTest : public ::testing::Test
+{
+protected:
+ const char *ipv6_prefix = "b001::abcd:1234:abcd:1234";
+ const char *ipv4_prefix = "12.13.14.15";
+ const uint32_t suffix = 12345;
+
+ UdpHeaderTest (size_t hdr_size, hicn_packet_format_t format)
+ : buffer_ (new uint8_t[hdr_size]), hdr_size_ (hdr_size),
+ format_ (format), name_{}, name4_{}, name6_{}
+ {
+ int rc = inet_pton (AF_INET6, ipv6_prefix, &ipv6_prefix_bytes.v6);
+ EXPECT_EQ (rc, 1);
+
+ rc = inet_pton (AF_INET, ipv4_prefix, &ipv4_prefix_bytes.v4);
+ EXPECT_EQ (rc, 1);
+
+ rc = hicn_name_create (ipv4_prefix, suffix, &name4_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_name_create (ipv6_prefix, suffix, &name6_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ }
+
+ UdpHeaderTest ()
+ : UdpHeaderTest (NEW_HDRLEN + UDP_HDRLEN + IPV6_HDRLEN,
+ HICN_PACKET_FORMAT_IPV6_UDP)
+ {
+ }
+
+ virtual ~UdpHeaderTest () { delete[] buffer_; }
+
+ // checked everytime we build the packet...
+ void
+ checkCommon ()
+ {
+ /* Initialize packet buffer headers */
+ hicn_packet_set_format (&pkbuf_, format_);
+ hicn_packet_set_type (&pkbuf_, HICN_PACKET_TYPE_INTEREST);
+ hicn_packet_set_buffer (&pkbuf_, buffer_, hdr_size_, 0);
+ int rc = hicn_packet_init_header (&pkbuf_, 0);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ auto ip6_hdr = (_ipv6_header_t *) buffer_;
+
+ // Check fields
+ EXPECT_EQ (ip6_hdr->saddr.as_u64[0], 0UL);
+ EXPECT_EQ (ip6_hdr->saddr.as_u64[1], 0UL);
+ EXPECT_EQ (ip6_hdr->daddr.as_u64[0], 0UL);
+ EXPECT_EQ (ip6_hdr->daddr.as_u64[1], 0UL);
+ EXPECT_EQ (ip6_hdr->nxt, IPPROTO_UDP);
+
+ _udp_header_t *udp_hdr = (_udp_header_t *) (ip6_hdr + 1);
+ EXPECT_EQ (udp_hdr->src_port, 0UL);
+ EXPECT_EQ (udp_hdr->dst_port, 0UL);
+ EXPECT_EQ (udp_hdr->checksum, 0UL);
+ // EXPECT_EQ (ntohs (udp_hdr->length), NEW_HDRLEN + AH_HDRLEN);
+
+ _new_header_t *new_hdr = (_new_header_t *) (udp_hdr + 1);
+ EXPECT_EQ (new_hdr->prefix.v6.as_u64[0], 0UL);
+ EXPECT_EQ (new_hdr->prefix.v6.as_u64[1], 0UL);
+ EXPECT_EQ (new_hdr->suffix, 0UL);
+ EXPECT_EQ (new_hdr->lifetime, 0UL);
+ EXPECT_EQ (new_hdr->path_label, 0UL);
+ EXPECT_EQ (new_hdr->payload_len, 0UL);
+ EXPECT_EQ (_get_new_header_version (new_hdr), 0x9);
+ }
+
+ virtual void
+ SetUp () override
+ {
+ checkCommon ();
+ }
+
+ uint8_t *buffer_;
+ size_t hdr_size_;
+ hicn_packet_buffer_t pkbuf_;
+ hicn_packet_format_t format_;
+ hicn_name_t name_, name4_, name6_;
+ hicn_ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes;
+};
+
+class UdpHeaderAHTest : public UdpHeaderTest
+{
+protected:
+ UdpHeaderAHTest ()
+ : UdpHeaderTest (AH_HDRLEN + NEW_HDRLEN + UDP_HDRLEN + IPV6_HDRLEN,
+ HICN_PACKET_FORMAT_IPV6_UDP_AH)
+ {
+ }
+};
+
+/**
+ * Header Initialization
+ */
+TEST_F (UdpHeaderTest, GetFormat)
+{
+ hicn_packet_format_t format = hicn_packet_get_format (&pkbuf_);
+ EXPECT_EQ (format, HICN_PACKET_FORMAT_IPV6_UDP);
+}
+
+TEST_F (UdpHeaderAHTest, GetFormat)
+{
+ // Get format from existing packet
+ hicn_packet_format_t format = hicn_packet_get_format (&pkbuf_);
+
+ // Check it corresponds to the new header format
+ EXPECT_EQ (format, HICN_PACKET_FORMAT_IPV6_UDP_AH);
+}
+
+#if 0
+
+// /**
+// * @brief Checksum functions are not required, but we keep them for
+// * compatibility.
+// */
+// TEST_F (NewHeaderTest, Checksum)
+// {
+// // Get format from existing packet
+// int rc = hicn_packet_compute_checksum (format_, header_);
+// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+// rc = hicn_packet_compute_header_checksum (format_, header_, 0);
+// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+// rc = hicn_packet_check_integrity_no_payload (format_, header_, 0);
+// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+// }
+
+// TEST_F (NewHeaderAHTest, Checksum)
+// {
+// // Get format from existing packet
+// int rc = hicn_packet_compute_checksum (format_, header_);
+// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+// rc = hicn_packet_compute_header_checksum (format_, header_, 0);
+// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+// rc = hicn_packet_check_integrity_no_payload (format_, header_, 0);
+// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+// }
+
+TEST_F (UdpHeaderTest, GetHeaderLengthFromFormat)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length_from_format (format_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, UDP_HDRLEN + IPV6_HDRLEN + NEW_HDRLEN);
+}
+
+TEST_F (UdpHeaderAHTest, GetHeaderLengthFromFormat)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length_from_format (format_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, UDP_HDRLEN + IPV6_HDRLEN + NEW_HDRLEN + AH_HDRLEN);
+}
+
+TEST_F (UdpHeaderTest, GetHeaderLength)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length (format_, header_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, UDP_HDRLEN + IPV6_HDRLEN + NEW_HDRLEN);
+}
+
+TEST_F (UdpHeaderAHTest, GetHeaderLength)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length (format_, header_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, UDP_HDRLEN + IPV6_HDRLEN + NEW_HDRLEN + AH_HDRLEN);
+}
+
+TEST_F (UdpHeaderTest, SetGetPayloadLength)
+{
+ // Get format from existing packet
+ std::size_t payload_len = 1000, payload_len_ret;
+ int rc = hicn_packet_set_payload_length (format_, header_, payload_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_packet_get_payload_length (format_, header_, &payload_len_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (payload_len, payload_len_ret);
+}
+
+TEST_F (UdpHeaderAHTest, SetGetPayloadLength)
+{
+ // Get format from existing packet
+ std::size_t payload_len = 1000, payload_len_ret;
+ int rc = hicn_packet_set_payload_length (format_, header_, payload_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_packet_get_payload_length (format_, header_, &payload_len_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (payload_len, payload_len_ret);
+}
+
+TEST_F (UdpHeaderTest, SetGetName)
+{
+ // Get v6 name and set it to new_header
+ hicn_name_t name_ret;
+
+ int rc = hicn_packet_set_interest (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_set_name (format_, header_, &name6_, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_name (format_, header_, &name_ret, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_name_compare (&name6_, &name_ret, 1);
+ EXPECT_EQ (rc, 0);
+}
+
+TEST_F (UdpHeaderTest, SetGetLocator)
+{
+ // This function does nothing but it is set for compatibility
+ hicn_ip_address_t locator;
+ memset (&locator, 0, sizeof (locator));
+ locator.v6.as_u8[15] = 1;
+ int rc = hicn_packet_set_interest (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_set_locator (format_, header_, &locator, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_locator (format_, header_, &locator, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+}
+
+TEST_F (UdpHeaderTest, SetGetSignatureSize)
+{
+ // No AH, so we should get an error
+ // FixMe no error raised here
+ size_t signature_size = 128;
+ int rc = hicn_packet_set_signature_size (format_, header_, signature_size);
+ (void) rc;
+ // EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Same for hicn_packet_get_signature_size
+ rc = hicn_packet_get_signature_size (format_, header_, &signature_size);
+ // EXPECT_NE (rc, HICN_LIB_ERROR_NONE);
+}
+
+TEST_F (UdpHeaderAHTest, SetGetSignatureSize)
+{
+ // No AH, so we should get an error
+ size_t signature_size = 128, signature_size_ret;
+ int rc = hicn_packet_set_signature_size (format_, header_, signature_size);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Same for hicn_packet_get_signature_size
+ rc = hicn_packet_get_signature_size (format_, header_, &signature_size_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (signature_size, signature_size_ret);
+}
+
+TEST_F (UdpHeaderTest, IsInterestIsData)
+{
+ // Mark packet as interest
+ int rc = hicn_packet_set_interest (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ int ret;
+ rc = hicn_packet_is_interest (format_, header_, &ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (ret, 1);
+
+ // Mark packet as data
+ rc = hicn_packet_set_data (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_is_interest (format_, header_, &ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (ret, 0);
+}
+
+TEST_F (UdpHeaderTest, SetGetLifetime)
+{
+ // Lifetime
+ u32 lifetime = 20000, lifetime_ret; // 20 sec.
+ int rc = hicn_packet_set_lifetime (format_, header_, lifetime);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_lifetime (format_, header_, &lifetime_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (lifetime, lifetime_ret);
+}
+
+TEST_F (UdpHeaderAHTest, SetGetLifetime)
+{
+ // Lifetime
+ u32 lifetime = 20000, lifetime_ret; // 20 sec.
+ int rc = hicn_packet_set_lifetime (format_, header_, lifetime);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_lifetime (format_, header_, &lifetime_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (lifetime, lifetime_ret);
+}
+
+TEST_F (UdpHeaderTest, SetGetPayloadType)
+{
+ // Lifetime
+ hicn_payload_type_t payload_type = HPT_MANIFEST, payload_type_ret;
+ int rc = hicn_packet_set_payload_type (format_, header_, payload_type);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_payload_type (format_, header_, &payload_type_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (payload_type, payload_type_ret);
+
+ payload_type = HPT_DATA;
+
+ rc = hicn_packet_set_payload_type (format_, header_, payload_type);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_payload_type (format_, header_, &payload_type_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (payload_type, payload_type_ret);
+}
+#endif
diff --git a/lib/src/test/test_validation.cc b/lib/src/test/test_validation.cc
new file mode 100644
index 000000000..091f26d65
--- /dev/null
+++ b/lib/src/test/test_validation.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+extern "C"
+{
+#include <hicn/validation.h>
+}
+
+static constexpr int BUF_SIZE = 10;
+
+class ValidationTest : public ::testing::Test
+{
+};
+
+TEST_F (ValidationTest, SymbolicName)
+{
+ const char symbolic_name_correct[BUF_SIZE] = "conn0";
+ const char symbolic_name_empty[BUF_SIZE] = "";
+ const char symbolic_name_wrong[BUF_SIZE] = "1conn0";
+
+ EXPECT_TRUE (is_symbolic_name (symbolic_name_correct, BUF_SIZE));
+ EXPECT_FALSE (is_symbolic_name (symbolic_name_empty, BUF_SIZE));
+ EXPECT_FALSE (is_symbolic_name (symbolic_name_wrong, BUF_SIZE));
+}
+
+TEST_F (ValidationTest, Number)
+{
+ const char number_correct[BUF_SIZE] = "123";
+ const char number_empty[BUF_SIZE] = "";
+ const char number_wrong[BUF_SIZE] = "a123";
+ const char number_wrong_2[BUF_SIZE] = "12T3";
+ const char number_wrong_3[BUF_SIZE] = "a";
+ const char number_wrong_negative[BUF_SIZE] = "-123";
+
+ EXPECT_TRUE (is_number (number_correct, BUF_SIZE));
+ EXPECT_FALSE (is_number (number_empty, BUF_SIZE));
+ EXPECT_FALSE (is_number (number_wrong, BUF_SIZE));
+ EXPECT_FALSE (is_number (number_wrong_2, BUF_SIZE));
+ EXPECT_FALSE (is_number (number_wrong_3, BUF_SIZE));
+ EXPECT_FALSE (is_number (number_wrong_negative, BUF_SIZE));
+} \ No newline at end of file
diff --git a/lib/src/test/test_vector.cc b/lib/src/test/test_vector.cc
new file mode 100644
index 000000000..88b0bb7cf
--- /dev/null
+++ b/lib/src/test/test_vector.cc
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+extern "C"
+{
+#include <hicn/util/vector.h>
+}
+
+static constexpr size_t DEFAULT_SIZE = 10;
+static constexpr size_t N_ELEMENTS = 5;
+
+class VectorTest : public ::testing::Test
+{
+protected:
+ VectorTest () { vector_init (vector, DEFAULT_SIZE, 0); }
+ virtual ~VectorTest () { vector_free (vector); }
+
+ int *vector = NULL;
+};
+
+TEST_F (VectorTest, VectorAllocateAndResize)
+{
+ // Allocated size should be the next power of two
+ EXPECT_EQ (vector_get_alloc_size (vector), 16UL);
+
+ // Setting elements within the allocated size should not trigger a resize
+ vector_ensure_pos (vector, 15);
+ EXPECT_EQ (vector_get_alloc_size (vector), 16UL);
+
+ // Setting elements after should through
+ vector_ensure_pos (vector, 16);
+ EXPECT_EQ (vector_get_alloc_size (vector), 32UL);
+}
+
+TEST_F (VectorTest, VectorSize)
+{
+ EXPECT_EQ (vector_len (vector), size_t (0));
+
+ // Check size after pushing one element
+ vector_push (vector, 1);
+ EXPECT_EQ (vector_len (vector), size_t (1));
+
+ // Check size after pushing additional elements
+ vector_push (vector, 2);
+ vector_push (vector, 3);
+ EXPECT_EQ (vector_len (vector), size_t (3));
+
+ // Try adding multiple elements
+ const int n_elements_to_add = 5;
+ size_t expected_new_len = vector_len (vector) + n_elements_to_add;
+ for (int i = 0; i < n_elements_to_add; i++)
+ vector_push (vector, i);
+ EXPECT_EQ (vector_len (vector), expected_new_len);
+}
+
+TEST_F (VectorTest, VectorCheckValue)
+{
+ // Add elements
+ vector_push (vector, 109);
+ vector_push (vector, 200);
+ EXPECT_EQ (vector_at (vector, 0), 109);
+ EXPECT_EQ (vector_at (vector, 1), 200);
+
+ // Update element
+ vector_set (vector, 1, 400);
+ EXPECT_EQ (vector_at (vector, 1), 400);
+
+ // Add at last available position
+ size_t prev_size = vector_len (vector);
+ vector_set (vector, vector_len (vector) - 1, 123);
+ EXPECT_EQ (vector_at (vector, vector_len (vector) - 1), 123);
+ EXPECT_EQ (prev_size, vector_len (vector)) << "Size should not have changed";
+}
+
+TEST_F (VectorTest, RemoveElement)
+{
+ // Populate vector
+ for (size_t i = 0; i < N_ELEMENTS; i++)
+ vector_push (vector, i);
+ EXPECT_EQ (vector_len (vector), N_ELEMENTS);
+ for (size_t i = 0; i < vector_len (vector); i++)
+ EXPECT_EQ (vector_at (vector, i), (int) i);
+
+ // Remove element
+ int value_to_remove = 3;
+ int num_removed = vector_remove_unordered (vector, value_to_remove);
+
+ EXPECT_EQ (vector_len (vector), N_ELEMENTS - 1);
+ EXPECT_EQ (num_removed, 1);
+ for (size_t i = 0; i < vector_len (vector); i++)
+ EXPECT_NE (vector_at (vector, i), value_to_remove);
+}
+
+TEST_F (VectorTest, RemoveNonExistingElement)
+{
+ // Push some initial values
+ vector_push (vector, 1);
+ vector_push (vector, 2);
+ vector_push (vector, 3);
+ EXPECT_EQ (vector_len (vector), size_t (3));
+
+ // Remove non-existing element
+ int num_removed = vector_remove_unordered (vector, 5);
+ EXPECT_EQ (num_removed, 0);
+ size_t prev_size = vector_len (vector);
+ EXPECT_EQ (prev_size, vector_len (vector)) << "Size should not have changed";
+}
+
+TEST_F (VectorTest, RemoveDuplicatedElement)
+{
+ // Populate vector
+ for (size_t i = 0; i < N_ELEMENTS; i++)
+ vector_push (vector, i);
+ EXPECT_EQ (vector_len (vector), N_ELEMENTS);
+ for (size_t i = 0; i < vector_len (vector); i++)
+ EXPECT_EQ (vector_at (vector, i), (int) i);
+ vector_set (vector, 0, 3); // Duplicate element
+
+ // Remove (duplicated) elements
+ int value_to_remove = 3;
+ int num_removed = vector_remove_unordered (vector, value_to_remove);
+
+ EXPECT_EQ (vector_len (vector), N_ELEMENTS - 2);
+ EXPECT_EQ (num_removed, 2);
+ for (size_t i = 0; i < vector_len (vector); i++)
+ EXPECT_NE (vector_at (vector, i), value_to_remove);
+}
+
+TEST_F (VectorTest, Iterate)
+{
+ for (size_t i = 0; i < N_ELEMENTS; i++)
+ vector_push (vector, i);
+
+ int count = 0;
+ int *elem;
+ vector_foreach (vector, elem, { EXPECT_EQ (*elem, count++); });
+}
+
+TEST_F (VectorTest, MultipleResize)
+{
+ // Use small vector (size=1) to force multiple realloc operations
+ int *small_vector;
+ vector_init (small_vector, 1, 0);
+
+ for (size_t i = 0; i < N_ELEMENTS; i++)
+ vector_push (small_vector, i);
+
+ for (size_t i = 0; i < N_ELEMENTS; i++)
+ EXPECT_EQ (vector_at (small_vector, i), (int) i);
+
+ EXPECT_EQ (vector_len (small_vector), 5UL);
+ EXPECT_EQ (vector_get_alloc_size (small_vector), 8UL);
+
+ vector_free (small_vector);
+}
+
+TEST_F (VectorTest, MaxSize)
+{
+ const int max_size = 4;
+
+ // Fill the vector until max size is reached
+ int *small_vector;
+ vector_init (small_vector, 2, max_size);
+ for (int i = 0; i < max_size; i++)
+ vector_push (small_vector, i);
+
+ // Try expanding or appending elements should fail
+ int rc = vector_ensure_pos (small_vector, max_size);
+ EXPECT_EQ (rc, -1);
+ rc = vector_push (small_vector, 123);
+ EXPECT_EQ (rc, -1);
+
+ vector_free (small_vector);
+}
+
+TEST_F (VectorTest, Contains)
+{
+ // No elements
+ EXPECT_EQ (vector_contains (vector, 1), false);
+
+ // Push one element
+ vector_push (vector, 1);
+ EXPECT_EQ (vector_contains (vector, 1), true);
+
+ // Update element
+ vector_set (vector, 0, 2);
+ EXPECT_EQ (vector_contains (vector, 1), false);
+ EXPECT_EQ (vector_contains (vector, 2), true);
+}
+
+TEST_F (VectorTest, Remove)
+{
+ // Remove element at invalid position
+ int rc = vector_remove_at (vector, 2);
+ EXPECT_EQ (rc, -1); // Failure
+
+ // Push two elements and remove the second one
+ vector_push (vector, 1);
+ vector_push (vector, 2);
+ rc = vector_remove_at (vector, 1);
+ EXPECT_EQ (rc, 0); // Success
+ EXPECT_EQ (vector_len (vector), size_t (1));
+
+ // Push another element: it should replace the previous one
+ vector_push (vector, 3);
+ EXPECT_EQ (vector_len (vector), size_t (2));
+ EXPECT_EQ (vector_at (vector, 1), 3);
+}
+
+TEST_F (VectorTest, RemoveInTheMiddle)
+{
+ for (size_t i = 0; i < N_ELEMENTS; i++)
+ vector_push (vector, i);
+
+ // Remove element in central position
+ int rc = vector_remove_at (vector, 2);
+ EXPECT_EQ (rc, 0); // Success
+ EXPECT_EQ (vector_contains (vector, 2), false);
+ EXPECT_EQ (vector_len (vector), N_ELEMENTS - 1);
+
+ // Check if elements have been shifted (preserving the order)
+ int expected[] = { 0, 1, 3, 4 };
+ for (size_t i = 0; i < vector_len (vector); i++)
+ EXPECT_EQ (vector_at (vector, i), expected[i]);
+}
+
+TEST_F (VectorTest, Reset)
+{
+ vector_push (vector, 1);
+ vector_push (vector, 2);
+ EXPECT_EQ (vector_len (vector), size_t (2));
+
+ vector_reset (vector);
+ EXPECT_EQ (vector_len (vector), size_t (0));
+
+ vector_push (vector, 5);
+ EXPECT_EQ (vector_len (vector), size_t (1));
+ EXPECT_EQ (vector_contains (vector, 5), true);
+ EXPECT_EQ (vector_at (vector, 0), 5);
+} \ No newline at end of file
diff --git a/lib/src/util/ip_address.c b/lib/src/util/ip_address.c
index 49916547d..b50864c96 100644
--- a/lib/src/util/ip_address.c
+++ b/lib/src/util/ip_address.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -20,44 +20,58 @@
#include <hicn/util/ip_address.h>
#include <hicn/util/log.h>
+#include <hicn/util/sstrncpy.h>
+#include <hicn/common.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
#ifdef __ANDROID__
-#define SWAP(x) bswap_32(x)
+#define SWAP(x) bswap_32 (x)
#else
-#define SWAP(x) __bswap_constant_32(x)
+#define SWAP(x) __bswap_constant_32 (x)
#endif
#else
#define SWAP(x) x
#endif
-
/* No htonl() with const */
-const ip_address_t IPV4_LOOPBACK = {
- .v4.as_inaddr.s_addr = SWAP(INADDR_LOOPBACK),
+const hicn_ip_address_t IPV4_LOOPBACK = {
+ .v4.as_inaddr.s_addr = SWAP (INADDR_LOOPBACK),
+};
+
+const hicn_ip_address_t IPV6_LOOPBACK = {
+ .v6.as_in6addr = IN6ADDR_LOOPBACK_INIT,
};
-const ip_address_t IPV6_LOOPBACK ={
- .v6.as_in6addr = IN6ADDR_LOOPBACK_INIT,
+const hicn_ip_address_t IPV4_ANY = {
+ .v4.as_inaddr.s_addr = INADDR_ANY,
};
-const ip_address_t IPV4_ANY = {
- .v4.as_inaddr.s_addr = INADDR_ANY,
+const hicn_ip_address_t IPV6_ANY = {
+ .v6.as_in6addr = IN6ADDR_ANY_INIT,
};
-const ip_address_t IPV6_ANY = {
- .v6.as_in6addr = IN6ADDR_ANY_INIT,
+const ipv4_address_t IP4_ADDRESS_EMPTY = {
+ .as_u32 = 0,
};
-const ip_address_t IP_ADDRESS_EMPTY = {
- .v6.as_u64 = { 0 },
+const ipv6_address_t IP6_ADDRESS_EMPTY = {
+ .as_u64 = { 0, 0 },
};
+const hicn_ip_address_t IP_ADDRESS_EMPTY = {
+ .v6.as_u64 = { 0, 0 },
+};
/* IP address */
int
-ip_address_get_family (const char * ip_address)
+hicn_ip_address_get_family (const hicn_ip_address_t *address)
+{
+ return hicn_ip_address_is_v4 (address) ? AF_INET : AF_INET6;
+}
+
+int
+hicn_ip_address_str_get_family (const char *ip_address)
{
struct addrinfo hint, *res = NULL;
int rc;
@@ -78,27 +92,41 @@ ip_address_get_family (const char * ip_address)
}
int
-ip_address_len (int family)
+hicn_ip_address_len (int family)
{
return (family == AF_INET6) ? IPV6_ADDR_LEN :
- (family == AF_INET) ? IPV4_ADDR_LEN : 0;
+ (family == AF_INET) ? IPV4_ADDR_LEN :
+ 0;
}
int
-ip_address_ntop (const ip_address_t * ip_address, char *dst, const size_t len,
- int family)
+hicn_ip_address_get_len (const hicn_ip_address_t *ip_address)
{
- const char * s;
- switch(family) {
+ return hicn_ip_address_len (hicn_ip_address_get_family (ip_address));
+}
+
+int
+hicn_ip_address_get_len_bits (const hicn_ip_address_t *ip_address)
+{
+ return bytes_to_bits (hicn_ip_address_get_len (ip_address));
+}
+
+int
+hicn_ip_address_ntop (const hicn_ip_address_t *ip_address, char *dst,
+ const size_t len, int family)
+{
+ const char *s;
+ switch (family)
+ {
case AF_INET:
- s = inet_ntop (AF_INET, ip_address->v4.buffer, dst, (socklen_t)len);
+ s = inet_ntop (AF_INET, ip_address->v4.buffer, dst, (socklen_t) len);
break;
case AF_INET6:
- s = inet_ntop (AF_INET6, ip_address->v6.buffer, dst, (socklen_t)len);
+ s = inet_ntop (AF_INET6, ip_address->v6.buffer, dst, (socklen_t) len);
break;
default:
return -1;
- }
+ }
return (s ? 1 : -1);
}
@@ -106,22 +134,26 @@ ip_address_ntop (const ip_address_t * ip_address, char *dst, const size_t len,
* Parse ip addresses in presentation format
*/
int
-ip_address_pton (const char *ip_address_str, ip_address_t * ip_address)
+hicn_ip_address_pton (const char *hicn_ip_address_str,
+ hicn_ip_address_t *ip_address)
{
int pton_fd;
int family;
- family = ip_address_get_family (ip_address_str);
+ family = hicn_ip_address_str_get_family (hicn_ip_address_str);
- switch (family) {
+ switch (family)
+ {
case AF_INET:
ip_address->pad[0] = 0;
ip_address->pad[1] = 0;
ip_address->pad[2] = 0;
- pton_fd = inet_pton (AF_INET, ip_address_str, &ip_address->v4.buffer);
+ pton_fd =
+ inet_pton (AF_INET, hicn_ip_address_str, &ip_address->v4.buffer);
break;
case AF_INET6:
- pton_fd = inet_pton (AF_INET6, ip_address_str, &ip_address->v6.buffer);
+ pton_fd =
+ inet_pton (AF_INET6, hicn_ip_address_str, &ip_address->v6.buffer);
break;
default:
return -1;
@@ -132,36 +164,38 @@ ip_address_pton (const char *ip_address_str, ip_address_t * ip_address)
if (pton_fd <= 0)
return -1;
- return 1;
+ return 0;
}
int
-ip_address_snprintf(char * s, size_t size, const ip_address_t * ip_address, int family)
+hicn_ip_address_snprintf (char *s, size_t size,
+ const hicn_ip_address_t *ip_address)
{
-
- const char * rc;
- switch(family) {
- case AF_INET:
- if (size < INET_ADDRSTRLEN)
- return -1;
- rc = inet_ntop (AF_INET, ip_address->v4.buffer, s, INET_ADDRSTRLEN);
- break;
- case AF_INET6:
- if (size < INET6_ADDRSTRLEN)
- return -1;
- rc = inet_ntop (AF_INET6, ip_address->v6.buffer, s, INET6_ADDRSTRLEN);
- break;
- default:
- return -1;
+ const char *rc;
+ int family = hicn_ip_address_get_family (ip_address);
+ switch (family)
+ {
+ case AF_INET:
+ if (size < INET_ADDRSTRLEN)
+ return -1;
+ rc = inet_ntop (AF_INET, ip_address->v4.buffer, s, INET_ADDRSTRLEN);
+ break;
+ case AF_INET6:
+ if (size < INET6_ADDRSTRLEN)
+ return -1;
+ rc = inet_ntop (AF_INET6, ip_address->v6.buffer, s, INET6_ADDRSTRLEN);
+ break;
+ default:
+ return -1;
}
- if (!rc)
- return -1;
- return (int)strlen(s);
+ if (!rc)
+ return -1;
+ return (int) strnlen_s (s, MAXSZ_IP_ADDRESS);
}
int
-ip_address_to_sockaddr(const ip_address_t * ip_address,
- struct sockaddr *sa, int family)
+hicn_ip_address_to_sockaddr (const hicn_ip_address_t *ip_address,
+ struct sockaddr *sa, int family)
{
struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) sa;
struct sockaddr_in *tmp4 = (struct sockaddr_in *) sa;
@@ -187,64 +221,72 @@ ip_address_to_sockaddr(const ip_address_t * ip_address,
}
int
-ip_address_cmp(const ip_address_t * ip1, const ip_address_t * ip2, int family)
+hicn_ip_address_cmp (const hicn_ip_address_t *ip1,
+ const hicn_ip_address_t *ip2)
{
- switch(family) {
- case AF_INET:
- return memcmp(&ip1->v4, &ip2->v4, sizeof(ip1->v4));
- break;
- case AF_INET6:
- return memcmp(&ip1->v6, &ip2->v6, sizeof(ip1->v6));
- break;
- default:
- return memcmp(ip1, ip2, sizeof(ip_address_t));
- }
+ /* This works as soon as all members are initialized */
+ return memcmp (ip1, ip2, sizeof (hicn_ip_address_t));
}
-int
-ip_address_empty(const ip_address_t * ip)
+bool
+hicn_ip_address_equals (const hicn_ip_address_t *ip1,
+ const hicn_ip_address_t *ip2)
{
- return (memcmp(ip, &IP_ADDRESS_EMPTY, sizeof(IP_ADDRESS_EMPTY)) == 0);
+ return hicn_ip_address_cmp (ip1, ip2) == 0;
}
+int
+hicn_ip_address_empty (const hicn_ip_address_t *ip)
+{
+ return (memcmp (ip, &IP_ADDRESS_EMPTY, sizeof (hicn_ip_address_t)) == 0);
+}
+void
+hicn_ip_address_clear (hicn_ip_address_t *address)
+{
+ memset (address, 0, sizeof (hicn_ip_address_t));
+}
/* Prefix */
/* Parse IP Prefixes in presentation format (in bits, separated by a slash) */
int
-ip_prefix_pton (const char *ip_address_str, ip_prefix_t * ip_prefix)
+hicn_ip_prefix_pton (const char *hicn_ip_address_str,
+ hicn_ip_prefix_t *hicn_ip_prefix)
{
int pton_fd;
char *p;
char *eptr;
- char *addr = strdup (ip_address_str);
+ char *addr = strdup (hicn_ip_address_str);
p = strchr (addr, '/');
- if (!p) {
- ip_prefix->len = ~0; // until we get the ip address family
- } else {
- ip_prefix->len = (u8)strtoul (p + 1, &eptr, 10);
- *p = 0;
- }
+ if (!p)
+ {
+ hicn_ip_prefix->len = ~0; // until we get the ip address family
+ }
+ else
+ {
+ hicn_ip_prefix->len = (u8) strtoul (p + 1, &eptr, 10);
+ *p = 0;
+ }
- ip_prefix->family = ip_address_get_family (addr);
+ hicn_ip_prefix->family = hicn_ip_address_str_get_family (addr);
- switch (ip_prefix->family)
+ switch (hicn_ip_prefix->family)
{
case AF_INET6:
- if (ip_prefix->len == (u8)~0)
- ip_prefix->len = IPV6_ADDR_LEN_BITS;
- if (ip_prefix->len > IPV6_ADDR_LEN_BITS)
- goto ERR;
- pton_fd = inet_pton (AF_INET6, addr, &ip_prefix->address.v6.buffer);
+ if (hicn_ip_prefix->len == (u8) ~0)
+ hicn_ip_prefix->len = IPV6_ADDR_LEN_BITS;
+ if (hicn_ip_prefix->len > IPV6_ADDR_LEN_BITS)
+ goto ERR;
+ pton_fd = inet_pton (AF_INET6, addr, &hicn_ip_prefix->address.v6.buffer);
break;
case AF_INET:
- if (ip_prefix->len == (u8)~0)
- ip_prefix->len = IPV4_ADDR_LEN_BITS;
- if (ip_prefix->len > IPV4_ADDR_LEN_BITS)
- goto ERR;
- pton_fd = inet_pton (AF_INET, addr, &ip_prefix->address.v4.buffer);
+ if (hicn_ip_prefix->len == (u8) ~0)
+ hicn_ip_prefix->len = IPV4_ADDR_LEN_BITS;
+ if (hicn_ip_prefix->len > IPV4_ADDR_LEN_BITS)
+ goto ERR;
+ pton_fd = inet_pton (AF_INET, addr, &hicn_ip_prefix->address.v4.buffer);
break;
default:
goto ERR;
@@ -253,139 +295,180 @@ ip_prefix_pton (const char *ip_address_str, ip_prefix_t * ip_prefix)
// 0 = not in presentation format
// < 0 = other error (use perror)
if (pton_fd <= 0)
- goto ERR;
+ goto ERR;
- free(addr);
- return 1;
+ free (addr);
+ return 0;
ERR:
free (addr);
return -1;
}
int
-ip_prefix_ntop_short(const ip_prefix_t * ip_prefix, char *dst, size_t size)
+hicn_ip_prefix_ntop_short (const hicn_ip_prefix_t *hicn_ip_prefix, char *dst,
+ size_t size)
{
char ip_s[MAXSZ_IP_ADDRESS];
- const char * s;
- switch(ip_prefix->family) {
+ const char *s;
+ switch (hicn_ip_prefix->family)
+ {
case AF_INET:
- s = inet_ntop (AF_INET, ip_prefix->address.v4.buffer, ip_s, MAXSZ_IP_ADDRESS);
+ s = inet_ntop (AF_INET, hicn_ip_prefix->address.v4.buffer, ip_s,
+ MAXSZ_IP_ADDRESS);
break;
case AF_INET6:
- s = inet_ntop (AF_INET6, ip_prefix->address.v6.buffer, ip_s, MAXSZ_IP_ADDRESS);
+ s = inet_ntop (AF_INET6, hicn_ip_prefix->address.v6.buffer, ip_s,
+ MAXSZ_IP_ADDRESS);
break;
default:
return -1;
- }
+ }
if (!s)
- return -1;
- int rc = snprintf(dst, size, "%s", ip_s);
+ return -1;
+ int rc = snprintf (dst, size, "%s", ip_s);
if (rc >= size)
- return (int)size;
+ return (int) size;
return rc;
}
int
-ip_prefix_ntop(const ip_prefix_t * ip_prefix, char *dst, size_t size)
+hicn_ip_prefix_ntop (const hicn_ip_prefix_t *hicn_ip_prefix, char *dst,
+ size_t size)
{
char ip_s[MAXSZ_IP_ADDRESS];
- const char * s;
- switch(ip_prefix->family) {
+ const char *s;
+ switch (hicn_ip_prefix->family)
+ {
case AF_INET:
- s = inet_ntop (AF_INET, ip_prefix->address.v4.buffer, ip_s, MAXSZ_IP_ADDRESS);
+ s = inet_ntop (AF_INET, hicn_ip_prefix->address.v4.buffer, ip_s,
+ MAXSZ_IP_ADDRESS);
break;
case AF_INET6:
- s = inet_ntop (AF_INET6, ip_prefix->address.v6.buffer, ip_s, MAXSZ_IP_ADDRESS);
+ s = inet_ntop (AF_INET6, hicn_ip_prefix->address.v6.buffer, ip_s,
+ MAXSZ_IP_ADDRESS);
break;
default:
return -1;
- }
+ }
if (!s)
- return -1;
- int rc = snprintf(dst, size, "%s/%d", ip_s, ip_prefix->len);
+ return -1;
+ int rc = snprintf (dst, size, "%s/%d", ip_s, hicn_ip_prefix->len);
if (rc >= size)
- return (int)size;
+ return (int) size;
return rc;
}
int
-ip_prefix_len (const ip_prefix_t * prefix)
+hicn_ip_prefix_snprintf (char *s, size_t size, const hicn_ip_prefix_t *prefix)
+{
+ return hicn_ip_prefix_ntop (prefix, s, size);
+}
+
+int
+hicn_ip_prefix_len (const hicn_ip_prefix_t *prefix)
{
- return prefix->len; // ip_address_len(&prefix->address, prefix->family);
+ return prefix->len; // hicn_ip_address_len(&prefix->address, prefix->family);
}
const u8 *
-ip_address_get_buffer(const ip_address_t * ip_address, int family)
+hicn_ip_address_get_buffer (const hicn_ip_address_t *ip_address, int family)
{
- switch(family) {
+ switch (family)
+ {
case AF_INET:
return ip_address->v4.buffer;
case AF_INET6:
return ip_address->v6.buffer;
default:
return NULL;
- }
+ }
}
bool
-ip_prefix_empty (const ip_prefix_t * prefix)
+hicn_ip_prefix_empty (const hicn_ip_prefix_t *prefix)
{
return prefix->len == 0;
}
int
-ip_prefix_to_sockaddr(const ip_prefix_t * prefix,
- struct sockaddr *sa)
+hicn_ip_prefix_to_sockaddr (const hicn_ip_prefix_t *prefix,
+ struct sockaddr *sa)
{
- // XXX assert len == ip_address_len
- return ip_address_to_sockaddr(&prefix->address, sa, prefix->family);
+ // XXX assert len == hicn_ip_address_len
+ return hicn_ip_address_to_sockaddr (&prefix->address, sa, prefix->family);
}
int
-ip_prefix_cmp(const ip_prefix_t * prefix1, const ip_prefix_t * prefix2)
+hicn_ip_prefix_cmp (const hicn_ip_prefix_t *prefix1,
+ const hicn_ip_prefix_t *prefix2)
+{
+ if (prefix1->family < prefix2->family)
+ return -1;
+ else if (prefix1->family > prefix2->family)
+ return 1;
+
+ if (prefix1->len < prefix2->len)
+ return -1;
+ else if (prefix1->len > prefix2->len)
+ return 1;
+
+ return hicn_ip_address_cmp (&prefix1->address, &prefix2->address);
+}
+
+/* Network byte order + host bit order */
+
+uint8_t
+hicn_ip_address_get_bit (const hicn_ip_address_t *address, uint8_t pos)
{
- if (prefix1->family < prefix2->family)
- return -1;
- else if (prefix1->family > prefix2->family)
- return 1;
+ return (address->v6.as_u8[pos / 8] >> (7 - pos % 8)) & 0x1;
+}
- if (prefix1->len < prefix2->len)
- return -1;
- else if (prefix1->len > prefix2->len)
- return 1;
+bool
+hicn_ip_address_match_family (const hicn_ip_address_t *address, int family)
+{
+ return hicn_ip_address_get_family (address) == family;
+}
- return ip_address_cmp(&prefix1->address, &prefix2->address, prefix1->family);
+uint32_t
+hicn_ip_address_get_hash (const hicn_ip_address_t *address)
+{
+ return hash32 (address, sizeof (address));
}
/* URL */
#define MAXSZ_PROTO_ 8 /* inetX:// */
-#define MAXSZ_PROTO MAXSZ_PROTO_ + NULLTERM
+#define MAXSZ_PROTO MAXSZ_PROTO_ + NULLTERM
#define MAXSZ_URL4_ MAXSZ_PROTO_ + MAXSZ_IP4_ADDRESS_ + MAXSZ_PORT_
#define MAXSZ_URL6_ MAXSZ_PROTO_ + MAXSZ_IP6_ADDRESS_ + MAXSZ_PORT_
-#define MAXSZ_URL_ MAXSZ_URL6_
-#define MAXSZ_URL4 MAXSZ_URL4_ + NULLTERM
-#define MAXSZ_URL6 MAXSZ_URL6_ + NULLTERM
-#define MAXSZ_URL MAXSZ_URL_ + NULLTERM
+#define MAXSZ_URL_ MAXSZ_URL6_
+#define MAXSZ_URL4 MAXSZ_URL4_ + NULLTERM
+#define MAXSZ_URL6 MAXSZ_URL6_ + NULLTERM
+#define MAXSZ_URL MAXSZ_URL_ + NULLTERM
int
-url_snprintf(char * s, size_t size, int family,
- const ip_address_t * ip_address, u16 port)
+url_snprintf (char *s, size_t size, const hicn_ip_address_t *ip_address,
+ u16 port)
{
- char ip_address_s[MAXSZ_IP_ADDRESS];
- int rc;
+ char hicn_ip_address_s[MAXSZ_IP_ADDRESS];
+ int rc;
- /* Other address are currently not supported */
- if (!IS_VALID_FAMILY(family))
- return -1;
+ int family = hicn_ip_address_get_family (ip_address);
- rc = ip_address_snprintf(ip_address_s, MAXSZ_IP_ADDRESS, ip_address, family);
- if (rc >= MAXSZ_IP_ADDRESS)
- WARN("[url_snprintf] Unexpected ip_address truncation");
- if (rc < 0)
- return rc;
+ /* Other address are currently not supported */
+ if (!IS_VALID_FAMILY (family))
+ return -1;
- return snprintf(s, size, "inet%c://%s:%d", (family == AF_INET) ? '4' : '6',
- ip_address_s, port);
+ if (!hicn_ip_address_match_family (ip_address, family))
+ return -1;
+ rc =
+ hicn_ip_address_snprintf (hicn_ip_address_s, MAXSZ_IP_ADDRESS, ip_address);
+ if (rc >= MAXSZ_IP_ADDRESS)
+ WARN ("[url_snprintf] Unexpected ip_address truncation");
+ if (rc < 0)
+ return rc;
+
+ return snprintf (s, size, "inet%c://%s:%d", (family == AF_INET) ? '4' : '6',
+ hicn_ip_address_s, port);
}
diff --git a/lib/src/util/log.c b/lib/src/util/log.c
index c1fc999ad..91a87e848 100644
--- a/lib/src/util/log.c
+++ b/lib/src/util/log.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -18,6 +18,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
+#include <strings.h>
#ifdef __ANDROID__
#include <android/log.h>
@@ -25,154 +26,184 @@
log_conf_t log_conf = DEFAULT_LOG_CONF;
-#define FMT_DATETIME "%02d-%02d-%04d %02d:%02d:%02d"
-#define FMT_DATETIME_LEN 20
-#define snprintf_nowarn(...) (snprintf(__VA_ARGS__) < 0 ? abort() : (void)0)
+#define FMT_DATETIME "%02d-%02d-%04d %02d:%02d:%02d"
+#define FMT_DATETIME_LEN 20
+#define snprintf_nowarn(...) (snprintf (__VA_ARGS__) < 0 ? abort () : (void) 0)
+#define COLOR_RED "\033[31m"
+#define COLOR_YELLOW "\033[33m"
+#define COLOR_RESET "\033[0m"
static char ts[FMT_DATETIME_LEN];
-static char *timestamp(void)
+static char *
+timestamp (void)
{
- time_t tv;
- struct tm *tm;
+ time_t tv;
+ struct tm *tm;
- time(&tv);
- tm = localtime(&tv);
+ time (&tv);
+ tm = localtime (&tv);
- snprintf_nowarn(ts, FMT_DATETIME_LEN, FMT_DATETIME, tm->tm_mday,
- tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min,
- tm->tm_sec);
- return ts;
+ snprintf_nowarn (ts, FMT_DATETIME_LEN, FMT_DATETIME, tm->tm_mday,
+ tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min,
+ tm->tm_sec);
+ return ts;
}
-void _log_va(int level, const char *fmt, va_list ap)
-{
+void
+_log_va (int level, const char *fmt, va_list ap)
+{
#if 0
if (!conf.log_system)
return;
#endif
- char *prefix;
+ char *prefix;
#ifdef __ANDROID__
- int prio = -1;
- if (level > log_conf.log_level)
- return;
-
- switch (level) {
- case LOG_FATAL:
- prio = ANDROID_LOG_FATAL;
- prefix = "FATAL: ";
- break;
- case LOG_ERROR:
- prio = ANDROID_LOG_ERROR;
- prefix = "ERROR: ";
- break;
- case LOG_WARN:
- prio = ANDROID_LOG_WARN;
- prefix = "WARNING: ";
- break;
- case LOG_INFO:
- prio = ANDROID_LOG_INFO;
- prefix = "";
- break;
- case LOG_DEBUG:
- prio = ANDROID_LOG_DEBUG;
- prefix = "DEBUG: ";
- break;
- case LOG_TRACE:
- prio = ANDROID_LOG_DEBUG;
- prefix = "TRACE: ";
- break;
- default:
- prio = ANDROID_LOG_INFO;
- prefix = "";
- break;
- }
-
- if (log_conf.log_file) {
- FILE *f = log_conf.log_file;
- fprintf(f, "%s %s", timestamp(), prefix);
- vfprintf(f, fmt, ap);
- fprintf(f, "\n");
- } else {
- __android_log_vprint(ANDROID_LOG_INFO, "HICN FACEMGR", fmt, ap);
- }
+ int prio = -1;
+ if (level > log_conf.log_level)
+ return;
+
+ switch (level)
+ {
+ case LOG_FATAL:
+ prio = ANDROID_LOG_FATAL;
+ prefix = "FATAL: ";
+ break;
+ case LOG_ERROR:
+ prio = ANDROID_LOG_ERROR;
+ prefix = "ERROR: ";
+ break;
+ case LOG_WARN:
+ prio = ANDROID_LOG_WARN;
+ prefix = "WARNING: ";
+ break;
+ case LOG_INFO:
+ prio = ANDROID_LOG_INFO;
+ prefix = "";
+ break;
+ case LOG_DEBUG:
+ prio = ANDROID_LOG_DEBUG;
+ prefix = "DEBUG: ";
+ break;
+ case LOG_TRACE:
+ prio = ANDROID_LOG_DEBUG;
+ prefix = "TRACE: ";
+ break;
+ default:
+ prio = ANDROID_LOG_INFO;
+ prefix = "";
+ break;
+ }
+
+ if (log_conf.log_file)
+ {
+ FILE *f = log_conf.log_file;
+ fprintf (f, "%s %s", timestamp (), prefix);
+ vfprintf (f, fmt, ap);
+ fprintf (f, "\n");
+ }
+ else
+ {
+ __android_log_vprint (prio, "HICN FACEMGR", fmt, ap);
+ }
#else
- if (level > log_conf.log_level)
- return;
-
- switch (level) {
- case LOG_FATAL:
- prefix = "FATAL: ";
- break;
- case LOG_ERROR:
- prefix = "ERROR: ";
- break;
- case LOG_WARN:
- prefix = "WARNING: ";
- break;
- case LOG_INFO:
- prefix = "";
- break;
- case LOG_DEBUG:
- prefix = "DEBUG: ";
- break;
- case LOG_TRACE:
- prefix = "TRACE: ";
- break;
- default:
- prefix = "";
- break;
- }
- FILE *f = log_conf.log_file ? log_conf.log_file : stdout;
- fprintf(f, "%s %s", timestamp(), prefix);
- vfprintf(f, fmt, ap);
- fprintf(f, "\n");
+ if (level > log_conf.log_level)
+ return;
+
+ char *color = COLOR_RESET;
+ switch (level)
+ {
+ case LOG_FATAL:
+ prefix = "FATAL: ";
+ break;
+ case LOG_ERROR:
+ prefix = "ERROR: ";
+ color = COLOR_RED;
+ break;
+ case LOG_WARN:
+ prefix = "WARNING: ";
+ color = COLOR_YELLOW;
+ break;
+ case LOG_INFO:
+ prefix = "";
+ break;
+ case LOG_DEBUG:
+ prefix = "DEBUG: ";
+ break;
+ case LOG_TRACE:
+ prefix = "TRACE: ";
+ break;
+ default:
+ prefix = "";
+ break;
+ }
+ FILE *f = log_conf.log_file ? log_conf.log_file : stdout;
+ fprintf (f, "%s%s %s", color, timestamp (), prefix);
+ vfprintf (f, fmt, ap);
+ fprintf (f, "%s\n", COLOR_RESET);
#ifdef DEBUG
- fflush(f);
+ fflush (f);
#endif
#endif
}
-void _log(int level, const char *fmt, ...)
+void
+_log (int level, const char *fmt, ...)
{
- va_list ap;
+ va_list ap;
- va_start(ap, fmt);
- _log_va(level, fmt, ap);
- va_end(ap);
+ va_start (ap, fmt);
+ _log_va (level, fmt, ap);
+ va_end (ap);
}
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
-void print_trace(void)
+void
+print_trace (void)
{
- void *array[32];
- size_t size;
+ void *array[32];
+ size_t size;
- size = backtrace(array, 32);
- fflush(conf.log_file);
- backtrace_symbols_fd(array, size, fileno(conf.log_file));
+ size = backtrace (array, 32);
+ fflush (conf.log_file);
+ backtrace_symbols_fd (array, size, fileno (conf.log_file));
}
#endif
-void fatal(char *fmt, ...)
+void
+fatal (char *fmt, ...)
{
- va_list ap;
+ va_list ap;
- va_start(ap, fmt);
- _log_va(LOG_FATAL, fmt, ap);
- va_end(ap);
+ va_start (ap, fmt);
+ _log_va (LOG_FATAL, fmt, ap);
+ va_end (ap);
#ifdef HAVE_BACKTRACE
- print_trace();
+ print_trace ();
#endif
- exit(200);
+ exit (200);
}
+
+const char *loglevel_str[] = { "fatal", "error", "warn",
+ "info", "debug", "trace" };
+
+int
+loglevel_from_str (const char *loglevel)
+{
+ for (int i = 0; i <= LOG_TRACE; i++)
+ {
+ if (strcasecmp (loglevel, loglevel_str[i]) == 0)
+ return i;
+ }
+ return -1;
+} \ No newline at end of file
diff --git a/lib/src/util/pool.c b/lib/src/util/pool.c
new file mode 100644
index 000000000..2c1e90b5e
--- /dev/null
+++ b/lib/src/util/pool.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file pool.c
+ * \brief Implementation of fixed-size pool allocator.
+ *
+ * NOTE:
+ * - Ideally, we should have a single realloc per resize, that would encompass
+ * both the free indices vector and bitmap, by nesting data structures.
+ * Because of the added complexity, and by lack of evidence of the need for
+ * this, we currently rely on a simpler implementation.
+ */
+
+#include <assert.h>
+#include <stdlib.h> // calloc
+
+#include <hicn/util/pool.h>
+#include <hicn/util/log.h>
+
+#include <stdio.h> // XXX
+
+void
+_pool_init (void **pool_ptr, size_t elt_size, size_t init_size,
+ size_t max_size)
+{
+ assert (pool_ptr);
+ assert (elt_size);
+
+ 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, 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 */
+ bitmap_t *fb = ph->free_bitmap;
+ 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
+_pool_free (void **pool_ptr)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ vector_free (ph->free_indices);
+ bitmap_free (ph->free_bitmap);
+
+ free (pool_hdr (*pool_ptr));
+ *pool_ptr = NULL;
+}
+
+bool
+_pool_validate_id (void **pool_ptr, off_t id)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ size_t pool_size = pool_get_alloc_size (*pool_ptr);
+ if (id >= pool_size || !bitmap_is_unset (ph->free_bitmap, id))
+ return false;
+
+ return true;
+}
+
+void
+_pool_resize (void **pool_ptr, size_t elt_size)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ size_t old_size = ph->alloc_size;
+ size_t new_size = old_size * 2;
+
+ WARN ("pool_resize to %lu", new_size);
+
+ if (ph->max_size && new_size > ph->max_size)
+ goto ERR_MAX_SIZE;
+
+ /* Double pool storage */
+ ph = realloc (ph, POOL_HDRLEN + new_size * elt_size);
+ if (!ph)
+ goto ERR_REALLOC;
+ ph->elt_size = elt_size;
+ ph->alloc_size = new_size;
+
+ /*
+ * After resize, the pool will have new free indices, ranging from
+ * old_size to (new_size - 1)
+ */
+ 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;
+}
+
+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)
+ {
+ _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 * elt_size;
+ return free_id;
+}
+
+void
+_pool_put (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);
+ vector_ensure_pos (ph->free_indices, l);
+ off_t freed_id = (*elt - *pool_ptr) / elt_size;
+ ph->free_indices[l] = freed_id;
+ vector_len (ph->free_indices)++;
+ bitmap_set (ph->free_bitmap, freed_id);
+}
diff --git a/lib/src/util/ring.c b/lib/src/util/ring.c
new file mode 100644
index 000000000..2c722a842
--- /dev/null
+++ b/lib/src/util/ring.c
@@ -0,0 +1,49 @@
+
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file ring.c
+ * \brief Implementation of ring buffer.
+ */
+
+#include <stdlib.h>
+
+#include <hicn/util/ring.h>
+
+void
+_ring_init (void **ring_ptr, size_t elt_size, size_t max_size)
+{
+ assert (ring_ptr);
+ assert (elt_size > 0);
+ // we use a static array, not a vector (for now)
+ assert (max_size != 0);
+
+ ring_hdr_t *rh = malloc (RING_HDRLEN + max_size * elt_size);
+
+ rh->roff = 0;
+ rh->woff = 0;
+ rh->size = 0;
+ rh->max_size = max_size;
+
+ *ring_ptr = (uint8_t *) rh + RING_HDRLEN;
+}
+
+void
+_ring_free (void **ring_ptr)
+{
+ free (ring_hdr (*ring_ptr));
+ *ring_ptr = NULL;
+}
diff --git a/lib/src/util/slab.c b/lib/src/util/slab.c
new file mode 100644
index 000000000..763dcb444
--- /dev/null
+++ b/lib/src/util/slab.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/util/pool.h>
+#include <hicn/util/slab.h>
+#include <stdlib.h>
+
+/* BLOCK LINKED LISTS */
+
+static void
+block_add_to_head (block_t **head_ptr, block_t *block)
+{
+ if (head_ptr == NULL || block == NULL)
+ return;
+
+ block->prev = NULL;
+ if (*head_ptr != NULL)
+ {
+ block->next = *head_ptr;
+ block->next->prev = block;
+ }
+
+ *head_ptr = block;
+}
+
+static block_t *
+block_remove_from_head (block_t **head_ptr)
+{
+ if (head_ptr == NULL || *head_ptr == NULL)
+ return NULL;
+
+ block_t *old_head = *head_ptr;
+ *head_ptr = old_head->next;
+
+ if (*head_ptr != NULL)
+ (*head_ptr)->prev = NULL;
+ return old_head;
+}
+
+static void
+block_remove (block_t **head_ptr, block_t *block)
+{
+ if (*head_ptr == NULL || block == NULL)
+ return;
+
+ if (block == *head_ptr)
+ *head_ptr = block->next;
+ if (block->next != NULL)
+ block->next->prev = block->prev;
+ if (block->prev != NULL)
+ block->prev->next = block->next;
+}
+
+static bool
+is_block_list_empty (block_t *block)
+{
+ return block == NULL;
+}
+
+static void
+block_list_free (block_t **head)
+{
+ if (head == NULL || *head == NULL)
+ return;
+
+ block_t *curr_block = *head;
+ while (curr_block != NULL)
+ {
+ block_t *next = curr_block->next;
+ pool_free (curr_block->pool);
+ free (curr_block);
+
+ curr_block = next;
+ }
+
+ *head = NULL;
+}
+
+/* BLOCK */
+
+static bool
+is_block_full (block_t *block)
+{
+ return pool_get_free_indices_size (block->pool) == 0;
+}
+
+static void
+block_set_ptr_in_chunks (block_t *block, size_t chunk_size)
+{
+ void *chunk = block->pool;
+
+ // Cannot use `pool_foreach()` since it requires to know the type
+ // while here we use a generic (void *)
+ for (int i = 0; i < pool_get_alloc_size (block->pool); i++)
+ {
+ chunk_hdr_t *hdr = (chunk_hdr_t *) chunk;
+ hdr->block = block;
+
+ chunk = (uint8_t *) (chunk) + chunk_size; // Move to next chunk
+ }
+}
+
+static block_t *
+block_create (size_t chunk_size, size_t num_chunks)
+{
+ block_t *block = malloc (sizeof (block_t));
+ if (block == NULL)
+ return NULL;
+
+ block->prev = block->next = NULL;
+ _pool_init (&block->pool, chunk_size, num_chunks, 0);
+ block_set_ptr_in_chunks (block, chunk_size);
+
+ return block;
+}
+
+/* SLAB */
+
+slab_t *
+_slab_create (size_t elt_size, size_t num_elts)
+{
+ // Initialize slab
+ slab_t *slab = malloc (sizeof (slab_t));
+ if (slab == NULL)
+ return NULL;
+
+ *slab = (slab_t){ .num_chunks = next_pow2 (num_elts),
+ .chunk_size = CHUNK_HDRLEN + elt_size,
+ .full = NULL,
+ .partial_or_empty = NULL };
+
+ // Add initial empty block to partial or empty list
+ block_t *block = block_create (slab->chunk_size, slab->num_chunks);
+ block_add_to_head (&slab->partial_or_empty, block);
+
+ return slab;
+}
+
+void
+slab_free (slab_t *slab)
+{
+ block_list_free (&slab->full);
+ block_list_free (&slab->partial_or_empty);
+ free (slab);
+}
+
+void *
+_slab_get (slab_t *slab)
+{
+ // Create new empty block if none with available chunks
+ if (is_block_list_empty (slab->partial_or_empty))
+ {
+ block_t *block = block_create (slab->chunk_size, slab->num_chunks);
+ block_add_to_head (&slab->partial_or_empty, block);
+
+ slab->num_chunks *= 2; // Grow size exponentially
+ }
+
+ // Get chunck from first block in 'partial_or_empty' list
+ void *chunk;
+ _pool_get (&slab->partial_or_empty->pool, &chunk, slab->chunk_size);
+
+ // If the current block (i.e. head of 'partial_or_empty' list) if full,
+ // move it to the 'full' list
+ if (is_block_full (slab->partial_or_empty))
+ {
+ block_t *block = block_remove_from_head (&slab->partial_or_empty);
+ block_add_to_head (&slab->full, block);
+ }
+
+ return (uint8_t *) chunk + CHUNK_HDRLEN;
+}
+
+void
+_slab_put (slab_t *slab, void *chunk)
+{
+ // Get which block the chunk (that we want to release) belong to
+ chunk_hdr_t *hdr = chunk_hdr (chunk);
+ block_t *block = hdr->block;
+
+ // Put chunk back into block
+ bool is_full = is_block_full (block);
+ _pool_put (&block->pool, (void *) &hdr, slab->chunk_size);
+
+ // If the block was previously full, move it to 'partial_or_empty' list
+ if (is_full)
+ {
+ block_remove (&slab->full, block);
+ block_add_to_head (&slab->partial_or_empty, block);
+ }
+} \ No newline at end of file
diff --git a/lib/src/util/types.c b/lib/src/util/types.c
new file mode 100644
index 000000000..744192593
--- /dev/null
+++ b/lib/src/util/types.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/util/types.h>
+
+uint32_t
+htonf (float f)
+{
+ uint32_t i;
+ uint32_t sign = 0;
+
+ if (f < 0)
+ {
+ sign = 1;
+ f = -f;
+ }
+
+ // i[31] = sign bit
+ i = sign << 31;
+
+ // i[30 to 16] = int(f)[14 to 0]
+ i |= (((uint32_t) f) & 0x7fff) << 16;
+
+ // i[15 to 0] = fraction(f) bits [15 to 0]
+ i |= (uint32_t) ((f - (uint32_t) f) * 65536.0f) & 0xffff;
+
+ return i;
+}
+
+float
+ntohf (uint32_t i)
+{
+ // integer part = i[14 to 0]
+ float f = (i >> 16) & 0x7fff;
+
+ // fraction part = i[15 to 0]
+ f += (i & 0xffff) / 65536.0f;
+
+ // sign = i[31]
+ if ((i >> 31) & 1)
+ f = -f;
+
+ return f;
+}
diff --git a/lib/src/util/vector.c b/lib/src/util/vector.c
new file mode 100644
index 000000000..1f5cd0269
--- /dev/null
+++ b/lib/src/util/vector.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file vector.c
+ * \brief Implementation of resizeable static array
+ */
+
+#include <assert.h>
+#include <stddef.h> // size_t
+#include <stdlib.h> // calloc
+#include <stdio.h>
+
+#include <hicn/util/vector.h>
+
+#define DEFAULT_VECTOR_SIZE 64
+
+int
+_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;
+
+ *vector_ptr = NULL;
+ int rc = _vector_resize (vector_ptr, elt_size, init_size);
+ if (rc < 0)
+ return -1;
+
+ vector_hdr_t *vh = vector_hdr (*vector_ptr);
+ vh->cur_size = 0;
+ vh->max_size = max_size;
+
+ return 0;
+}
+
+void
+_vector_free (void **vector_ptr)
+{
+ free (vector_hdr (*vector_ptr));
+ *vector_ptr = NULL;
+}
+
+int
+_vector_resize (void **vector_ptr, size_t elt_size, off_t pos)
+{
+ vector_hdr_t *vh;
+ size_t old_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 -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 0;
+}
diff --git a/lib/src/util/windows/dlfcn.c b/lib/src/util/windows/dlfcn.c
index c8173cdb0..5606074a0 100644
--- a/lib/src/util/windows/dlfcn.c
+++ b/lib/src/util/windows/dlfcn.c
@@ -1,4 +1,4 @@
-/* dlfcn.c */
+/* dlfcn.c */
#include <inttypes.h>
#include <stdio.h>
@@ -6,60 +6,68 @@
#include <string.h>
#include <windows.h>
-static struct {
- long lasterror;
- const char *err_rutin;
-} var = {
- 0,
- NULL
-};
+static struct
+{
+ long lasterror;
+ const char *err_rutin;
+} var = { 0, NULL };
-void *dlopen (const char *filename, int flags)
+void *
+dlopen (const char *filename, int flags)
{
- HINSTANCE hInst;
+ HINSTANCE hInst;
- hInst= LoadLibrary (filename);
- if (hInst==NULL) {
- var.lasterror = GetLastError ();
- var.err_rutin = "dlopen";
+ hInst = LoadLibrary (filename);
+ if (hInst == NULL)
+ {
+ var.lasterror = GetLastError ();
+ var.err_rutin = "dlopen";
}
- return hInst;
+ return hInst;
}
-int dlclose (void *handle)
+int
+dlclose (void *handle)
{
- BOOL ok;
- int rc= 0;
+ BOOL ok;
+ int rc = 0;
- ok= FreeLibrary ((HINSTANCE)handle);
- if (! ok) {
- var.lasterror = GetLastError ();
- var.err_rutin = "dlclose";
- rc= -1;
+ ok = FreeLibrary ((HINSTANCE) handle);
+ if (!ok)
+ {
+ var.lasterror = GetLastError ();
+ var.err_rutin = "dlclose";
+ rc = -1;
}
- return rc;
+ return rc;
}
-void *dlsym (void *handle, const char *name)
+void *
+dlsym (void *handle, const char *name)
{
- FARPROC fp;
+ FARPROC fp;
- fp= GetProcAddress ((HINSTANCE)handle, name);
- if (!fp) {
- var.lasterror = GetLastError ();
- var.err_rutin = "dlsym";
+ fp = GetProcAddress ((HINSTANCE) handle, name);
+ if (!fp)
+ {
+ var.lasterror = GetLastError ();
+ var.err_rutin = "dlsym";
}
- return (void *)(intptr_t)fp;
+ return (void *) (intptr_t) fp;
}
-const char *dlerror (void)
+const char *
+dlerror (void)
{
-static char errstr [88];
+ static char errstr[88];
- if (var.lasterror) {
- sprintf (errstr, "%s error #%ld", var.err_rutin, var.lasterror);
- return errstr;
- } else {
- return NULL;
+ if (var.lasterror)
+ {
+ snprintf (errstr, 88, "%s error #%ld", var.err_rutin, var.lasterror);
+ return errstr;
+ }
+ else
+ {
+ return NULL;
}
} \ No newline at end of file