aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt11
-rw-r--r--apps/CMakeLists.txt2
-rw-r--r--cmake/Modules/BuildMacros.cmake18
-rwxr-xr-xcmake/Modules/FindLibhicnctrl.cmake6
-rw-r--r--cmake/Modules/Packager.cmake12
-rw-r--r--ctrl/facemgr/CMakeLists.txt35
-rw-r--r--ctrl/facemgr/README.md10
-rw-r--r--ctrl/facemgr/cmake/Modules/Packaging.cmake12
-rw-r--r--ctrl/facemgr/doc/interface.md358
-rw-r--r--ctrl/facemgr/examples/facemgr.conf217
-rwxr-xr-xctrl/facemgr/examples/run-bonjour.sh162
-rw-r--r--ctrl/facemgr/examples/updowncli/Makefile25
-rw-r--r--ctrl/facemgr/examples/updowncli/updowncli.c57
-rw-r--r--ctrl/facemgr/examples/updownsrv/Makefile25
-rw-r--r--ctrl/facemgr/examples/updownsrv/updownsrv.c231
-rw-r--r--ctrl/facemgr/includes/CMakeLists.txt44
-rw-r--r--ctrl/facemgr/includes/facemgr.h (renamed from ctrl/facemgr/src/netdevice.c)18
-rw-r--r--ctrl/facemgr/includes/hicn/android_utility/android_utility.h48
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr.h (renamed from ctrl/facemgr/src/interface_map.h)15
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/api.h81
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/cfg.h193
-rw-r--r--ctrl/facemgr/includes/hicn/util/log.h (renamed from ctrl/facemgr/src/util/log.h)0
-rw-r--r--ctrl/facemgr/src/CMakeLists.txt79
-rw-r--r--ctrl/facemgr/src/api.c1421
-rw-r--r--ctrl/facemgr/src/cfg.c991
-rw-r--r--ctrl/facemgr/src/common.h35
-rw-r--r--ctrl/facemgr/src/event.c39
-rw-r--r--ctrl/facemgr/src/event.h59
-rw-r--r--ctrl/facemgr/src/face.c262
-rw-r--r--ctrl/facemgr/src/face.h177
-rw-r--r--ctrl/facemgr/src/face_cache.h24
-rw-r--r--ctrl/facemgr/src/face_rules.c21
-rw-r--r--ctrl/facemgr/src/facelet.c1008
-rw-r--r--ctrl/facemgr/src/facelet.h198
-rw-r--r--ctrl/facemgr/src/facemgr.c298
-rw-r--r--ctrl/facemgr/src/facemgr.h77
-rw-r--r--ctrl/facemgr/src/interface.c29
-rw-r--r--ctrl/facemgr/src/interface.h21
-rw-r--r--ctrl/facemgr/src/interface_map.c21
-rw-r--r--ctrl/facemgr/src/interface_ops_map.c21
-rw-r--r--ctrl/facemgr/src/interfaces/CMakeLists.txt11
-rw-r--r--ctrl/facemgr/src/interfaces/android_utility/CMakeLists.txt27
-rw-r--r--ctrl/facemgr/src/interfaces/android_utility/android_utility.c138
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt32
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/bonjour.c408
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/bonjour.h (renamed from ctrl/facemgr/src/face_rules.h)30
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/mdns/LICENSE24
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/mdns/README.md9
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c192
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h879
-rw-r--r--ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt1
-rw-r--r--ctrl/facemgr/src/interfaces/dummy/dummy.c98
-rw-r--r--ctrl/facemgr/src/interfaces/dummy/dummy.h (renamed from ctrl/facemgr/src/interface_ops_map.h)22
-rw-r--r--ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c204
-rw-r--r--ctrl/facemgr/src/interfaces/netlink/netlink.c472
-rw-r--r--ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt1
-rw-r--r--ctrl/facemgr/src/interfaces/network_framework/network_framework.c138
-rw-r--r--ctrl/facemgr/src/interfaces/network_framework/network_framework.h (renamed from ctrl/facemgr/src/face_cache.c)11
-rw-r--r--ctrl/facemgr/src/interfaces/updown/CMakeLists.txt31
-rw-r--r--ctrl/facemgr/src/interfaces/updown/updown.c138
-rw-r--r--ctrl/facemgr/src/main.c773
-rw-r--r--ctrl/facemgr/src/netdevice.h52
-rw-r--r--ctrl/facemgr/src/util/log.c60
-rw-r--r--ctrl/facemgr/src/util/map.h113
-rw-r--r--ctrl/facemgr/src/util/policy.c59
-rw-r--r--ctrl/facemgr/src/util/set.h95
-rw-r--r--ctrl/libhicnctrl/CMakeLists.txt31
-rw-r--r--[l---------]ctrl/libhicnctrl/includes/ctrl.h26
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h135
-rwxr-xr-xctrl/libhicnctrl/includes/hicn/ctrl/commands.h12
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/face.h90
-rw-r--r--ctrl/libhicnctrl/src/CMakeLists.txt28
-rw-r--r--ctrl/libhicnctrl/src/api.c300
-rw-r--r--ctrl/libhicnctrl/src/cli.c5
-rw-r--r--ctrl/libhicnctrl/src/face.c308
-rw-r--r--ctrl/libhicnctrl/src/util/ip_address.h316
-rw-r--r--ctrl/libhicnctrl/src/util/policy.c53
-rw-r--r--ctrl/libhicnctrl/src/util/policy.h266
-rw-r--r--ctrl/libhicnctrl/src/util/token.h40
-rw-r--r--ctrl/libhicnctrl/src/util/types.h36
-rw-r--r--ctrl/sysrepo-plugins/README.md200
-rw-r--r--hicn-light/CMakeLists.txt5
-rw-r--r--hicn-light/src/hicn/CMakeLists.txt5
-rw-r--r--hicn-light/src/hicn/config/configuration.c77
-rw-r--r--hicn-light/src/hicn/config/configurationListeners.c197
-rw-r--r--hicn-light/src/hicn/config/controlListConnections.c14
-rw-r--r--hicn-light/src/hicn/config/controlListListeners.c21
-rw-r--r--hicn-light/src/hicn/config/controlUpdateConnection.c2
-rw-r--r--hicn-light/src/hicn/core/connection.c10
-rw-r--r--hicn-light/src/hicn/core/connection.h4
-rw-r--r--hicn-light/src/hicn/core/mapMe.c6
-rw-r--r--hicn-light/src/hicn/core/nameBitvector.c14
-rw-r--r--hicn-light/src/hicn/core/nameBitvector.h3
-rw-r--r--hicn-light/src/hicn/io/hicnConnection.c16
-rw-r--r--hicn-light/src/hicn/io/hicnConnection.h2
-rw-r--r--hicn-light/src/hicn/io/hicnListener.c24
-rw-r--r--hicn-light/src/hicn/io/hicnTunnel.c2
-rw-r--r--hicn-light/src/hicn/io/ioOperations.c4
-rw-r--r--hicn-light/src/hicn/io/ioOperations.h11
-rw-r--r--hicn-light/src/hicn/io/listener.h18
-rw-r--r--hicn-light/src/hicn/io/listenerSet.c36
-rw-r--r--hicn-light/src/hicn/io/listenerSet.h37
-rw-r--r--hicn-light/src/hicn/io/streamConnection.c15
-rw-r--r--hicn-light/src/hicn/io/tcpListener.c30
-rw-r--r--hicn-light/src/hicn/io/tcpListener.h8
-rw-r--r--hicn-light/src/hicn/io/udpConnection.c17
-rw-r--r--hicn-light/src/hicn/io/udpConnection.h2
-rw-r--r--hicn-light/src/hicn/io/udpListener.c38
-rw-r--r--hicn-light/src/hicn/io/udpListener.h11
-rw-r--r--hicn-light/src/hicn/io/udpTunnel.c2
-rw-r--r--hicn-light/src/hicn/processor/fibEntry.c8
-rw-r--r--hicn-light/src/hicn/socket/api.c34
-rw-r--r--hicn-light/src/hicn/socket/api.h6
-rw-r--r--hicn-light/src/hicn/socket/ops.h18
-rw-r--r--hicn-light/src/hicn/socket/ops_linux.c102
-rw-r--r--hicn-light/src/hicn/utils/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/utils/commands.h13
-rw-r--r--hicn-light/src/hicn/utils/policy.h232
-rw-r--r--hicn-plugin/CMakeLists.txt43
-rw-r--r--hicn-plugin/README.md2
-rw-r--r--hicn-plugin/cmake/Modules/Packaging.cmake15
-rw-r--r--hicn-plugin/scripts/post20
-rw-r--r--hicn-plugin/scripts/postinst19
-rw-r--r--hicn-plugin/scripts/postun5
-rw-r--r--hicn-plugin/src/cli.c72
-rw-r--r--hicn-plugin/src/data_fwd_node.c5
-rw-r--r--hicn-plugin/src/data_pcslookup_node.c35
-rw-r--r--hicn-plugin/src/hicn.api12
-rw-r--r--hicn-plugin/src/hicn.c102
-rw-r--r--hicn-plugin/src/hicn_api.c118
-rw-r--r--hicn-plugin/src/hicn_api_test.c28
-rw-r--r--hicn-plugin/src/infra.h14
-rw-r--r--hicn-plugin/src/mgmt.c4
-rw-r--r--hicn-plugin/src/params.h9
-rw-r--r--hicn-plugin/src/pcs.h2
-rw-r--r--hicn-plugin/src/strategy.c10
-rw-r--r--lib/CMakeLists.txt1
-rw-r--r--lib/includes/CMakeLists.txt55
-rw-r--r--lib/includes/hicn/base.h (renamed from lib/src/base.h)0
-rw-r--r--lib/includes/hicn/common.h (renamed from lib/src/common.h)0
-rw-r--r--lib/includes/hicn/compat.h (renamed from lib/src/compat.h)12
-rw-r--r--lib/includes/hicn/error.h (renamed from lib/src/error.h)0
-rw-r--r--lib/includes/hicn/header.h (renamed from lib/src/header.h)0
-rw-r--r--lib/includes/hicn/hicn.h (renamed from lib/src/hicn.h)0
-rw-r--r--lib/includes/hicn/mapme.h (renamed from lib/src/mapme.h)0
-rw-r--r--lib/includes/hicn/name.h (renamed from lib/src/name.h)60
-rw-r--r--lib/includes/hicn/ops.h (renamed from lib/src/ops.h)0
-rw-r--r--lib/includes/hicn/policy.h (renamed from ctrl/facemgr/src/util/policy.h)10
-rw-r--r--lib/includes/hicn/protocol.h (renamed from lib/src/protocol.h)0
-rw-r--r--lib/includes/hicn/protocol/ah.h (renamed from lib/src/protocol/ah.h)0
-rw-r--r--lib/includes/hicn/protocol/icmp.h (renamed from lib/src/protocol/icmp.h)0
-rw-r--r--lib/includes/hicn/protocol/icmprd.h (renamed from lib/src/protocol/icmprd.h)0
-rw-r--r--lib/includes/hicn/protocol/ipv4.h (renamed from lib/src/protocol/ipv4.h)0
-rw-r--r--lib/includes/hicn/protocol/ipv6.h (renamed from lib/src/protocol/ipv6.h)0
-rw-r--r--lib/includes/hicn/protocol/tcp.h (renamed from lib/src/protocol/tcp.h)0
-rw-r--r--lib/includes/hicn/protocol/udp.h (renamed from lib/src/protocol/udp.h)0
-rw-r--r--lib/includes/hicn/util/ip_address.h160
-rw-r--r--lib/includes/hicn/util/token.h (renamed from ctrl/facemgr/src/util/token.h)0
-rw-r--r--lib/includes/hicn/util/types.h (renamed from ctrl/facemgr/src/util/types.h)2
-rw-r--r--lib/src/CMakeLists.txt63
-rw-r--r--lib/src/common.c3
-rw-r--r--lib/src/compat.c50
-rw-r--r--lib/src/error.c2
-rw-r--r--lib/src/mapme.c10
-rw-r--r--lib/src/name.c162
-rw-r--r--lib/src/ops.c4
-rw-r--r--lib/src/policy.c (renamed from hicn-light/src/hicn/utils/policy.c)2
-rw-r--r--lib/src/protocol/ah.c10
-rw-r--r--lib/src/protocol/icmp.c6
-rw-r--r--lib/src/protocol/ipv4.c10
-rw-r--r--lib/src/protocol/ipv6.c6
-rw-r--r--lib/src/protocol/tcp.c6
-rw-r--r--lib/src/util/ip_address.c (renamed from ctrl/facemgr/src/util/ip_address.h)229
-rw-r--r--libtransport/CMakeLists.txt4
-rw-r--r--libtransport/src/hicn/transport/CMakeLists.txt4
-rw-r--r--libtransport/src/hicn/transport/core/content_object.cc7
-rw-r--r--libtransport/src/hicn/transport/core/content_object.h4
-rw-r--r--libtransport/src/hicn/transport/core/facade.h2
-rw-r--r--libtransport/src/hicn/transport/core/forwarder_interface.h6
-rw-r--r--libtransport/src/hicn/transport/core/hicn_binary_api.c22
-rw-r--r--libtransport/src/hicn/transport/core/hicn_binary_api.h15
-rw-r--r--libtransport/src/hicn/transport/core/interest.cc8
-rw-r--r--libtransport/src/hicn/transport/core/interest.h4
-rw-r--r--libtransport/src/hicn/transport/core/name.cc6
-rw-r--r--libtransport/src/hicn/transport/core/name.h2
-rw-r--r--libtransport/src/hicn/transport/core/packet.h4
-rw-r--r--libtransport/src/hicn/transport/core/prefix.cc30
-rw-r--r--libtransport/src/hicn/transport/core/prefix.h6
-rw-r--r--libtransport/src/hicn/transport/core/raw_socket_interface.cc2
-rw-r--r--libtransport/src/hicn/transport/core/vpp_forwarder_interface.cc40
-rw-r--r--libtransport/src/hicn/transport/interfaces/rtc_socket_producer.cc142
-rw-r--r--libtransport/src/hicn/transport/interfaces/rtc_socket_producer.h18
-rw-r--r--libtransport/src/hicn/transport/protocols/rtc.cc2
-rw-r--r--utils/CMakeLists.txt2
194 files changed, 10753 insertions, 4226 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c0d689331..5977b7955 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,10 +72,11 @@ set(HICN_PLUGIN hicn-plugin)
set(HICN_EXTRA_PLUGIN hicn-extra-plugin)
set(LIBTRANSPORT hicntransport)
set(HICN_UTILS hicn-utils)
-set(HICN_CTRL hicn-ctrl)
-set(LIBHICN_CTRL hicn-ctrl)
+set(HICNCTRL hicnctrl)
+set(LIBHICNCTRL hicnctrl)
set(HICN_APPS hicn-apps)
-set(FACE_MGR facemgr)
+set(LIBFACEMGR facemgr)
+set(FACEMGR facemgr)
set(LIBMEMIF memif)
if (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
@@ -102,12 +103,12 @@ endif()
## Libraries targets
set(LIBHICN_SHARED ${LIBHICN}.shared)
set(LIBTRANSPORT_SHARED ${LIBTRANSPORT}.shared)
-set(LIBHICN_CTRL_SHARED ${LIBHICN_CTRL}.shared)
+set(LIBHICNCTRL_SHARED ${LIBHICNCTRL}.shared)
set(LIBMEMIF_SHARED ${LIBMEMIF}.shared)
set(LIBHICN_STATIC ${LIBHICN}.static)
set(LIBTRANSPORT_STATIC ${LIBTRANSPORT}.static)
-set(LIBHICN_CTRL_STATIC ${LIBHICN_CTRL}.static)
+set(LIBHICNCTRL_STATIC ${LIBHICNCTRL}.static)
set(LIBMEMIF_STATIC ${LIBMEMIF}.static)
## HEADER FILES
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index 933097892..e9f1e07de 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -31,7 +31,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
include_directories(${LIBTRANSPORT_INCLUDE_DIRS})
set(HICN_APPS hicn-apps)
else()
- if (ANDROID_API)
+ if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
find_package(OpenSSL REQUIRED)
find_package(ZLIB REQUIRED)
set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_STATIC})
diff --git a/cmake/Modules/BuildMacros.cmake b/cmake/Modules/BuildMacros.cmake
index 63d54502b..8b591d05b 100644
--- a/cmake/Modules/BuildMacros.cmake
+++ b/cmake/Modules/BuildMacros.cmake
@@ -25,12 +25,13 @@ macro(build_executable exec)
${ARGN}
)
- add_executable(${exec} ${ARG_SOURCES})
+ add_executable(${exec}-bin ${ARG_SOURCES})
set(BUILD_ROOT ${CMAKE_BINARY_DIR}/build-root)
- set_target_properties(${exec}
+ set_target_properties(${exec}-bin
PROPERTIES
+ OUTPUT_NAME ${exec}
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
INSTALL_RPATH_USE_LINK_PATH TRUE
ARCHIVE_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
@@ -39,19 +40,19 @@ macro(build_executable exec)
)
if(ARG_LINK_LIBRARIES)
- target_link_libraries(${exec} ${ARG_LINK_LIBRARIES})
+ target_link_libraries(${exec}-bin ${ARG_LINK_LIBRARIES})
endif()
if(ARG_DEPENDS)
- add_dependencies(${exec} ${ARG_DEPENDS})
+ add_dependencies(${exec}-bin ${ARG_DEPENDS})
endif()
if(ARG_DEFINITIONS)
- target_compile_definitions(${exec} PRIVATE ${ARG_DEFINITIONS})
+ target_compile_definitions(${exec}-bin PRIVATE ${ARG_DEFINITIONS})
endif()
if(ARG_INCLUDE_DIRS)
- target_include_directories(${exec} BEFORE PUBLIC
+ target_include_directories(${exec}-bin BEFORE PUBLIC
${ARG_INCLUDE_DIRS}
${PROJECT_BINARY_DIR}
)
@@ -59,7 +60,7 @@ macro(build_executable exec)
if(NOT ARG_NO_INSTALL)
install(
- TARGETS ${exec}
+ TARGETS ${exec}-bin
RUNTIME
DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT ${ARG_COMPONENT}
@@ -178,6 +179,9 @@ macro(build_library lib)
if ("${dir}" STREQUAL includes)
set(dir "")
endif()
+ if ("${dir}" STREQUAL ${ARG_INSTALL_ROOT_DIR})
+ set(dir "")
+ endif()
else()
set(dir "")
endif()
diff --git a/cmake/Modules/FindLibhicnctrl.cmake b/cmake/Modules/FindLibhicnctrl.cmake
index 1399b41bf..7c20420b4 100755
--- a/cmake/Modules/FindLibhicnctrl.cmake
+++ b/cmake/Modules/FindLibhicnctrl.cmake
@@ -31,14 +31,14 @@ find_path(LIBHICNCTRL_INCLUDE_DIR hicn/ctrl.h
DOC "Find the hICN control include"
)
-find_library(LIBHICNCTRL_LIBRARY NAMES hicn-ctrl
+find_library(LIBHICNCTRL_LIBRARY NAMES hicnctrl
HINTS ${HICN_SEARCH_PATH_LIST}
PATH_SUFFIXES lib
DOC "Find the hicn control library"
)
-set(LIBHICNCTRL_LIBRARIES ${HICNCTRL_LIBRARY})
-set(LIBHICNCTRL_INCLUDE_DIRS ${HICNCTRL_INCLUDE_DIR})
+set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_LIBRARY})
+set(LIBHICNCTRL_INCLUDE_DIRS ${LIBHICNCTRL_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(hicnctrl DEFAULT_MSG
diff --git a/cmake/Modules/Packager.cmake b/cmake/Modules/Packager.cmake
index 27a269b88..898e40bcb 100644
--- a/cmake/Modules/Packager.cmake
+++ b/cmake/Modules/Packager.cmake
@@ -116,6 +116,10 @@ macro(make_packages)
set(CPACK_${type}_${uc}_PACKAGE_DEPENDS "${DEB_DEPS}")
set(CPACK_${type}_${uc}_PACKAGE_NAME "${lc}")
set(CPACK_COMPONENT_${uc}_DESCRIPTION "${${lc}_DESCRIPTION}")
+
+ if (NOT ${${lc}_DEB_PACKAGE_CONTROL_EXTRA} STREQUAL "")
+ set(CPACK_DEBIAN_${uc}_PACKAGE_CONTROL_EXTRA "${${lc}_DEB_PACKAGE_CONTROL_EXTRA}")
+ endif()
endforeach()
elseif(OS_ID_LIKE MATCHES "rhel")
set(CPACK_GENERATOR "RPM")
@@ -152,6 +156,14 @@ macro(make_packages)
set(CPACK_RPM_${uc}_PACKAGE_NAME "${package_name}")
set(CPACK_${type}_${uc}_FILE_NAME "${package_name}-${rpm_ver}.${arch}.rpm")
+
+ if (NOT ${${lc}_RPM_POST_INSTALL_SCRIPT_FILE} STREQUAL "")
+ set(CPACK_RPM_${uc}_POST_INSTALL_SCRIPT_FILE "${${lc}_RPM_POST_INSTALL_SCRIPT_FILE}")
+ endif()
+
+ if (NOT ${${lc}_RPM_POST_UNINSTALL_SCRIPT_FILE} STREQUAL "")
+ set(CPACK_RPM_${uc}_POST_UNINSTALL_SCRIPT_FILE "${${lc}_RPM_POST_UNINSTALL_SCRIPT_FILE}")
+ endif()
endforeach()
endif()
diff --git a/ctrl/facemgr/CMakeLists.txt b/ctrl/facemgr/CMakeLists.txt
index f688dd2ca..377773c2d 100644
--- a/ctrl/facemgr/CMakeLists.txt
+++ b/ctrl/facemgr/CMakeLists.txt
@@ -20,6 +20,22 @@ endif()
project(facemgr)
+option(WITH_THREAD "Run library as thread" OFF)
+option(WITH_EXAMPLE_DUMMY "Compile dummy example interface" OFF)
+option(WITH_EXAMPLE_UPDOWN "Compile updown example interface" OFF)
+
+if(WITH_THREAD)
+ message("Building with thread support")
+endif()
+
+if(WITH_EXAMPLE_DUMMY)
+ message("Building with 'dummy' example interface")
+endif()
+
+if(WITH_EXAMPLE_UPDOWN)
+ message("Building with 'updown' example interface")
+endif()
+
if (NOT CMAKE_BUILD_TYPE)
message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
set(CMAKE_BUILD_TYPE "Release")
@@ -42,22 +58,29 @@ find_package_wrapper(Config REQUIRED)
find_package_wrapper(LibEvent REQUIRED)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ find_package_wrapper(Libhicn REQUIRED)
find_package_wrapper(Libhicnctrl REQUIRED)
- set(FACE_MGR facemgr)
+ set(FACEMGR facemgr)
+ set(LIBFACEMGR facemgr)
else()
- if (ANDROID_API)
- set(LIBHICNCTRL_LIBRARIES ${LIBHICN_CTRL_STATIC})
+ if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
+ set(HICN_LIBRARIES ${LIBHICN_STATIC})
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_STATIC})
list(APPEND DEPENDENCIES
- ${LIBHICN_CTRL_STATIC}
+ ${LIBHICN_STATIC}
+ ${LIBHICNCTRL_STATIC}
)
else ()
- set(LIBHICNCTRL_LIBRARIES ${LIBHICN_CTRL_SHARED})
+ set(HICN_LIBRARIES ${LIBHICN_SHARED})
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_SHARED})
list(APPEND DEPENDENCIES
- ${LIBHICN_CTRL_SHARED}
+ ${LIBHICN_SHARED}
+ ${LIBHICNCTRL_SHARED}
)
endif ()
endif()
+add_subdirectory(includes)
add_subdirectory(src)
include(Packaging)
diff --git a/ctrl/facemgr/README.md b/ctrl/facemgr/README.md
index e1a1beb4f..0cad9bc11 100644
--- a/ctrl/facemgr/README.md
+++ b/ctrl/facemgr/README.md
@@ -1 +1,11 @@
# hICN Face Manager
+
+The bonjour interfaces uses SO_BINDTODEVICE to be able to send bonjour queries
+to the right interfaces. As such facemgr has to be run as root, or with the
+CAP_NET_RAW capability.
+
+```
+sudo getcap build-root/bin/facemgr
+sudo setcap cap_net_raw+ep build-root/bin/facemgr
+sudo getcap build-root/bin/facemgr
+```
diff --git a/ctrl/facemgr/cmake/Modules/Packaging.cmake b/ctrl/facemgr/cmake/Modules/Packaging.cmake
index 97a1b6260..3a7e5a85c 100644
--- a/ctrl/facemgr/cmake/Modules/Packaging.cmake
+++ b/ctrl/facemgr/cmake/Modules/Packaging.cmake
@@ -15,17 +15,17 @@
# Packages section
######################
-set(${FACE_MGR}_DESCRIPTION
- "hICN face manager, lib${LIBHICN_CTRL}"
+set(${FACEMGR}_DESCRIPTION
+ "hICN face manager, lib${LIBHICNCTRL}"
CACHE STRING "Description for deb/rpm package."
)
-set(${FACE_MGR}_DEB_DEPENDENCIES
- "libconfig9, libevent-dev, lib${LIBHICN_CTRL} (>= stable_version)"
+set(${FACEMGR}_DEB_DEPENDENCIES
+ "libconfig9, libevent-dev, lib${LIBHICNCTRL} (>= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
-set(${FACE_MGR}_RPM_DEPENDENCIES
- "libconfig, libevent-devel, lib${LIBHICN_CTRL} >= stable_version"
+set(${FACEMGR}_RPM_DEPENDENCIES
+ "libconfig, libevent-devel, lib${LIBHICNCTRL} >= stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
diff --git a/ctrl/facemgr/doc/interface.md b/ctrl/facemgr/doc/interface.md
new file mode 100644
index 000000000..11c8da275
--- /dev/null
+++ b/ctrl/facemgr/doc/interface.md
@@ -0,0 +1,358 @@
+# Face manager : Interfaces
+
+## Overview
+
+The architecture of the face manager is built around the concept of interfaces,
+which allows for a modular and extensible deployment.
+
+Interfaces are used to implement in isolation various sources of information
+which help with the construction of faces (such as network interface and service
+discovery), and with handling the heterogeneity of host platforms.
+
+
+### Platform and supported interfaces
+
+Currently, Android, Linux and MacOS are supported through the following
+interfaces:
+
+- hicn-light [Linux, Android, MacOS, iOS]
+ An interface to the hicn-light forwarder, and more specifically to the Face
+ Table and FIB data structures. This component is responsible to effectively
+ create, update and delete faces in the forwarder, based on the information
+ provided by third party interfaces, plus adding default routes for each of
+ the newly created face. The communication with the forwarder is based on the
+ hicn control library (`libhicnctrl`).
+
+- netlink [Linux, Android]
+ The default interface on Linux systems (including Android) to communicate
+ with the kernel and receive information from various sources, including link
+ and address information (both IPv4 and IPv6) about network interfaces.
+
+- android\_utility [Android only]
+ Information available through Netlink is limited with respect to cellular
+ interfaces. This component allows querying the Android layer through SDK
+ functions to get the type of a given network interface (Wired, WiFi or
+ Cellular).
+
+- bonjour [Linux, Android]
+ This component performs remote service discovery based on the bonjour
+ protocol to discover a remote hICN forwarder that might be needed to
+ establish overlay faces.
+
+- network\_framework [MacOS, iOS]
+
+ This component uses the recommended Network framework on Apple devices,
+ which provided all required information to query faces in a unified API:
+ link and address information, interface types, and bonjour service
+ discovery.
+
+
+### Architectural overview
+
+#### Facelets
+
+TODO:
+- Key attributes (netdevice and protocol family)
+- Facelet API
+
+#### Events
+
+TODO
+
+#### Facelet cache & event scheduling
+
+TODO:
+ - Facelet cache
+ - Joins
+ - How synchronization work
+
+### Interface API
+
+TODO
+
+## Developing a new interface
+
+### Dummy template
+
+The face manager source code includes a template that can be used as a skeleton
+to develop new faces. It can be found in `src/interface/dummy/dummy.{h,c}`. Both
+include guard and specific interface functions are prefixed by a (short)
+identifier which acts as a namespace for interface specific code (in our case
+the string 'dummy\_').
+
+Registration and instanciation of the different interfaces is currently done at
+compile time in the file `src/api.c`, and the appropriate hooks to use the dummy
+interface are avaialble in the code between `#if 0/#endif` tags.
+
+#### Interface template header; configuration parameters
+
+All interfaces have a standard interface defined in `src/interface.{h,c}`, and
+as such the header file is only used to specify the configuration parameters of
+the interface, if any.
+
+In the template, these configuration options are empty:
+```
+/*
+ * Configuration data
+ */
+typedef struct {
+ /* ... */
+} dummy_cfg_t;
+```
+
+#### Overview of the interface template
+
+The file starts with useful includes:
+- the global include `<hicn/facemgr.h>` : this provides public facing elements
+ of the face manager, such the standard definition of faces (`face_t` from
+ `libhicnctrl`), helper classes (such as `ip_address_t` from `libhicn`), etc.
+- common.h
+- facelet.h : facelets are the basic unit of communication between the face
+manager and the different interfaces. They are used to construct the faces
+incrementally.
+- interface.h : the parent class of interfaces, such as the current dummy
+interface.
+
+Each interface can hold a pointer to an internal data structure, which is
+declared as follows:
+```
+/*
+ * Internal data
+ */
+typedef struct {
+ /* The configuration data will likely be allocated on the stack (or should
+ * be freed) by the caller, we recommend to make a copy of this data.
+ * This copy can further be altered with default values.
+ */
+ dummy_cfg_t cfg;
+
+ /* ... */
+
+ int fd; /* Sample internal data: file descriptor */
+} dummy_data_t;
+```
+
+We find here a copy of the configuration settings (which allows the called to
+instanciate the structure on the stack), as well as a file descriptor
+(assuming most interfaces will react on events on a file descriptor).
+
+The rest of the file consists in the implementation of the interface, in
+particular the different function required by the registration of a new
+interface to the system. They are grouped as part of the `interface_ops_t` data
+structure declared at the end of the file:
+
+```
+interface\_ops\_t dummy\_ops = {
+ .type = "dummy",
+ .initialize = dummy_initialize,
+ .finalize = dummy_finalize,
+ .callback = dummy_callback,
+ .on_event = dummy_on_event,
+};
+```
+
+The structure itself is declared and documented in `src/interface.h`
+```
+/**
+ * \brief Interface operations
+ */
+typedef struct {
+ /** The type given to the interfaces */
+ char * type;
+ /* Constructor */
+ int (*initialize)(struct interface\_s * interface, void * cfg);
+ /* Destructor */
+ int (*finalize)(struct interface_s * interface);
+ /* Callback upon file descriptor event (iif previously registered) */
+ int (*callback)(struct interface_s * interface);
+ /* Callback upon facelet events coming from the face manager */
+ int (*on_event)(struct interface_s * interface, const struct facelet_s * facelet);
+} interface\_ops\_t;
+```
+
+Such an interface has to be registered first, then one (or multiple) instance(s)
+can be created (see `src/interface.c` for the function prototypes, and
+`src/api.c` for their usage).
+
+- interface registration:
+
+```
+extern interface\_ops\_t dummy\_ops;
+
+/* [...] */
+
+rc = interface\_register(&dummy\_ops);
+if (rc < 0)
+ goto ERR_REGISTER;
+```
+
+- interface instanciation:
+
+```
+#include "interfaces/dummy/dummy.h"
+
+/* [...] */
+
+rc = facemgr_create_interface(facemgr, "dummy0", "dummy", &facemgr->dummy);
+if (rc < 0) {
+ ERROR("Error creating 'Dummy' interface\n");
+ goto ERR_DUMMY_CREATE;
+}
+```
+
+#### Implementation of the interface API
+
+We now quickly go other the different functions, but their usage will be better
+understood through the hands-on example treated in the following section.
+
+In the template, the constructor is the most involved as it need to:
+
+- initialize the internal data structure:
+
+```
+ dummy_data_t * data = malloc(sizeof(dummy_data_t));
+ if (!data)
+ goto ERR_MALLOC;
+ interface->data = data;
+```
+
+- process configuration parameters, eventually setting some default values:
+
+```
+ /* Use default values for unspecified configuration parameters */
+ if (cfg) {
+ data->cfg = *(dummy_cfg_t *)cfg;
+ } else {
+ memset(&data->cfg, 0, sizeof(data->cfg));
+ }
+```
+
+- open an eventually required file descriptor
+
+For the sake of simplicity, the current API only supports a single file
+descriptor per-interface, and it has to be created in the constructor, and
+set as the return value so as to be registered by the system, and added to the
+event loop for read events. A return value of 0 means the interface does not
+require any file descriptor. As usual, a negative return value indicates an
+error.
+
+```
+ data->fd = 0;
+
+ /* ... */
+
+ /*
+ * We should return a negative value in case of error, and a positive value
+ * otherwise:
+ * - a file descriptor (>0) will be added to the event loop; or
+ * - 0 if we don't use any file descriptor
+ */
+ return data->fd;
+```
+
+While support for multiple file descriptors might be added in the future, an
+alternative short-term implementation might consider the instanciation of
+multiple interface, as is done for Bonjour in the current codebase, in
+`src/api.c`.
+
+Data reception on the file descriptor will get the callback function called, in
+our case `dummy_callback`. Finally, the destructor `dummy_finalize` should close
+an eventual open file descriptor.
+
+In order to retrieve the internal data structure, that should in particular
+store such a file descriptor, all other function but the constructor can
+dereference it from the interface pointer they receive as parameter:
+
+```
+dummy\_data\_t * data = (dummy\_data\_t*)interface->data;
+```
+
+#### Raising and receiving events
+
+An interface will receive events in the form of a facelet through the `*_on_event`
+function. It can then use the facelet API we have describe above to read
+information about the face.
+
+As this information is declared const, the interface can either create a new
+facelet (identified by the same netdevice and protocol family), or eventually
+clone it.
+
+The facelet event can then be defined and raised to the face maanger for further
+processing through the following code:
+```
+ facelet_set_event(facelet, EVENT_TYPE_CREATE);
+ facelet_raise_event(facelet, interface);
+```
+
+Here the event is a facelet creation (`EVENT_TYPE_CREATE`). The full facelet API
+and the list of possible event types is available in `src/facelet.h`
+
+
+#### Integration in the build system
+
+The build system is based on CMake. Each interface should declare its source
+files, private and public header files, as well as link dependencies in the
+local `CMakeLists.txt` file.
+
+TODO: detail the structure of the file
+
+
+### Hands-on example
+
+#### Overview
+
+In order to better illustrate the development of a new interface, we will
+consider the integration of a sample server providing a signal instructing the
+face manager to alternatively use either the WiFi or the LTE interface. The code
+of this server is available in the folder `examples/updownsrv/`, and the
+corresponding client code in `examples/updowncli`.
+
+Communication between client and server is done through unix sockets over an
+abstract namespace (thereby not using the file system, which would cause issues
+on Android). The server listens for client connections, and periodically
+broadcast a binary information to all connected clients, in the form of one byte
+equal to either \0 (which we might interpret as enable LTE, disable WiFi), or \1
+(enable WiFi, disable LTE).
+
+Our objective is to develop a new face manager interface that would listen to
+such event in order to update the administrative status of the current faces.
+This would thus alternatively set the different interfaces admnistratively up
+and down (which takes precedence over the actual status of the interface when
+the forwarder establishes the set of available next hops for a given prefix).
+The actual realization of such queries will be ultimately performed by the
+hicn-light interface.
+
+#### Sample server and client
+
+In the folder containing the source code of hICN, the following commands allow
+to run the sample server:
+
+```
+cd ctrl/facemgr/examples/updownsrv
+make
+./updownsrv
+```
+
+The server should display "Waiting for clients..."
+
+Similar commands allow to run the sample client:
+```
+cd ctrl/facemgr/examples/updowncli
+make
+./updowncli
+```
+
+The client should display "Waiting for server data...", then every couple of
+seconds display either "WiFi" or "LTE".
+
+#### Facemanager interface
+
+An example illustrating how to connect to the dummy service from `updownsrv` is
+provided as the `updown` interface in the facemgr source code.
+
+This interface periodically swaps the status of the LTE interface up and down.
+It is instanciated as part of the facemgr codebase when the code is compiled
+with the ``-DWITH_EXAMPLE_UPDOWN` cmake option.
+
+
+
diff --git a/ctrl/facemgr/examples/facemgr.conf b/ctrl/facemgr/examples/facemgr.conf
index 54c212c2b..4658d13e3 100644
--- a/ctrl/facemgr/examples/facemgr.conf
+++ b/ctrl/facemgr/examples/facemgr.conf
@@ -1,37 +1,194 @@
+#
# hICN facemgr configuration file
+#
-faces:
-{
- # A list of interfaces to ignore
- ignore = ("lo");
-
- # A list of rules used to assign tags to interfaces
- # Each rule follows the syntax { name = "NAME"; tags = ("TAG", ...); }
- # with TAG = WIRED | WIFI | CELLULAR | TRUSTED
- rules = (
- {
- name = "utun1";
- tags = ("WIRED", "TRUSTED");
- }
- );
-
- overlay = {
- ipv4 = {
- local_port = 9695;
- remote_port = 9695;
- remote_addr = "10.60.16.14";
- };
- ipv6 = {
- local_port = 9695;
- remote_port = 9695;
- remote_addr = "2001:420:44f1:10:20c:29ff:fef3:8f8f";
- };
- };
-}
+################################################################################
+# Global settings
+################################################################################
+
+global = {
+
+# Default type for face creation
+#
+# Values: "auto" | "native-udp" | "native-tcp" | "overlay-udp" | "overlay-tcp"
+# Default "auto"
+#
+#face_type = "auto";
+face_type = "overlay-udp"
+
+# Disable service discovery for overlay creation
+#
+# This is only meaningful for overlay_* face types. If service discovery is
+# disabled, only manually entered overlay information will be used, if any.
+# Otherwise, no face will be created.
+#
+# Values : true | false
+# Default: false
+#
+#disable_discovery = true;
+
+# TODO Disable IPv4 face creation
+#
+# Values : true | false
+# Default: false
+#
+#disable_ipv4 = true;
+
+# TODO Disable IPv6 face creation
+#
+# Values : true | false
+# Default: false
+#
+#disable_ipv6 = true;
+
+# TODO overlay
+#
+# By default, no address is specified, and local and remote ports are set to
+# the standard value for hICN (9695).
+#
+
+};
+
+################################################################################
+# Per-interface rules
+################################################################################
+#
+# Rules allow to override the default behaviour of the face manager.
+#
+# The list of rules must be specified as follows (note that the last one has no
+# coma at the end) :
+#
+# rules = (
+# { ... },
+# { ... },
+# { ... }
+# );
+#
+# A rule is composed of match and override attributes, and has the following
+# syntax:
+#
+# {
+# match = {
+# interface_name = STRING;
+# interface_type = STRING;
+# };
+# override = {
+# face_type = STRING;
+# disable_discovery = BOOL;
+# ignore = BOOL;
+# tags = (STRING, STRING, STRING);
+# overlay = {
+# ipv4 = {
+# local_port = PORT;
+# remote_addr = IP_ADDRESS;
+# remote_port = PORT;
+# };
+# ipv6 = {
+# local_port = PORT;
+# remote_addr = IP_ADDRESS;
+# remote_port = PORT;
+# };
+# };
+# };
+# }
+#
+# Match attributes:
+#
+# Match attributes serve to identify rules and as such defining two rules with
+# similar matches is not allowed. However, overlapping match definitions are
+# possible, in which case only the first matching rule is considered.
+#
+# A match is composed of the name of an interface and/or its type (either
+# attribute is optional but at least one has to be specified).
+#
+# * interface_name - a string representing an interface name
+#
+# * interface_type - the type of interface to match
+#
+# Values: "wired" | "wifi" | "cellular"
+#
+# Override attributes:
+#
+# Those attributes are applied when all specified match attributes correspond,
+# and override general settings or default values.
+#
+# * face_type - type used for face creation
+#
+# Values: "auto" | "native_udp" | "native_tcp" | "overlay_udp" | "overlay_tcp"
+#
+# * disable_discovery - disable service discovery for overlay creation
+#
+# Values : true | false
+#
+# * ignore - a boolean indicating whether that interface should be ignored
+#
+# * TODO tags - a (possibly empty) list of tags to be associated to the created face.
+#
+# Values: "wired" | "wifi" | "cellular" | "trusted"
+#
+# * overlay
+#
+# An overlay specification is used to complement any information retrieved
+# through service discovery (or replace it if service discovery is
+# disabled).
+#
+# It is possible to specify values for IPv4, IPv6 or both.
+#
+# Note that it is not currently possible to set different settings for IPv4 and
+# IPv6 but overlay specifications.
+#
+#
+# Here are a few example of rule definitions:
+#
+# rules = (
+# # Ignore localhost interface
+# {
+# match = {
+# interface_name = "lo";
+# };
+# override = {
+# ignore = true;
+# };
+# },
+# # Set tags for unknown tunnnel interface
+# {
+# match = {
+# interface_name = "utun1";
+# };
+# override = {
+# tags = ("WIRED", "TRUSTED");
+# };
+# },
+# # Force cellular connections to use manually specified overlay faces
+# {
+# match = {
+# interface_type = "cellular",
+# };
+# override = {
+# overlay = {
+# ipv4 = {
+# local_port = 9695;
+# remote_addr = "10.60.16.14";
+# remote_port = 9695;
+# };
+# ipv6 = {
+# local_port = 9695;
+# remote_addr = "2001:420:44f1:10:20c:29ff:fef3:8f8f";
+# remote_port = 9695;
+# };
+# };
+# };
+# }
+# );
+#
+#rules = (
+#);
+
+################################################################################
+# Logging
+################################################################################
log:
{
log_level = "DEBUG";
}
-
-
diff --git a/ctrl/facemgr/examples/run-bonjour.sh b/ctrl/facemgr/examples/run-bonjour.sh
new file mode 100755
index 000000000..c6c317b42
--- /dev/null
+++ b/ctrl/facemgr/examples/run-bonjour.sh
@@ -0,0 +1,162 @@
+#!/bin/bash
+
+set -e
+
+PORT=9695
+
+#-------------------------------------------------------------------------------
+
+FN_AVAHI_CFG_SRC=$SCRIPT_PATH/etc_avahi_services_hicn.service
+FN_AVAHI_CFG=/etc/avahi/services/hicn.service
+
+# https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression
+! read -r -d '' TPL_AVAHI_CFG <<-EOF
+<?xml version="1.0" standalone='no'?>
+<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
+<service-group>
+ <name>hicn node</name>
+ <service>
+ <type>_hicn._udp</type>
+ <port>$PORT</port>
+ </service>
+</service-group>
+EOF
+
+#-------------------------------------------------------------------------------
+
+# Reliably determine script's full path
+SCRIPT_PATH="$( cd "$(dirname "$0")" ; pwd -P )"
+
+# https://unix.stackexchange.com/questions/325594/script-a-test-for-installed-debian-package-error-handling
+function pkg_is_installed()
+{
+ PKG="$1"
+ LISTF=$(mktemp)
+ dpkg-query -W -f '${Package} ${State}\n' >$LISTF
+ grep "^${PKG} " $LISTF >/dev/null
+ GREP_RC=$?
+ rm $LISTF
+
+ # for even moar strict error handling
+ test $GREP_RC == 0 -o $GREP_RC == 1
+
+ return $GREP_RC
+}
+
+# https://stackoverflow.com/questions/3466166/how-to-check-if-running-in-cygwin-mac-or-linux
+function detect_os()
+{
+ unameOut="$(uname -s)"
+ case "${unameOut}" in
+ Linux*) machine=linux;;
+ Darwin*) machine=mac;;
+ CYGWIN*) machine=cygwin;;
+ MINGW*) machine=mingw;;
+ *) machine=unknown;;
+ esac
+ echo ${machine}
+}
+
+function ensure_pkg_is_installed()
+{
+ PKG="$1"
+ pkg_is_installed $PKG && return
+ sudo apt install $PKG
+}
+
+function ensure_file_installed()
+{
+ SRC=$1
+ DST=$2
+
+ # Test whether destination exists and is up to date
+ [ -s $DST ] && cmp -s $SRC $DST && return
+
+ sudo cp $SRC $DST
+}
+
+function ensure_file_template()
+{
+ DST=$1
+ TPL=$2
+
+ echo "$TPL" | sudo tee $DST >/dev/null
+}
+
+function is_function()
+{
+ [ "$(type -t $1)" == "function" ]
+}
+
+function os_function()
+{
+ FUN=$1
+ shift
+ ARGS=$@
+
+ OS=$(detect_os)
+ if ! is_function ${FUN}_${OS}; then
+ echo "Platform $OS not supported for $FUN [${FUN}_${OS}]"
+ exit -1
+ fi
+ ${FUN}_${OS} $ARGS
+}
+
+#-------------------------------------------------------------------------------
+
+# NOTE: debian only
+function run_bonjour_server_linux()
+{
+ ensure_pkg_is_installed avahi-daemon
+ #ensure_file_installed $FN_AVAHI_CFG_SRC $FN_AVAHI_CFG
+ ensure_file_template $FN_AVAHI_CFG "$TPL_AVAHI_CFG"
+ sudo service avahi-daemon restart
+ echo >&2, "Bonjour is now served through avahi"
+}
+
+function run_bonjour_server_mac()
+{
+ dns-sd -R hicn _hicn._tcp local $PORT
+ # Proxy mode -P
+}
+
+function run_bonjour_client_linux()
+{
+ avahi-browse -ptr _hicn._udp
+}
+
+function run_bonjour_client_mac()
+{
+ dns-sd -B _hicn._udp local
+
+}
+
+# XXX function run_bonjour_proxy_linux() { }
+
+function run_bonjour_proxy_mac()
+{
+ if [[ $# != 2 ]]; then
+ echo "Usage: $0 proxy IP_ADDRESS"
+ exit -1
+ fi
+ IP=$1
+ dns-sd -P hicn _hicn._udp local $PORT hicn.local $IP path=/
+}
+
+#-------------------------------------------------------------------------------
+
+case $1 in
+ client)
+ os_function run_bonjour_client
+ ;;
+ server)
+ os_function run_bonjour_server
+ ;;
+ proxy)
+ os_function run_bonjour_proxy $@
+ ;;
+ *)
+ echo "$0 [client|server]"
+ exit -1
+ ;;
+esac
diff --git a/ctrl/facemgr/examples/updowncli/Makefile b/ctrl/facemgr/examples/updowncli/Makefile
new file mode 100644
index 000000000..5e6111c2a
--- /dev/null
+++ b/ctrl/facemgr/examples/updowncli/Makefile
@@ -0,0 +1,25 @@
+EXEC = $(shell basename $$(pwd))
+CC = gcc
+
+CFLAGS = -std=gnu11 -O3 -Wall -Wextra -Wpedantic -Wstrict-aliasing
+#CFLAGS += $(shell pkg-config --cflags glib-2.0 gio-2.0)
+#LDFLAGS = $(shell pkg-config --libs glib-2.0 gio-2.0)
+
+SRC = $(wildcard *.c)
+OBJ = $(SRC:.c=.o)
+
+all: $(EXEC)
+
+${EXEC}: $(OBJ)
+ $(CC) -o $@ $^ $(LDFLAGS)
+
+%.o: %.c
+ $(CC) -o $@ -c $< $(CFLAGS)
+
+.PHONY: clean mrproper
+
+clean:
+ @rm -rf *.o
+
+mrproper: clean
+ @rm -rf $(EXEC)
diff --git a/ctrl/facemgr/examples/updowncli/updowncli.c b/ctrl/facemgr/examples/updowncli/updowncli.c
new file mode 100644
index 000000000..4f5a14165
--- /dev/null
+++ b/ctrl/facemgr/examples/updowncli/updowncli.c
@@ -0,0 +1,57 @@
+#include <assert.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/**
+ * \brief Default unix socket path (the leading \0 means using the abstract
+ * namespace instead of the filesystem).
+ */
+#define UNIX_PATH "\0updownsrv"
+
+int main() {
+ struct sockaddr_un addr;
+ char buf[100];
+ int fd,rc;
+
+ char * socket_path = UNIX_PATH;
+
+ if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ perror("socket error");
+ exit(-1);
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ if (*socket_path == '\0') {
+ *addr.sun_path = '\0';
+ strncpy(addr.sun_path+1, socket_path+1, sizeof(addr.sun_path)-2);
+ } else {
+ strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
+ }
+
+ if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+ perror("connect error");
+ exit(-1);
+ }
+
+ printf("Waiting for server data...\n");
+ while( (rc=read(fd, buf, sizeof(buf))) > 0) {
+ assert(rc == 1);
+ switch(buf[0]) {
+ case '\0':
+ printf("WiFi\n");
+ break;
+ case '\1':
+ printf("LTE\n");
+ break;
+ default:
+ printf("Unknown\n");
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/ctrl/facemgr/examples/updownsrv/Makefile b/ctrl/facemgr/examples/updownsrv/Makefile
new file mode 100644
index 000000000..5e6111c2a
--- /dev/null
+++ b/ctrl/facemgr/examples/updownsrv/Makefile
@@ -0,0 +1,25 @@
+EXEC = $(shell basename $$(pwd))
+CC = gcc
+
+CFLAGS = -std=gnu11 -O3 -Wall -Wextra -Wpedantic -Wstrict-aliasing
+#CFLAGS += $(shell pkg-config --cflags glib-2.0 gio-2.0)
+#LDFLAGS = $(shell pkg-config --libs glib-2.0 gio-2.0)
+
+SRC = $(wildcard *.c)
+OBJ = $(SRC:.c=.o)
+
+all: $(EXEC)
+
+${EXEC}: $(OBJ)
+ $(CC) -o $@ $^ $(LDFLAGS)
+
+%.o: %.c
+ $(CC) -o $@ -c $< $(CFLAGS)
+
+.PHONY: clean mrproper
+
+clean:
+ @rm -rf *.o
+
+mrproper: clean
+ @rm -rf $(EXEC)
diff --git a/ctrl/facemgr/examples/updownsrv/updownsrv.c b/ctrl/facemgr/examples/updownsrv/updownsrv.c
new file mode 100644
index 000000000..e10247860
--- /dev/null
+++ b/ctrl/facemgr/examples/updownsrv/updownsrv.c
@@ -0,0 +1,231 @@
+/*
+ * Dummy server sending alternating bytes to all clients.
+ *
+ * This is used by the face manager to illustrate the creation of interfaces
+ * using unix domains that sets a face up and down.
+ */
+
+#include <arpa/inet.h> // inet_ntop
+#include <errno.h> // EINTR,. ..
+#include <netinet/in.h> // INET_ADDRSTRLEN, INET6_ADDRSTRLEN
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/timerfd.h>
+#include <sys/un.h> // sockaddr_un
+#include <unistd.h> // fcntl
+#include <fcntl.h> // fcntl
+
+
+/**
+ * \brief Default unix socket path (the leading \0 means using the abstract
+ * namespace instead of the filesystem).
+ */
+#define UNIX_PATH "\0updownsrv"
+
+/**
+ * \brief Default interval (in seconds) between timer events */
+#define DEFAULT_INTERVAL 100000
+
+/**
+ * \brief Maximum allowed number of connected clients
+ */
+#define MAX_CLIENTS 5
+
+/**
+ * \brief Maximum backlog of listening unix socket
+ */
+#define LISTEN_BACKLOG MAX_CLIENTS
+
+
+/**
+ * \brief Creates a unix server socket
+ * \param [in] path - string representing the path on which to listen for
+ * connections
+ * \return int - fd associated to the socket
+ */
+int
+create_unix_server(char * path)
+{
+ struct sockaddr_un addr;
+ int fd;
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1) {
+ perror("socket error");
+ return -1;
+ }
+
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ perror("fcntl");
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ if (*path == '\0') {
+ *addr.sun_path = '\0';
+ strncpy(addr.sun_path+1, path+1, sizeof(addr.sun_path)-2);
+ } else {
+ strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1);
+ unlink(path);
+ }
+
+ if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+ perror("bind error");
+ return -1;
+ }
+
+ if (listen(fd, LISTEN_BACKLOG) == -1) {
+ perror("listen error");
+ return -1;
+ }
+
+ return fd;
+}
+
+
+/**
+ * \brief Main function
+ */
+int main() {
+ int fd, tfd;
+ int rc;
+
+ /* Alternating state of the server : 0 / 1 */
+ unsigned state = 0;
+
+ /*
+ * This server has to send a signal to all connected clients at periodic
+ * intervals. Since we don't expect a large number of connected clients for
+ * such a simple program, we simply use a statically allocated array.
+ */
+ int clients[MAX_CLIENTS];
+ size_t num_clients = 0;
+
+ fd_set active_fd_set, read_fd_set;
+ FD_ZERO (&active_fd_set);
+
+ /* Create listening unix socket */
+ fd = create_unix_server(UNIX_PATH);
+ if (fd < 0)
+ exit(EXIT_FAILURE);
+ FD_SET (fd, &active_fd_set);
+
+ /* Create timer */
+ tfd = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (tfd == -1) {
+ perror("timer error");
+ exit(EXIT_FAILURE);
+ }
+
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ perror("fcntl");
+ exit(EXIT_FAILURE);
+ }
+
+ FD_SET (tfd, &active_fd_set);
+
+ struct itimerspec ts = {
+ .it_interval = {
+ .tv_sec = DEFAULT_INTERVAL,
+ .tv_nsec = 0,
+ },
+ .it_value = {
+ .tv_sec = DEFAULT_INTERVAL,
+ .tv_nsec = 0,
+ }
+ };
+ rc = timerfd_settime(tfd, 0, &ts, NULL);
+ if (rc == -1) {
+ perror("timerfd_settime");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Waiting for clients...\n");
+
+ for(;;) {
+ /* Block until input arrives on one or more active sockets. */
+ read_fd_set = active_fd_set;
+ rc = select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL);
+ if (rc < 0) {
+ if (rc == EINTR)
+ break;
+ perror("select");
+ exit (EXIT_FAILURE);
+ }
+
+ /* Service all the sockets with input pending. */
+ for (int i = 0; i < FD_SETSIZE; ++i) {
+ if (!FD_ISSET (i, &read_fd_set))
+ continue;
+ if (i == fd) {
+ /* Connection request on original socket. */
+ int client_fd = accept(fd, NULL, NULL);
+ if (client_fd < 0) {
+ perror("accept");
+ continue;
+ }
+
+ fprintf(stderr, "Server: connect from new client\n");
+ clients[num_clients++] = client_fd;
+ FD_SET(client_fd, &active_fd_set);
+ } else if (i == tfd) {
+ /* Timer event */
+ uint64_t res;
+
+ read(tfd, &res, sizeof(res));
+// while (read(fd, &missed, sizeof(missed)) > 0)
+// ;
+ for (unsigned j = 0; j < num_clients; j++) {
+ write(clients[j], state ? "\1" : "\0", 1);
+ }
+ printf("STATE=%d\n", state);
+ state = 1 - state;
+ } else {
+ char buf[1024];
+ rc = read(i, buf, sizeof(buf));
+ /* Client event : we close the connection on any event... */
+ for (unsigned j = 0; j < num_clients; j++) {
+ if (i == clients[j]) {
+ clients[j] = clients[num_clients--];
+ break;
+ }
+ }
+ close(i);
+ FD_CLR(i, &active_fd_set);
+ }
+ }
+
+ }
+
+ int ret = EXIT_SUCCESS;
+
+ /* Close all active client connections */
+ for (unsigned i = 0; i < num_clients; i++) {
+ rc = close(clients[i]);
+ if (rc == -1) {
+ perror("close");
+ ret = EXIT_FAILURE;
+ }
+ }
+
+ /* Close server */
+ rc = close(fd);
+ if (rc == -1) {
+ perror("close");
+ ret = EXIT_FAILURE;
+ }
+
+ /* Terminate timer */
+ ts.it_value.tv_sec = 0;
+ rc = timerfd_settime(tfd, 0, &ts, NULL);
+ if (rc == -1) {
+ perror("timerfd_settime");
+ exit(EXIT_FAILURE);
+ }
+
+ exit(ret);
+}
diff --git a/ctrl/facemgr/includes/CMakeLists.txt b/ctrl/facemgr/includes/CMakeLists.txt
new file mode 100644
index 000000000..566424c67
--- /dev/null
+++ b/ctrl/facemgr/includes/CMakeLists.txt
@@ -0,0 +1,44 @@
+# 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.
+
+# XXX
+
+set(LIBFACEMGR_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR} ""
+ CACHE INTERNAL
+ "" FORCE
+)
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
+
+ set(TO_INSTALL_HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/facemgr.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/api.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/cfg.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/log.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/android_utility/android_utility.h
+ PARENT_SCOPE
+ )
+
+else ()
+
+ set(TO_INSTALL_HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/facemgr.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/api.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/cfg.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/log.h
+ PARENT_SCOPE
+ )
+
+endif ()
+
+
diff --git a/ctrl/facemgr/src/netdevice.c b/ctrl/facemgr/includes/facemgr.h
index 817b0e47b..b322e7b1f 100644
--- a/ctrl/facemgr/src/netdevice.c
+++ b/ctrl/facemgr/includes/facemgr.h
@@ -14,15 +14,15 @@
*/
/**
- * \file netdevice.c
- * \brief Implementation of Netdevice abstraction
+ * \file facemgr.h
+ * \brief Main interface for hICN face manager library
*/
+#ifndef HICN_FACEMGR_H
+#define HICN_FACEMGR_H
-#include "common.h"
-#include "netdevice.h"
+#include <hicn/policy.h>
+#include <hicn/facemgr/api.h>
+#include <hicn/facemgr/cfg.h>
+
+#endif /* HICN_FACEMGR_H */
-const char * netdevice_type_str[] = {
-#define _(x) [NETDEVICE_TYPE_ ## x] = STRINGIZE(x),
-foreach_netdevice_type
-#undef _
-}
diff --git a/ctrl/facemgr/includes/hicn/android_utility/android_utility.h b/ctrl/facemgr/includes/hicn/android_utility/android_utility.h
new file mode 100644
index 000000000..53adfedf6
--- /dev/null
+++ b/ctrl/facemgr/includes/hicn/android_utility/android_utility.h
@@ -0,0 +1,48 @@
+/*
+ * 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 android_utility/android_utility.h
+ * \brief Android utility.
+ *
+ * This class relies on a small utility wrapper shipped with the Android
+ * application to access to Java SDK APIs for information not available to
+ * native code.
+ *
+ * For instance, we currently don't have on Linux any mean to get the type
+ * associated to an interface, especially for cellular interfaces. WiFi and
+ * Bluetooth information is for instance available through specific netlink
+ * subsystems, or by means of a support library, but cellular detection mostly
+ * relies on heuristics based on interface names (eg. in network manager).
+ *
+ * Android ship a Radio Interface Layer (RIL) daemon that exposes a control
+ * socket to the Java API to control the radio layer, but there is no working
+ * code exploiting it and no proper documentation.
+ */
+
+#ifndef FACEMGR_INTERFACE_ANDROID_UTILITY_H
+#define FACEMGR_INTERFACE_ANDROID_UTILITY_H
+
+#ifdef __ANDROID__
+
+#include <jni.h>
+
+typedef struct {
+ JavaVM *jvm;
+} android_utility_cfg_t;
+
+#endif /* __ANDROID__ */
+
+#endif /* FACEMGR_INTERFACE_ANDROID_UTILITY_H */
diff --git a/ctrl/facemgr/src/interface_map.h b/ctrl/facemgr/includes/hicn/facemgr.h
index 5930b3001..4165a8fc4 100644
--- a/ctrl/facemgr/src/interface_map.h
+++ b/ctrl/facemgr/includes/hicn/facemgr.h
@@ -13,12 +13,15 @@
* limitations under the License.
*/
-#ifndef INTERFACE_MAP_H
-#define INTERFACE_MAP_H
+/**
+ * \file facemgr.h
+ * \brief Main interface for hICN face manager library
+ */
+#ifndef HICN_FACEMGR_H
+#define HICN_FACEMGR_H
-#include "interface.h"
-#include "util/map.h"
+#include <hicn/policy.h>
+#include <hicn/facemgr/api.h>
-TYPEDEF_MAP_H(interface_map, const char *, interface_t *);
+#endif /* HICN_FACEMGR_H */
-#endif /* INTERFACE_MAP_H */
diff --git a/ctrl/facemgr/includes/hicn/facemgr/api.h b/ctrl/facemgr/includes/hicn/facemgr/api.h
new file mode 100644
index 000000000..c5c29c219
--- /dev/null
+++ b/ctrl/facemgr/includes/hicn/facemgr/api.h
@@ -0,0 +1,81 @@
+/*
+ * 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 facemgr.h
+ * \brief Face manager library interface
+ */
+#ifndef FACEMGR_H
+#define FACEMGR_H
+
+#include <hicn/facemgr/cfg.h>
+#include <hicn/util/ip_address.h>
+#ifdef __ANDROID__
+#include <hicn/android_utility/android_utility.h>
+#endif
+
+/*
+ * \brief Manual overlay settings (alternative to service discovery)
+ */
+
+typedef struct {
+ uint16_t local_port;
+ ip_address_t remote_addr;
+ uint16_t remote_port;
+} facemgr_overlay_setting_t;
+
+#define FACEMGR_OVERLAY_SETTING_EMPTY (facemgr_overlay_setting_t) { \
+ .local_port = 0, \
+ .remote_addr = IP_ADDRESS_EMPTY, \
+ .remote_port = 0, \
+}
+
+typedef struct {
+ facemgr_overlay_setting_t v4;
+ facemgr_overlay_setting_t v6;
+} facemgr_overlay_t;
+
+#define FACEMGR_OVERLAY_EMPTY (facemgr_overlay_t) { \
+ .v4 = FACEMGR_OVERLAY_SETTING_EMPTY, \
+ .v6 = FACEMGR_OVERLAY_SETTING_EMPTY, \
+}
+
+/*
+ * \brief Face manager context
+ */
+typedef struct facemgr_s facemgr_t;
+
+int facemgr_initialize(facemgr_t *);
+int facemgr_finalize(facemgr_t *);
+facemgr_t * facemgr_create();
+facemgr_t * facemgr_create_with_config(facemgr_cfg_t * cfg);
+void facemgr_stop(facemgr_t *);
+void facemgr_free(facemgr_t *);
+
+int facemgr_set_config(facemgr_t * facemgr, facemgr_cfg_t * cfg);
+int facemgr_reset_config(facemgr_t * facemgr);
+void facemgr_set_event_loop_handler(facemgr_t * facemgr, void * loop,
+ void * loop_register_fd,
+ void * loop_unregister_event);
+int facemgr_bootstrap(facemgr_t * facemgr);
+#ifdef __ANDROID__
+void facemgr_set_jvm(facemgr_t * facemgr, JavaVM *jvm);
+#endif /* __ANDROID__ */
+
+typedef int (*facemgr_list_faces_cb_t)(face_t * face, void * user_data);
+
+void facemgr_list_faces(facemgr_t * facemgr, facemgr_list_faces_cb_t cb, void * user_data);
+
+#endif /* FACEMGR_H */
diff --git a/ctrl/facemgr/includes/hicn/facemgr/cfg.h b/ctrl/facemgr/includes/hicn/facemgr/cfg.h
new file mode 100644
index 000000000..c121c687f
--- /dev/null
+++ b/ctrl/facemgr/includes/hicn/facemgr/cfg.h
@@ -0,0 +1,193 @@
+/*
+ * 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 cfg.h
+ * \brief Face manager configuration
+ */
+#ifndef FACEMGR_CFG_H
+#define FACEMGR_CFG_H
+
+#include <hicn/ctrl/face.h>
+#include <hicn/util/log.h>
+
+/* Face type */
+
+#define foreach_face_type_layer \
+ _(UNDEFINED) \
+ _(3) \
+ _(4) \
+ _(N)
+
+typedef enum {
+#define _(x) FACE_TYPE_LAYER_ ## x,
+ foreach_face_type_layer
+#undef _
+} face_type_layer_t;
+
+#define foreach_face_type_encap \
+ _(UNDEFINED) \
+ _(TCP) \
+ _(UDP) \
+ _(N)
+
+typedef enum {
+#define _(x) FACE_TYPE_ENCAP_ ## x,
+ foreach_face_type_encap
+#undef _
+} face_type_encap_t;
+
+typedef struct {
+ face_type_layer_t layer;
+ face_type_encap_t encap;
+} facemgr_face_type_t;
+
+#define FACEMGR_FACE_TYPE_UNDEFINED (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_UNDEFINED, \
+ .encap = FACE_TYPE_ENCAP_UNDEFINED, \
+}
+
+#define FACEMGR_FACE_TYPE_NATIVE_UDP (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_3, \
+ .encap = FACE_TYPE_ENCAP_UDP, \
+}
+
+#define FACEMGR_FACE_TYPE_NATIVE_TCP (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_3, \
+ .encap = FACE_TYPE_ENCAP_TCP, \
+}
+
+#define FACEMGR_FACE_TYPE_OVERLAY_UDP (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_4, \
+ .encap = FACE_TYPE_ENCAP_UDP, \
+}
+
+#define FACEMGR_FACE_TYPE_OVERLAY_TCP (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_4, \
+ .encap = FACE_TYPE_ENCAP_TCP, \
+}
+
+/* Face manager configuration */
+
+#ifdef __ANDROID__
+#define FACEMGR_FACE_TYPE_DEFAULT FACEMGR_FACE_TYPE_OVERLAY_UDP
+#else
+#define FACEMGR_FACE_TYPE_DEFAULT FACEMGR_FACE_TYPE_NATIVE_TCP
+#endif /* __ANDROID__ */
+
+#define DEFAULT_FACE_TYPE FACE_TYPE_AUTO
+#define FACEMGR_CFG_DEFAULT_DISCOVERY true
+//#define DEFAULT_IGNORE "lo"
+#define FACEMGR_CFG_DEFAULT_IPV4 true
+#define FACEMGR_CFG_DEFAULT_IPV6 true
+
+
+
+typedef struct facemgr_cfg_s facemgr_cfg_t;
+
+facemgr_cfg_t * facemgr_cfg_create();
+void facemgr_cfg_free(facemgr_cfg_t * cfg);
+int facemgr_cfg_initialize(facemgr_cfg_t * cfg);
+int facemgr_cfg_finalize(facemgr_cfg_t * cfg);
+void facemgr_cfg_dump(facemgr_cfg_t * cfg);
+
+/* Rules */
+
+typedef struct facemgr_cfg_rule_s facemgr_cfg_rule_t;
+
+facemgr_cfg_rule_t * facemgr_cfg_rule_create();
+void facemgr_cfg_rule_free(facemgr_cfg_rule_t * rule);
+int facemgr_cfg_rule_initialize(facemgr_cfg_rule_t * rule);
+int facemgr_cfg_rule_finalize(facemgr_cfg_rule_t * rule);
+
+int facemgr_cfg_rule_set_match(facemgr_cfg_rule_t * rule,
+ const char * interface_name, netdevice_type_t interface_type);
+
+int facemgr_cfg_rule_set_face_type(facemgr_cfg_rule_t * cfg_rule, facemgr_face_type_t * face_type);
+int facemgr_cfg_rule_unset_face_type(facemgr_cfg_rule_t * cfg_rule);
+
+int facemgr_cfg_rule_set_discovery(facemgr_cfg_rule_t * cfg_rule, bool status);
+int facemgr_cfg_rule_unset_discovery(facemgr_cfg_rule_t * cfg_rule);
+
+int facemgr_cfg_rule_set_ignore(facemgr_cfg_rule_t * cfg_rule, bool status);
+int facemgr_cfg_rule_unset_ignore(facemgr_cfg_rule_t * cfg_rule);
+
+int facemgr_cfg_rule_set_ipv4(facemgr_cfg_rule_t * cfg_rule, bool status);
+int facemgr_cfg_rule_unset_ipv4(facemgr_cfg_rule_t * cfg_rule);
+
+int facemgr_cfg_rule_set_ipv6(facemgr_cfg_rule_t * cfg_rule, bool status);
+int facemgr_cfg_rule_unset_ipv6(facemgr_cfg_rule_t * cfg_rule);
+
+int facemgr_cfg_rule_set_overlay(facemgr_cfg_rule_t * rule, int family,
+ ip_address_t * local_addr, uint16_t local_port,
+ ip_address_t * remote_addr, uint16_t remote_port);
+int facemgr_rule_unset_overlay(facemgr_cfg_rule_t * rule, int family);
+
+/* General */
+int facemgr_cfg_set_face_type(facemgr_cfg_t * cfg, facemgr_face_type_t * face_type);
+int facemgr_cfg_unset_face_type(facemgr_cfg_t * cfg);
+int facemgr_cfg_set_discovery(facemgr_cfg_t * cfg, bool status);
+int facemgr_cfg_unset_discovery(facemgr_cfg_t * cfg);
+
+int facemgr_cfg_set_overlay(facemgr_cfg_t * cfg, int family,
+ ip_address_t * local_addr, uint16_t local_port,
+ ip_address_t * remote_addr, uint16_t remote_port);
+int facemgr_cfg_unset_overlay(facemgr_cfg_t * cfg, int family);
+
+
+int facemgr_cfg_add_rule(facemgr_cfg_t * cfg, facemgr_cfg_rule_t * rule);
+int facemgr_cfg_del_rule(facemgr_cfg_t * cfg, facemgr_cfg_rule_t * rule);
+int facemgr_cfg_get_rule(const facemgr_cfg_t * cfg, const char * interface_name,
+ netdevice_type_t interface_type, facemgr_cfg_rule_t ** rule);
+
+/* Log */
+
+/*
+ * Query API
+ *
+ * Takes the overrides into account
+ *
+ * TODO : interface_types are currently not taken into account by this API
+ */
+
+int facemgr_cfg_get_face_type(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ facemgr_face_type_t * face_type);
+int facemgr_cfg_get_discovery(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ bool * discovery);
+int facemgr_cfg_get_ignore(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ bool * ignore);
+int facemgr_cfg_get_ipv4(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ bool * ipv4);
+int facemgr_cfg_get_ipv6(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ bool * ipv6);
+int facemgr_cfg_get_overlay_local_addr(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ int family, ip_address_t * addr);
+int facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ int family, u16 * port);
+int facemgr_cfg_get_overlay_remote_addr(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ int family, ip_address_t * addr);
+int facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ int family, u16 * port);
+
+#endif /* FACEMGR_CFG_H */
diff --git a/ctrl/facemgr/src/util/log.h b/ctrl/facemgr/includes/hicn/util/log.h
index f1cafba47..f1cafba47 100644
--- a/ctrl/facemgr/src/util/log.h
+++ b/ctrl/facemgr/includes/hicn/util/log.h
diff --git a/ctrl/facemgr/src/CMakeLists.txt b/ctrl/facemgr/src/CMakeLists.txt
index e7dbda5c1..f99e57e07 100644
--- a/ctrl/facemgr/src/CMakeLists.txt
+++ b/ctrl/facemgr/src/CMakeLists.txt
@@ -20,40 +20,22 @@ set(COMPILER_DEFINITIONS
)
set(HEADER_FILES
-#cache.h
common.h
error.h
- event.h
- face.h
- face_cache.h
- face_rules.h
+ facelet.h
interface.h
- interface_map.h
- interface_ops_map.h
util/hash.h
- util/ip_address.h
- util/log.h
util/map.h
- util/policy.h
util/set.h
- util/token.h
- util/types.h
-
)
set(SOURCE_FILES
-# cache.c
+ api.c
+ cfg.c
error.c
- event.c
- face.c
- face_cache.c
- face_rules.c
+ facelet.c
interface.c
- interface_map.c
- interface_ops_map.c
- facemgr.c
util/log.c
- util/policy.c
)
set(INCLUDE_DIRS
@@ -61,51 +43,82 @@ set(INCLUDE_DIRS
../includes/
${CONFIG_INCLUDE_DIR}
${LIBEVENT_INCLUDE_DIR}
+ ${HICN_INCLUDE_DIRS}
${LIBHICNCTRL_INCLUDE_DIRS}
)
set(LIBRARIES
${CONFIG_LIBRARY}
${LIBEVENT_LIBRARY}
+ ${HICN_LIBRARIES}
${LIBHICNCTRL_LIBRARIES}
)
+
add_subdirectory(interfaces)
-if (ANDROID_API)
- build_library(${FACE_MGR}
+if(WITH_THREAD)
+ set(LIBRARIES
+ ${LIBRARIES}
+ "pthread"
+ "event_pthreads"
+ )
+ set(COMPILER_DEFINITIONS
+ ${COMPILER_DEFINITIONS}
+ "-DWITH_THREAD"
+ )
+endif()
+
+if(WITH_EXAMPLE_DUMMY)
+ set(COMPILER_DEFINITIONS
+ ${COMPILER_DEFINITIONS}
+ "-DWITH_EXAMPLE_DUMMY"
+ )
+endif()
+
+if(WITH_EXAMPLE_UPDOWN)
+ set(COMPILER_DEFINITIONS
+ ${COMPILER_DEFINITIONS}
+ "-DWITH_EXAMPLE_UPDOWN"
+ )
+endif()
+
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
+ build_library(${LIBFACEMGR}
STATIC
SOURCES ${SOURCE_FILES}
INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
DEPENDS ${DEPENDENCIES}
- COMPONENT ${FACE_MGR}
+ LINK_LIBRARIES ${LIBRARIES}
+ COMPONENT ${FACEMGR}
INCLUDE_DIRS ${INCLUDE_DIRS}
INSTALL_ROOT_DIR hicn
DEFINITIONS ${COMPILER_DEFINITIONS}
)
else ()
- build_library(${FACE_MGR}
- STATIC NO_DEV
+ build_library(${LIBFACEMGR}
+ SHARED STATIC NO_DEV
SOURCES ${SOURCE_FILES}
INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
DEPENDS ${DEPENDENCIES}
- COMPONENT ${FACE_MGR}
+ LINK_LIBRARIES ${LIBRARIES}
+ COMPONENT ${FACEMGR}
INCLUDE_DIRS ${INCLUDE_DIRS}
INSTALL_ROOT_DIR hicn
DEFINITIONS ${COMPILER_DEFINITIONS}
)
endif ()
-if(NOT ANDROID_API AND NOT COMPILE_FOR_IOS)
+if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Android" AND NOT COMPILE_FOR_IOS)
list(APPEND DAEMON_SRC
main.c
)
- build_executable(${FACE_MGR}
+ build_executable(${FACEMGR}
SOURCES ${DAEMON_SRC}
- LINK_LIBRARIES ${FACE_MGR}.static ${LIBRARIES}
- DEPENDS ${FACE_MGR}.static
- COMPONENT ${FACE_MGR}
+ LINK_LIBRARIES ${LIBFACEMGR}.static ${LIBRARIES}
+ DEPENDS ${LIBFACEMGR}.static
+ COMPONENT ${FACEMGR}
INCLUDE_DIRS ${INCLUDE_DIRS}
DEFINITIONS ${COMPILER_DEFINITIONS}
)
diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c
new file mode 100644
index 000000000..f630792c4
--- /dev/null
+++ b/ctrl/facemgr/src/api.c
@@ -0,0 +1,1421 @@
+/*
+ * 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 facemgr.c
+ * \brief Implementation of Face manager library interface
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <hicn/facemgr/api.h>
+#include <hicn/facemgr/cfg.h>
+#include <hicn/util/log.h>
+
+#ifdef __APPLE__
+#include "interfaces/network_framework/network_framework.h"
+#endif /* __APPLE__ */
+
+#ifdef __linux__
+#include "interfaces/bonjour/bonjour.h"
+#endif /* __linux__ */
+
+#ifdef __ANDROID__
+#include <hicn/android_utility/android_utility.h>
+#endif /* __ANDROID__ */
+
+#include <hicn/ctrl/face.h>
+#include "common.h"
+#include "facelet.h"
+#include "interface.h"
+#include "util/map.h"
+#include "util/set.h"
+
+#define RAND_NAME_LEN 5
+
+#define DEFAULT_PORT 9695
+
+typedef struct {
+ interface_t * interface;
+ void * event;
+} interface_map_data_t;
+
+TYPEDEF_SET_H(facelet_cache, facelet_t *);
+TYPEDEF_SET(facelet_cache, facelet_t *, facelet_cmp, facelet_snprintf);
+
+TYPEDEF_MAP_H(interface_map, const char *, interface_map_data_t *);
+TYPEDEF_MAP(interface_map, const char *, interface_map_data_t *, strcmp, string_snprintf, generic_snprintf);
+
+int int_cmp(int x, int y) { return x - y; }
+
+TYPEDEF_MAP_H(bonjour_map, netdevice_t *, interface_t *);
+TYPEDEF_MAP(bonjour_map, netdevice_t *, interface_t *, netdevice_cmp, generic_snprintf, generic_snprintf);
+
+/* TODO automatically register interfaces */
+
+#ifdef __APPLE__
+extern interface_ops_t network_framework_ops;
+#endif
+#ifdef __linux__
+extern interface_ops_t netlink_ops;
+extern interface_ops_t bonjour_ops;
+#endif
+#ifdef __ANDROID__
+extern interface_ops_t android_utility_ops;
+#endif /* __ANDROID__ */
+#ifdef WITH_EXAMPLE_DUMMY
+extern interface_ops_t dummy_ops;
+#endif
+#ifdef WITH_EXAMPLE_UPDOWN
+extern interface_ops_t updown_ops;
+#endif
+extern interface_ops_t hicn_light_ops;
+
+
+int
+facemgr_overlay_snprintf(char * s, size_t size, const facemgr_overlay_t * overlay)
+{
+ return -1;
+}
+
+struct facemgr_s {
+ /**************************************************/
+ /* Configuration parameters (exposed through API) */
+
+ facemgr_cfg_t * cfg;
+
+#ifdef __ANDROID__
+ /*
+ * Those two pointers are needed to call java functions from the face
+ * manager.
+ */
+ JavaVM *jvm;
+#endif /* __ANDROID__ */
+
+ /* Event loop support */
+ void * loop;
+ void * (*loop_register_fd)(void * loop, int fd, void * cb, void * cb_args);
+ int (*loop_unregister_event)(void * loop, void * event);
+
+ /****************************/
+ /* Internal data structures */
+
+ /* Map of interfaces index by name */
+ interface_map_t interface_map;
+
+ /* Faces under construction */
+ facelet_cache_t facelet_cache;
+
+ /********************************************************/
+ /* Interfaces - Those should be fully replaced by a map */
+
+ interface_t * hl;
+
+#ifdef __ANDROID__
+ interface_t * au; /* android_utility */
+#endif /* __ANDROID__ */
+
+#ifdef __APPLE__
+ interface_t * nf; /* network_framework */
+#endif /* __APPLE__ */
+
+#ifdef __linux__
+ interface_t * nl; /* netlink */
+
+ /*
+ * We maintain a map of dynamically created bonjour interfaces, one for each
+ * found netdevice
+ */
+ bonjour_map_t bonjour_map;
+#endif /* __linux__ */
+
+#ifdef WITH_EXAMPLE_DUMMY
+ interface_t * dummy;
+#endif
+#ifdef WITH_EXAMPLE_UPDOWN
+ interface_t * updown;
+#endif
+};
+
+int
+facemgr_initialize(facemgr_t * facemgr)
+{
+ int rc;
+
+ rc = interface_map_initialize(&facemgr->interface_map);
+ if (rc < 0)
+ goto ERR_INTERFACE_MAP;
+
+ rc = facelet_cache_initialize(&facemgr->facelet_cache);
+ if (rc < 0)
+ goto ERR_FACE_CACHE_PENDING;
+
+#ifdef __linux__
+ rc = bonjour_map_initialize(&facemgr->bonjour_map);
+ if (rc < 0)
+ goto ERR_BJ;
+#endif /* __linux */
+
+ facemgr->cfg = facemgr_cfg_create();
+ if (!facemgr->cfg)
+ goto ERR_CFG;
+
+ return 0;
+
+ERR_CFG:
+#ifdef __linux__
+ bonjour_map_finalize(&facemgr->bonjour_map);
+ERR_BJ:
+#endif /* __linux__ */
+ facelet_cache_finalize(&facemgr->facelet_cache);
+ERR_FACE_CACHE_PENDING:
+ interface_map_finalize(&facemgr->interface_map);
+ERR_INTERFACE_MAP:
+ return -1;
+}
+
+int
+facemgr_finalize(facemgr_t * facemgr)
+{
+ int rc;
+
+ /* TODO Free all interfaces: pass free to map */
+
+ rc = interface_map_finalize(&facemgr->interface_map);
+ if (rc < 0)
+ goto ERR;
+
+ rc = facelet_cache_finalize(&facemgr->facelet_cache);
+ if (rc < 0)
+ goto ERR;
+
+#ifdef __linux__
+ rc = bonjour_map_finalize(&facemgr->bonjour_map);
+ if (rc < 0)
+ goto ERR;
+#endif /* __linux__ */
+
+ return 0;
+
+ERR:
+ return -1;
+}
+
+AUTOGENERATE_CREATE_FREE(facemgr);
+
+int
+facemgr_set_config(facemgr_t * facemgr, facemgr_cfg_t * cfg)
+{
+ if (facemgr->cfg) {
+ facemgr_cfg_free(facemgr->cfg);
+ }
+ facemgr->cfg = cfg;
+ return 0;
+}
+
+int facemgr_reset_config(facemgr_t * facemgr)
+{
+ assert(facemgr->cfg);
+ facemgr_cfg_free(facemgr->cfg);
+ facemgr->cfg = facemgr_cfg_create();
+ if (!facemgr->cfg)
+ return -1;
+ return 0;
+}
+
+facemgr_t *
+facemgr_create_with_config(facemgr_cfg_t * cfg)
+{
+ facemgr_t * facemgr = facemgr_create();
+ if (!facemgr)
+ return NULL;
+ int rc = facemgr_set_config(facemgr, cfg);
+ if (rc < 0) {
+ free(facemgr);
+ return NULL;
+ }
+ return facemgr;
+}
+
+int facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet);
+
+int
+facemgr_create_interface(facemgr_t * facemgr, const char * name, const char * type, void * cfg, interface_t ** pinterface)
+{
+ int fd, rc;
+ void * event = NULL;
+ char rand_name[RAND_NAME_LEN+1];
+ interface_t * interface;
+
+ if (!name) {
+ /*
+ * We can manipulate the name on the stack as it will be strdup'ed by
+ * interface_create
+ */
+ rand_str(rand_name, RAND_NAME_LEN);
+ name = rand_name;
+ }
+
+ INFO("Creating interface %s [%s]...", name, type);
+ interface = interface_create(name, type);
+ if (!interface) {
+ ERROR("Error creating interface %s [%s]", name, type);
+ goto ERR_CREATE;
+ }
+ interface_set_callback(interface, facemgr_on_event, facemgr);
+
+ fd = interface_initialize(interface, cfg);
+ if (fd < 0)
+ goto ERR_INIT;
+ if (fd != 0) {
+ event = facemgr->loop_register_fd(facemgr->loop, fd, interface->ops->callback, interface);
+ if (event == NULL)
+ goto ERR_FD;
+ }
+
+ interface_map_data_t * interface_map_data = malloc(sizeof(interface_map_data_t));
+ if (!interface_map_data)
+ goto ERR_MAP_DATA;
+
+
+ *interface_map_data = (interface_map_data_t) {
+ .interface = interface,
+ .event = event,
+ };
+
+ rc = interface_map_add(&facemgr->interface_map, interface->name, interface_map_data);
+ if (rc < 0)
+ goto ERR_MAP_ADD;
+
+ DEBUG("Interface %s created successfully.", name);
+ if (pinterface)
+ *pinterface = interface;
+ return 0;
+
+ERR_MAP_ADD:
+ free(interface_map_data);
+ERR_MAP_DATA:
+ if (fd > 0)
+ facemgr->loop_unregister_event(facemgr->loop, interface_map_data->event);
+ERR_FD:
+ interface_finalize(interface);
+ERR_INIT:
+ interface_free(interface);
+ERR_CREATE:
+ if (pinterface)
+ *pinterface = NULL;
+ return -1;
+}
+
+int
+facemgr_delete_interface(facemgr_t * facemgr, interface_t * interface)
+{
+ int rc;
+
+ interface_map_data_t * interface_map_data = NULL;
+
+ DEBUG("Removing interface %s\n", interface->name);
+ rc = interface_map_remove(&facemgr->interface_map, interface->name, &interface_map_data);
+ if (rc < 0)
+ return -1;
+
+ if (!interface_map_data)
+ return -1;
+
+ free(interface_map_data);
+
+ rc = facemgr->loop_unregister_event(facemgr->loop, interface_map_data->event);
+ if (rc < 0)
+ return -1;
+
+
+ interface_finalize(interface);
+ interface_free(interface);
+
+ return 0;
+}
+
+#ifdef __linux__
+int facemgr_query_bonjour(facemgr_t * facemgr, netdevice_t * netdevice)
+{
+ interface_t * bj = NULL;
+
+ int rc = bonjour_map_get(&facemgr->bonjour_map, netdevice, &bj);
+ if (rc < 0)
+ return rc;
+
+ if (!bj) {
+ /* Create a new bonjour interface */
+ bonjour_cfg_t bj_cfg = {
+ .netdevice = *netdevice,
+ };
+ rc = facemgr_create_interface(facemgr, NULL, "bonjour", &bj_cfg, &bj);
+ if (rc < 0) {
+ ERROR("Error creating 'Bonjour' interface for '%s'\n", netdevice->name);
+ return -1;
+ }
+ }
+
+ DEBUG("sending event to bonjour interface");
+
+ /* Send an event to the interface (GET ?) */
+ return interface_on_event(bj, NULL);
+}
+#endif /* __linux__ */
+
+#ifdef __ANDROID__
+int facemgr_query_android_utility(facemgr_t * facemgr, netdevice_t netdevice)
+{
+ /* Send an event to the interface */
+ facelet_t * facelet = facelet_create();
+ if (!facelet)
+ goto ERR_MALLOC;
+
+ int rc = facelet_set_netdevice(facelet, netdevice);
+ if (rc < 0)
+ goto ERR_ND;
+
+ rc = interface_on_event(facemgr->au, facelet);
+ if (rc < 0)
+ goto ERR_EVENT;
+
+ return 0;
+
+ERR_EVENT:
+ERR_ND:
+ facelet_free(facelet);
+ERR_MALLOC:
+ return -1;
+}
+#endif /* __ANDROID__ */
+
+
+/**
+ * \brief Performs a cache lookup to find matching facelets
+ * \param [in] facelet_cache - Facelet cache on which to perform lookup
+ * \param [in] facelet - Facelet to lookup
+ * \param [out] cached_facelet - Pointer used to return a newly allocated
+ * facelet array corresponding to the result of the cache lookup.
+ * \return The number of entries in the array in case of success (positive
+ * value), or -1 in case of error.
+ */
+int
+facelet_cache_lookup(const facelet_cache_t * facelet_cache, facelet_t * facelet,
+ facelet_t ***cached_facelets)
+{
+ /*
+ * If the facelet is uniquely identified by its key, it is used to perform
+ * an efficient lookup directly...
+ */
+ if (facelet_has_key(facelet)) {
+ facelet_t * found = NULL;
+ if (facelet_cache_get(facelet_cache, facelet, &found) < 0) {
+ ERROR("[facelet_cache_lookup] Error during cache lookup");
+ return -1;
+ }
+ if (!found)
+ return 0;
+ *cached_facelets = malloc(sizeof(facelet_t*));
+ *cached_facelets[0] = found;
+ return 1;
+ }
+
+ /* ...otherwise, we iterate over the facelet
+ * cache to find matching elements.
+ */
+ facelet_t ** facelet_array;
+ int n = facelet_cache_get_array(facelet_cache, &facelet_array);
+ if (n < 0) {
+ ERROR("[facelet_cache_lookup] Error during cache match");
+ return -1;
+ }
+ *cached_facelets = malloc(n * sizeof(facelet_t*));
+
+ DEBUG("cache match n = %d", n);
+
+ int num_match = 0;
+ for (unsigned i = 0; i < n; i++) {
+ char buf[128];
+ facelet_snprintf(buf, 128, facelet_array[i]);
+ DEBUG("- facelet_array[%d] %s", i, buf);
+ facelet_snprintf(buf, 128, facelet);
+ DEBUG(" facelet %s", buf);
+
+ DEBUG("match ?");
+ if (!facelet_match(facelet_array[i], facelet)) {
+ DEBUG("no match");
+ continue;
+ }
+ DEBUG("match!");
+ (*cached_facelets)[num_match++] = facelet_array[i];
+ }
+ free(facelet_array);
+ DEBUG("return nummatch=%d", num_match);
+ return num_match;
+}
+
+
+/**
+ * \brief Checks whether the facelet satisfies face creation rules
+ * \param [in] facemgr - Pointer to the face manager instance
+ * \param [in] facelet - Pointer to the facelet to process
+ * \return 0 in case of success, -2 if we don't have enough information to
+ * decide, -3 if the face does not satisfy rules, and -1 in case of error
+ */
+int
+facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
+{
+ /* As key, netdevice and family should always be present */
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ int rc = facelet_get_netdevice(facelet, &netdevice);
+ if (rc < 0) {
+ ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice from facelet");
+ return -1;
+ }
+
+ int family = AF_UNSPEC;
+ if (facelet_has_family(facelet)) {
+ if (facelet_get_family(facelet, &family) < 0) {
+ ERROR("[facemgr_facelet_satisfy_rules] Error retrieving family from facelet");
+ return -1;
+ }
+ }
+
+ netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+#ifdef __ANDROID__
+ /*
+ * In addition to netdevice, netdevice_type should be present to correctly
+ * apply rules
+ */
+ rc = facelet_get_netdevice_type(facelet, &netdevice_type);
+ if (rc < 0) {
+ ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from facelet");
+ return -2;
+ }
+#endif /* __ANDROID__ */
+
+ /* Ignore */
+ bool ignore;
+ if (facemgr_cfg_get_ignore(facemgr->cfg, &netdevice, netdevice_type,
+ &ignore) < 0)
+ return -1;
+ if (ignore) {
+ DEBUG("Ignored interface '%s/%s'...", netdevice.name,
+ netdevice_type_str[netdevice_type]);
+ return -3;
+ }
+
+ /* IPv4 */
+ bool ipv4;
+ if (facemgr_cfg_get_ipv4(facemgr->cfg, &netdevice, netdevice_type,
+ &ipv4) < 0)
+ return -1;
+ if (!ipv4) {
+ DEBUG("Ignored IPv4...");
+ return -3;
+ }
+
+ /* IPv6 */
+ bool ipv6;
+ if (facemgr_cfg_get_ipv6(facemgr->cfg, &netdevice, netdevice_type,
+ &ipv6) < 0)
+ return -1;
+ if (!ipv6) {
+ DEBUG("Ignored IPv6...");
+ return -3;
+ }
+
+ return 0;
+}
+
+#ifdef __ANDROID__
+/**
+ * \brief Complements facelet information through Android Utility interface
+ * \return 0 if request was successful, -1 in case of error, and -2 if the
+ * interface is not applicable
+ *
+ * This function returnds _after_ completion.
+ */
+int
+facemgr_complement_facelet_au(facemgr_t * facemgr, facelet_t * facelet)
+{
+
+ if (facelet_has_netdevice_type(facelet))
+ return -2;
+
+ if (facelet_is_au_done(facelet))
+ return -2;
+
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ int rc = facelet_get_netdevice(facelet, &netdevice);
+ if (rc < 0) {
+ ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice from facelet");
+ return -1;
+ }
+
+ DEBUG("Querying android utility...");
+ facelet_set_au_done(facelet);
+
+ /* /!\ Synchronous code here /!\ */
+ if (facemgr_query_android_utility(facemgr, netdevice) < 0)
+ return -1;
+ return 0;
+}
+#endif /* __ANDROID__ */
+
+#ifdef __linux__
+/**
+ * \brief Complements facelet information through Bonjour interface.
+ * \return 0 if request was successful, -1 in case of error, and -2 if the
+ * interface is not applicable
+ *
+ * This function returnds _before_ completion as bonjour querying is
+ * asynchronous.
+ */
+int
+facemgr_complement_facelet_bj(facemgr_t * facemgr, facelet_t * facelet)
+{
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ int rc = facelet_get_netdevice(facelet, &netdevice);
+ if (rc < 0) {
+ ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice from facelet");
+ return -1;
+ }
+
+ netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+#ifdef __ANDROID__
+ /*
+ * In addition to netdevice, netdevice_type should be present to correctly
+ * apply rules
+ */
+ rc = facelet_get_netdevice_type(facelet, &netdevice_type);
+ if (rc < 0) {
+ ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice_type from facelet");
+ return -2;
+ }
+#endif /* __ANDROID__ */
+
+ bool discovery;
+ if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type,
+ &discovery) < 0)
+ return -2;
+
+ DEBUG("Discovery: %s", discovery ? "ON" : "OFF");
+
+ if (!discovery)
+ return -2;
+
+ facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
+ if (facelet_get_face_type(facelet, &face_type) < 0) {
+ ERROR("[facemgr_complement_facelet_bj] Error retrieving face type from facelet");
+ return -1;
+ }
+
+ bool discovery_needed = (face_type.layer == FACE_TYPE_LAYER_4) &&
+ ((!facelet_has_remote_addr(facelet)) || (!facelet_has_remote_port(facelet)));
+
+ DEBUG("Discovery needed: %s", discovery ? "ON" : "OFF");
+
+ if (!discovery_needed) {
+ return -2;
+ }
+
+ if (!facelet_has_local_addr(facelet)) {
+ DEBUG("No discovery possible without local address");
+ return -2;
+ }
+
+ if (facelet_is_bj_done(facelet)) {
+ DEBUG("Bonjour already queried");
+ return -2;
+ }
+
+ facelet_set_bj_done(facelet);
+ return facemgr_query_bonjour(facemgr, &netdevice);
+}
+#endif /* __linux__ */
+
+/**
+ * \brief Complements facelet information through Manual settings.
+ * \return 0 if request was successful, -1 in case of error, and -2 if the
+ * interface is not applicable
+ *
+ * This function returnds _before_ completion as bonjour querying is
+ * asynchronous.
+ */
+int
+facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet)
+{
+
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ int rc = facelet_get_netdevice(facelet, &netdevice);
+ if (rc < 0) {
+ ERROR("[facemgr_complement_facelet_manual] Error retrieving netdevice from facelet");
+ return -1;
+ }
+
+ netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+#ifdef __ANDROID__
+ /*
+ * In addition to netdevice, netdevice_type should be present to correctly
+ * apply rules
+ */
+ rc = facelet_get_netdevice_type(facelet, &netdevice_type);
+ if (rc < 0) {
+ ERROR("[facemgr_complement_facelet_manual] Error retrieving netdevice_type from facelet");
+ return -2;
+ }
+#endif /* __ANDROID__ */
+
+ int family = AF_UNSPEC;
+ if (facelet_has_family(facelet)) {
+ if (facelet_get_family(facelet, &family) < 0) {
+ ERROR("[facemgr_complement_facelet_manual] Error retrieving family from facelet");
+ return -1;
+ }
+ }
+
+ /* Do not query manual is there is a change to go through bonjour */
+ bool discovery;
+ if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type,
+ &discovery) < 0)
+ return -2;
+
+ facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
+ if (facelet_get_face_type(facelet, &face_type) < 0) {
+ ERROR("[facemgr_complement_facelet_manual] Error retrieving face type from facelet");
+ return -1;
+ }
+
+ bool discovery_needed = (face_type.layer == FACE_TYPE_LAYER_4) &&
+ ((!facelet_has_remote_addr(facelet)) || (!facelet_has_remote_port(facelet)));
+
+ if (!discovery_needed) {
+ DEBUG("manual settings not considered as no discovery is needed");
+ return -2;
+ }
+
+ if (discovery && !facelet_is_bj_done(facelet)) {
+ DEBUG("manual settings not considered as discovery is enabled and Bonjour has not yet been done");
+ return -2;
+ }
+
+ DEBUG("Applying manual settings...");
+ /*
+ * Manual overlay specification (remote addr/port)
+ * We never override a result we have obtained through bonjour
+ */
+ if (!facelet_has_remote_addr(facelet)) {
+ ip_address_t remote_addr;
+ if (facemgr_cfg_get_overlay_remote_addr(facemgr->cfg,
+ &netdevice, netdevice_type, family, &remote_addr) < 0) {
+ ERROR("[facemgr_complement_facelet_manual] Error getting remote addr information from cfg");
+ return -1;
+ }
+ if (ip_address_empty(&remote_addr)) {
+ ERROR("[facemgr_complement_facelet_manual] Got empty remote addr information from cfg");
+ } else {
+ DEBUG(" - remote address");
+ facelet_set_remote_addr(facelet, remote_addr);
+ }
+ }
+
+ if (!facelet_has_remote_port(facelet)) {
+ uint16_t remote_port;
+ int rc = facemgr_cfg_get_overlay_remote_port(facemgr->cfg,
+ &netdevice, netdevice_type, family, &remote_port);
+ if (rc < 0) {
+ ERROR("[facemgr_complement_facelet_manual] Error getting remote port information from cfg");
+ return -1;
+ }
+ DEBUG(" - remote port");
+ facelet_set_remote_port(facelet, remote_port);
+ }
+
+ /*
+ * Complementing local addr/port XXX this should be done somewhere
+ * else : manual settings have the lowest priority
+ *
+ * Local IP address is specific as it allows to override the source
+ * address just before creating the face... we would need to check
+ * whether this is an address that belong to us... it might be used
+ * to arbitrate amongst several IP addresses instead...
+ */
+ ip_address_t local_addr;
+ if (facemgr_cfg_get_overlay_local_addr(facemgr->cfg, &netdevice,
+ netdevice_type, family, &local_addr) < 0) {
+ ERROR("[facemgr_complement_facelet_manual] Error getting local addr information from cfg");
+ return -1;
+ }
+ if (ip_address_empty(&local_addr)) {
+ ERROR("[facemgr_complement_facelet_manual] Got empty local addr information from cfg");
+ } else {
+ DEBUG(" - local addres");
+ facelet_set_local_addr(facelet, local_addr);
+ }
+
+ /* Sets a default local port, so far nobody sets it */
+ uint16_t local_port;
+ if (facemgr_cfg_get_overlay_local_port(facemgr->cfg,
+ &netdevice, netdevice_type, family, &local_port) < 0) {
+ ERROR("[facemgr_complement_facelet_manual] Error getting local port information from cfg");
+ return -1;
+ }
+ DEBUG(" - local port");
+ facelet_set_local_port(facelet, local_port);
+ return 0;
+}
+
+int
+facemgr_complement_facelet(facemgr_t * facemgr, facelet_t * facelet)
+{
+ int rc;
+
+ if (!facelet_has_key(facelet))
+ return -2;
+
+#ifdef __ANDROID__
+ rc = facemgr_complement_facelet_au(facemgr, facelet);
+ if (rc != -2)
+ return rc;
+#endif /* __ANDROID__ */
+
+ /* We continue only if the current call was not applicable. In the current
+ * setting we have no interface that can be requested in parallel, and no
+ * need to. This might evolve in future releases.
+ */
+
+#ifdef __linux__
+ rc = facemgr_complement_facelet_bj(facemgr, facelet);
+ if (rc != -2)
+ return rc;
+#endif /* __linux__ */
+
+ DEBUG("Complement manual");
+
+ rc = facemgr_complement_facelet_manual(facemgr, facelet);
+ if (rc != -2)
+ return rc;
+
+ INFO("[facemgr_complement_facelet] No more interfaces to query... incomplete face");
+ return 0;
+}
+
+/**
+ * \brief Process facelet CREATE event
+ * \param [in] facemgr - Pointer to the face manager instance
+ * \param [in] facelet - Pointer to the facelet event to process
+ * \return 0 if everything went correctly, or -1 in case of error.
+ */
+int
+facemgr_process_create(facemgr_t * facemgr, facelet_t * facelet)
+{
+ /*
+ * We create an interface locally, which does not means it should not exist
+ * remotely. Once such codepath is enabled, the two facelets will have been
+ * merged and we need to handle an eventual update on our side.
+ *
+ * In the same way, we need to check for the equivalence of face types etc.
+ */
+ int rc;
+
+ if (facelet_cache_add(&facemgr->facelet_cache, facelet) < 0) {
+ ERROR("[facemgr_process_create] Error adding facelet to cache");
+ return -1;
+ }
+ DEBUG("Facelet added to cache");
+
+ /*
+ * If the facelet does not satisfy filters, we do not lose any information
+ * but do not take any action to complement the face
+ */
+ rc = facemgr_facelet_satisfy_rules(facemgr, facelet);
+ if (rc == -3) {
+ /* Does not satisfy rules */
+ return 0;
+ }
+
+ // FIXME: we should complement a part of the facelet, so that we don't
+ // necessarily keep this information if we get more locally. Or at least we
+ // should remember that.
+ if (rc == -2) {
+ /*
+ * We don't have equivalent for linux right now, heuristic is only used
+ * at the end... might change.
+ */
+#ifdef __ANDROID__
+ /* Priority is given to information that complements a face */
+ if (facemgr_complement_facelet_au(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_create] Error while attempting to complement face for fields required by rule application");
+ return -1;
+ }
+ return 0;
+#endif /* __ANDROID__ */
+ }
+ if (rc < 0)
+ return -1;
+
+// netdevice_t netdevice = NETDEVICE_EMPTY;
+// if (facelet_get_netdevice(facelet, &netdevice) < 0) {
+// ERROR("[facemgr_process_create] Error retrieving netdevice from facelet");
+// return -1;
+// }
+//
+// netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+//#ifdef __ANDROID__
+// /*
+// * In addition to netdevice, netdevice_type should be present to correctly
+// * apply rules
+// */
+// if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
+// ERROR("[facemgr_process_create] Error retrieving netdevice_type from facelet");
+// return -2;
+// }
+//#endif /* __ANDROID__ */
+
+
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
+ DEBUG("---[ FACELET CREATE : %s ] ---", facelet_s);
+
+ /* Do we have enough information about the facelet ? */
+ if (!facelet_validate_face(facelet)) {
+ if (facemgr_complement_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_create] Error while attempting to complement face for fields required by face creation");
+ return -1;
+ }
+ // we should not stop after complement_manual but create a face if
+ // possible... so we add a second validation
+ }
+
+ if (!facelet_validate_face(facelet))
+ return 0;
+
+ /*
+ * Is the forwarder connected, and has the facelet cache already sync'ed the
+ * remote faces ?
+ */
+ // TODO
+
+ /*
+ * Actually create the face on the forwarder
+ *
+ * FIXME Currently hicn-light is hardcoded
+ */
+ if (interface_on_event(facemgr->hl, facelet) < 0)
+ return -1;
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ return 0;
+}
+
+/**
+ * \brief Process facelet GET event
+ * \param [in] facemgr - Pointer to the face manager instance
+ * \param [in] facelet - Pointer to the facelet event to process
+ * \return 0 if everything went correctly, or -1 in case of error.
+ */
+int
+facemgr_process_get(facemgr_t * facemgr, facelet_t * facelet)
+{
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ if (facelet_has_netdevice(facelet)) {
+ netdevice_t netdevice;
+ if (facelet_get_netdevice(facelet, &netdevice) < 0)
+ return -1;
+ if (!IS_VALID_NETDEVICE(netdevice))
+ return 0;
+ return facelet_cache_add(&facemgr->facelet_cache, facelet);
+ }
+ return 0;
+}
+
+/**
+ * \brief Process facelet UPDATE event
+ * \param [in] facemgr - Pointer to the face manager instance
+ * \param [in] facelet - Pointer to the facelet event to process
+ * \return 0 if everything went correctly, or -1 in case of error.
+ */
+int
+facemgr_process_update(facemgr_t * facemgr, facelet_t * facelet)
+{
+ /* This is the most complex operation since we have the same problems as in
+ * CREATE + the need to manage changes...
+ *
+ * This might eventually trigger a face deletion...
+ */
+
+ /*
+ * Update in local does not mean the face should not be created remotely as
+ * it might be the first time we have enough information to create it
+ */
+
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
+ DEBUG("---[ FACELET UPDATE : %s ] ---", facelet_s);
+
+ /* Sets face type */
+ if (!facelet_has_face_type(facelet)) {
+
+ /* As key, netdevice and family should always be present */
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ int rc = facelet_get_netdevice(facelet, &netdevice);
+ if (rc < 0) {
+ ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice from facelet");
+ return -1;
+ }
+
+ netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+#ifdef __ANDROID__
+ /*
+ * In addition to netdevice, netdevice_type should be present to correctly
+ * apply rules
+ */
+ rc = facelet_get_netdevice_type(facelet, &netdevice_type);
+ if (rc < 0) {
+ ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from facelet");
+ return -2;
+ }
+#endif /* __ANDROID__ */
+
+ facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
+ if (facemgr_cfg_get_face_type(facemgr->cfg, &netdevice, netdevice_type, &face_type) < 0)
+ return rc;
+ facelet_set_face_type(facelet, face_type);
+ }
+
+ /* Process GET/UDPATE... */
+ switch(facelet_get_status(facelet)) {
+ case FACELET_STATUS_UNDEFINED:
+ ERROR("[facemgr_process_update] Unexpected facelet status");
+ return -1;
+
+ case FACELET_STATUS_DELETED:
+ case FACELET_STATUS_NEW:
+ /*
+ * If the remote action should be a CREATE, then we need to check
+ * whether we have enough information about the face...
+ */
+ if (!facelet_validate_face(facelet)) {
+ if (facemgr_complement_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_update] Error while attempting to complement face for fields required by face creation");
+ return -1;
+ }
+ }
+ if (!facelet_validate_face(facelet))
+ return 0;
+
+ facelet_set_event(facelet, FACELET_EVENT_CREATE);
+ interface_on_event(facemgr->hl, facelet);
+
+ /* This works assuming the call to hicn-light is blocking */
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ break;
+
+ case FACELET_STATUS_CLEAN:
+ /* Nothing to do */
+ break;
+
+ case FACELET_STATUS_DIRTY:
+ /*
+ * For now we assume only local changes, and proceed to try and
+ * update the hICN forwarder.
+ *
+ * In case of update, the face exists which means we should already
+ * have enough information
+ */
+ if (!facelet_validate_face(facelet)) {
+ if (facemgr_complement_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_create] Error while attempting to complement face for fields required by face creation");
+ return -1;
+ }
+ }
+
+ if (!facelet_validate_face(facelet))
+ return 0;
+
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ if (interface_on_event(facemgr->hl, facelet) < 0)
+ return -1;
+
+ /* This works assuming the call to hicn-light is blocking and we
+ * have proceeded to all udpates */
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ break;
+
+ case FACELET_STATUS_CONFLICT:
+ ERROR("[facemgr_process_update] Conflict resolution (not) yet implemented");
+ return -1;
+ case FACELET_STATUS_N:
+ ERROR("[facemgr_process_update] Facelet in error");
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * \brief Process facelet DELETE event
+ * \param [in] facemgr - Pointer to the face manager instance
+ * \param [in] facelet - Pointer to the facelet event to process
+ * \return 0 if everything went correctly, or -1 in case of error.
+ */
+int
+facemgr_process_delete(facemgr_t * facemgr, facelet_t * facelet)
+{
+ if (interface_on_event(facemgr->hl, facelet) < 0)
+ return -1;
+
+ facelet_set_status(facelet, FACELET_STATUS_DELETED);
+ //facelet_set_bj_done(facelet, false);
+
+ return 0;
+}
+
+/**
+ * \brief Process incoming events from interfaces
+ *
+ * Implementation notes:
+ * - Any event or timeout due to an interface triggers either a local cache
+ * update, as well a face operations needed to resync the state.
+ */
+int
+facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
+{
+ int ret = 0;
+ assert(facelet_in);
+
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_in);
+ DEBUG("----------------------------------");
+ DEBUG("EVENT %s\n", facelet_s);
+
+ facelet_t ** cached_facelets = NULL;
+ int n = facelet_cache_lookup(&facemgr->facelet_cache, facelet_in, &cached_facelets);
+ if (n < 0) {
+ ERROR("[facemgr_on_event] Error during cache lookup");
+ goto ERR;
+ }
+ DEBUG("num matches n=%d", n);
+ if (n == 0) {
+ /* This is a new facelet... we expect a CREATE event. */
+ switch(facelet_get_event(facelet_in)) {
+ case FACELET_EVENT_CREATE:
+ if (facemgr_process_create(facemgr, facelet_in) < 0) {
+ ERROR("[facemgr_process_cached_facelet] Error processing CREATE event");
+ goto ERR;
+ }
+ break;
+
+ case FACELET_EVENT_GET:
+ /* Insert new facelet in cached */
+ if (facemgr_process_get(facemgr, facelet_in) < 0) {
+ ERROR("[facemgr_process_cached_facelet] Error processing GET event");
+ goto ERR;
+ }
+ break;
+
+ case FACELET_EVENT_UPDATE:
+ /* Might be because we previously ignored the facelet... */
+ //ERROR("[facemgr_on_event] Unexpected UPDATE... face does not exist");
+ //goto ERR;
+ INFO("Ignored UPDATE for non-existing face");
+ break;
+
+ case FACELET_EVENT_DELETE:
+ ERROR("[facemgr_on_event] Unexpected DELETE... face does not exist");
+ goto ERR;
+
+ case FACELET_EVENT_UNDEFINED:
+ ERROR("[facemgr_on_event] Unexpected UNDEFINED event.");
+ goto ERR;
+
+ default: /* XXX Some events should be deprecated */
+ ERROR("[facemgr_on_event] Deprecated event");
+ goto ERR;
+ }
+ goto DUMP_CACHE;
+ }
+
+ /*
+ * From now on, it should not make any difference whether we have one or
+ * more facelet.
+ */
+ for (unsigned i = 0; i < n; i ++) {
+ /*
+ * We merge each cached facelet with incoming one, and perform state
+ * reconciliation by sending appropriate updates to the forwarder
+ */
+ facelet_t * facelet = cached_facelets[i];
+ DEBUG("... match #%d", i);
+ switch(facelet_get_event(facelet_in)) {
+ case FACELET_EVENT_CREATE:
+ // FIXME, this might occur if the facemgr restarts and we try to
+ // re-create existing faces
+ ERROR("[facemgr_on_event] CREATE event for a face that already exists...");
+ ret = -1;
+ continue;
+
+ case FACELET_EVENT_GET: /* should be an INFORM message */
+ // FIXME, this might occur if the forwarder restarts and we
+ // resync faces...
+ ERROR("[facemgr_on_event] GET event for a face that already exists...");
+ ret = -1;
+ continue;
+
+ case FACELET_EVENT_UPDATE:
+ {
+ DEBUG("FACELET_EVENT_UPDATE");
+ char buf[128];
+ facelet_snprintf(buf, 128, facelet_in);
+ DEBUG("MERGE %s", buf);
+ facelet_snprintf(buf, 128, facelet);
+ DEBUG(" ON %s", buf);
+ }
+ if (facelet_merge(facelet, facelet_in) < 0) {
+ ERROR("[facemgr_on_event] Error merging facelets");
+ continue;
+ }
+ if (facemgr_process_update(facemgr, facelet) < 0) {
+ ERROR("[facemgr_on_event] Error processing UPDATE event");
+ ret = -1;
+ }
+ continue;
+
+ case FACELET_EVENT_DELETE:
+ if (facelet_merge(facelet, facelet_in) < 0) {
+ ERROR("[facemgr_on_event] Error merging facelets");
+ continue;
+ }
+ if (facemgr_process_delete(facemgr, facelet) < 0) {
+ ERROR("[facemgr_on_event] Error processing DELETE event");
+ ret = -1;
+ }
+ continue;
+
+ default: /* XXX Some events should be deprecated */
+ ERROR("[facemgr_on_event] Deprecated event");
+ ret = -1;
+ }
+
+ }
+ free(cached_facelets);
+ goto DUMP_CACHE;
+
+ERR:
+ ret = -1;
+
+DUMP_CACHE:
+ DEBUG(" <CACHE>");
+ facelet_cache_dump(&facemgr->facelet_cache);
+ DEBUG(" </CACHE>");
+ DEBUG("</EVENT ret=%d>", ret);
+ DEBUG("----------------------------------");
+ return ret;
+}
+
+int
+facemgr_bootstrap(facemgr_t * facemgr)
+{
+ int rc;
+
+ DEBUG("Registering interfaces...");
+ rc = interface_register(&hicn_light_ops);
+ if (rc < 0) {
+ ERROR("Could not register interfaces");
+ goto ERR_REGISTER;
+ }
+
+#ifdef __APPLE__
+ rc = interface_register(&network_framework_ops);
+ if (rc < 0)
+ goto ERR_REGISTER;
+#endif /* __APPLE__ */
+
+#ifdef __linux__
+ rc = interface_register(&netlink_ops);
+ if (rc < 0)
+ goto ERR_REGISTER;
+ rc = interface_register(&bonjour_ops);
+ if (rc < 0)
+ goto ERR_REGISTER;
+#endif /* __linux__ */
+
+#ifdef __ANDROID__
+ rc = interface_register(&android_utility_ops);
+ if (rc < 0)
+ goto ERR_REGISTER;
+#endif /* __ANDROID__ */
+
+#ifdef WITH_EXAMPLE_DUMMY
+ rc = interface_register(&dummy_ops);
+ if (rc < 0)
+ goto ERR_REGISTER;
+#endif
+
+#ifdef WITH_EXAMPLE_UPDOWN
+ rc = interface_register(&updown_ops);
+ if (rc < 0)
+ goto ERR_REGISTER;
+#endif
+
+ rc = facemgr_create_interface(facemgr, "hl", "hicn_light", NULL, &facemgr->hl);
+ if (rc < 0) {
+ ERROR("Error creating 'hICN forwarder (hicn-light)' interface\n");
+ goto ERR_HL_CREATE;
+ }
+
+#ifdef __APPLE__
+ network_framework_cfg_t nf_cfg = {
+ .rules = &facemgr->rules,
+ };
+ rc = facemgr_create_interface(facemgr, "nf", "network_framework", &nf_cfg, &facemgr->nf);
+ if (rc < 0) {
+ ERROR("Error creating 'Apple Network Framework' interface\n");
+ goto ERR_NF_CREATE;
+ }
+#endif /* __APPLE__ */
+
+#ifdef __linux__
+ rc = facemgr_create_interface(facemgr, "nl", "netlink", NULL, &facemgr->nl);
+ if (rc < 0) {
+ ERROR("Error creating 'Netlink' interface\n");
+ goto ERR_NL_CREATE;
+ }
+#endif /* __linux__ */
+
+#ifdef __ANDROID__
+ android_utility_cfg_t au_cfg = {
+ .jvm = facemgr->jvm,
+ };
+ rc = facemgr_create_interface(facemgr, "au", "android_utility", &au_cfg, &facemgr->au);
+ if (rc < 0) {
+ ERROR("Error creating 'Android Utility' interface\n");
+ goto ERR_AU_CREATE;
+ }
+#endif /* __ANDROID__ */
+
+#ifdef WITH_EXAMPLE_DUMMY
+ rc = facemgr_create_interface(facemgr, "dummy0", "dummy", NULL, &facemgr->dummy);
+ if (rc < 0) {
+ ERROR("Error creating 'dummy' interface\n");
+ goto ERR_DUMMY_CREATE;
+ }
+#endif
+
+#ifdef WITH_EXAMPLE_UPDOWN
+ rc = facemgr_create_interface(facemgr, "updown0", "updown", NULL, &facemgr->updown);
+ if (rc < 0) {
+ ERROR("Error creating 'updown' interface\n");
+ goto ERR_UPDOWN_CREATE;
+ }
+#endif
+
+ DEBUG("Facemgr successfully initialized...");
+
+ return 0;
+
+ /* FIXME facemgr_delete_interface */
+#ifdef WITH_EXAMPLE_UPDOWN
+ interface_free(facemgr->updown);
+ERR_UPDOWN_CREATE:
+#endif
+#ifdef WITH_EXAMPLE_DUMMY
+ interface_free(facemgr->dummy);
+ERR_DUMMY_CREATE:
+#endif
+#ifdef __ANDROID__
+ interface_free(facemgr->au);
+ERR_AU_CREATE:
+#endif /* __ANDROID__ */
+#ifdef __linux__
+ interface_free(facemgr->nl);
+ERR_NL_CREATE:
+#endif /* __linux__ */
+#ifdef __APPLE__
+ interface_free(facemgr->nf);
+ERR_NF_CREATE:
+#endif /* __APPLE__ */
+ interface_free(facemgr->hl);
+ERR_HL_CREATE:
+ERR_REGISTER:
+ return -1;
+}
+
+void facemgr_stop(facemgr_t * facemgr)
+{
+ // FIXME we should iterate on interface map
+
+#ifdef __APPLE__
+ facemgr_delete_interface(facemgr, facemgr->nf);
+#endif /* __APPLE__ */
+
+
+#ifdef __linux__
+ facemgr_delete_interface(facemgr, facemgr->nl);
+
+ /* Delete all bonjour interfaces */
+ interface_t ** bonjour_array;// = NULL; // NOTE: would allow avoiding tests
+ int n = bonjour_map_get_value_array(&facemgr->bonjour_map, &bonjour_array);
+ if (n > 0) {
+ netdevice_t ** netdevice_array; // = NULL;
+ int m = bonjour_map_get_key_array(&facemgr->bonjour_map, &netdevice_array);
+ if (m > 0) {
+ assert(m == n);
+ for (int i = 0; i < n; i++) { /* Fail silently */
+ DEBUG("Deleting bonjour interface associated to %s (%p)\n",
+ netdevice_array[i]->name, bonjour_array[i]);
+ facemgr_delete_interface(facemgr, bonjour_array[i]);
+ }
+ free(netdevice_array);
+ }
+ free(bonjour_array);
+ }
+#endif /* __linux__ */
+
+#ifdef __ANDROID__
+ facemgr_delete_interface(facemgr, facemgr->au);
+#endif /* __ANDROID__ */
+
+ facemgr_delete_interface(facemgr, facemgr->hl);
+
+#ifdef WITH_EXAMPLE_DUMMY
+ facemgr_delete_interface(facemgr, facemgr->dummy);
+#endif
+
+#ifdef WITH_EXAMPLE_UPDOWN
+ facemgr_delete_interface(facemgr, facemgr->updown);
+#endif
+}
+
+#ifdef __ANDROID__
+void facemgr_set_jvm(facemgr_t * facemgr, JavaVM *jvm)
+{
+ facemgr->jvm = jvm;
+}
+#endif /* __ANDROID__ */
+
+void facemgr_set_event_loop_handler(facemgr_t * facemgr, void * loop, void * loop_register_fd, void * loop_unregister_event)
+{
+ facemgr->loop = loop;
+ facemgr->loop_register_fd = loop_register_fd;
+ facemgr->loop_unregister_event = loop_unregister_event;
+}
+
+void facemgr_list_faces(facemgr_t * facemgr, facemgr_list_faces_cb_t cb, void * user_data)
+{
+ //face_cache_iter(&facemgr->face_cache, cb, user_data);
+ facelet_cache_dump(&facemgr->facelet_cache);
+}
diff --git a/ctrl/facemgr/src/cfg.c b/ctrl/facemgr/src/cfg.c
new file mode 100644
index 000000000..6b04208bb
--- /dev/null
+++ b/ctrl/facemgr/src/cfg.c
@@ -0,0 +1,991 @@
+/**
+ * \file cfg.c
+ * \brief Implementation of Face manager configuration
+ */
+
+#include <assert.h>
+#include <hicn/ctrl.h> // HICN_DEFAULT_PORT
+#include <hicn/facemgr/cfg.h>
+#include <hicn/policy.h>
+#include <hicn/util/ip_address.h>
+#include "util/set.h"
+
+/* Overlay */
+
+typedef struct {
+ bool is_local_port;
+ uint16_t local_port;
+ bool is_local_addr;
+ ip_address_t local_addr;
+ bool is_remote_port;
+ uint16_t remote_port;
+ bool is_remote_addr;
+ ip_address_t remote_addr;
+} facemgr_cfg_overlay_t;
+
+int
+facemgr_cfg_overlay_initialize(facemgr_cfg_overlay_t * overlay)
+{
+ overlay->is_local_port = false;
+ overlay->local_port = 0;
+ overlay->is_local_addr = false;
+ overlay->local_addr = IP_ADDRESS_EMPTY;
+
+ overlay->is_remote_port = false;
+ overlay->remote_port = 0;
+ overlay->is_remote_addr = false;
+ overlay->remote_addr = IP_ADDRESS_EMPTY;
+
+ return 0;
+}
+
+int
+facemgr_cfg_overlay_finalize(facemgr_cfg_overlay_t * overlay)
+{
+ return 0;
+}
+
+facemgr_cfg_overlay_t * facemgr_cfg_overlay_create()
+{
+ facemgr_cfg_overlay_t * overlay = malloc(sizeof(facemgr_cfg_overlay_t));
+ if (!overlay)
+ return NULL;
+
+ int rc = facemgr_cfg_overlay_initialize(overlay);
+ if (rc < 0) {
+ free(overlay);
+ return NULL;
+ }
+
+ return overlay;
+}
+
+void facemgr_cfg_overlay_free(facemgr_cfg_overlay_t * overlay)
+{
+ facemgr_cfg_overlay_finalize(overlay);
+ free(overlay);
+}
+
+typedef struct {
+ facemgr_cfg_overlay_t * v4;
+ facemgr_cfg_overlay_t * v6;
+} facemgr_cfg_overlays_t;
+
+typedef struct {
+ const char * interface_name;
+ netdevice_type_t interface_type;
+} facemgr_cfg_match_t;
+
+
+typedef struct {
+ /* Interface specific */
+ bool is_face_type; // default is auto
+ facemgr_face_type_t face_type;
+
+ /* This should be defaut for the global settings */
+ bool is_ignore;
+ bool ignore;
+ bool is_discovery;
+ bool discovery;
+ bool is_ipv4;
+ bool ipv4;
+ bool is_ipv6;
+ bool ipv6;
+
+ facemgr_cfg_overlays_t overlays; // fallback unless discovery is disabled
+} facemgr_cfg_override_t;
+
+struct facemgr_cfg_rule_s {
+ facemgr_cfg_match_t match;
+ facemgr_cfg_override_t override;
+};
+
+int
+facemgr_cfg_override_initialize(facemgr_cfg_override_t * override)
+{
+ override->is_face_type = false;
+ override->face_type = FACEMGR_FACE_TYPE_UNDEFINED;
+
+ override->is_ignore = false;
+ override->ignore = false;
+
+ override->is_discovery = false;
+ override->discovery = false;
+
+ override->overlays.v4 = NULL;
+ override->overlays.v6 = NULL;
+
+ return 0;
+}
+
+int
+facemgr_cfg_override_finalize(facemgr_cfg_override_t * override)
+{
+ if (override->overlays.v4) {
+ facemgr_cfg_overlay_free(override->overlays.v4);
+ override->overlays.v4 = NULL;
+ }
+ if (override->overlays.v6) {
+ facemgr_cfg_overlay_free(override->overlays.v6);
+ override->overlays.v6 = NULL;
+ }
+
+ return 0;
+}
+
+
+/* Rule */
+facemgr_cfg_rule_t * facemgr_cfg_rule_create()
+{
+ facemgr_cfg_rule_t * rule = malloc(sizeof(facemgr_cfg_rule_t));
+ if (!rule)
+ return NULL;
+
+ int rc = facemgr_cfg_rule_initialize(rule);
+ if (rc < 0)
+ return NULL;
+
+ return rule;
+}
+
+void facemgr_cfg_rule_free(facemgr_cfg_rule_t * rule)
+{
+ facemgr_cfg_rule_finalize(rule);
+ free(rule);
+}
+
+int
+facemgr_cfg_rule_initialize(facemgr_cfg_rule_t * rule)
+{
+ rule->match.interface_name = NULL;
+ rule->match.interface_type = NETDEVICE_TYPE_UNDEFINED;
+
+ int rc = facemgr_cfg_override_initialize(&rule->override);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int
+facemgr_cfg_rule_finalize(facemgr_cfg_rule_t * rule)
+{
+ if (rule->match.interface_name) {
+ free((void*)rule->match.interface_name);
+ rule->match.interface_name = NULL;
+ }
+ return facemgr_cfg_override_finalize(&rule->override);
+}
+
+void
+facemgr_cfg_rule_dump(facemgr_cfg_rule_t * rule)
+{
+ DEBUG(" <rule>");
+ DEBUG(" <match interface_name=%s interface_type=%s>",
+ rule->match.interface_name,
+ netdevice_type_str[rule->match.interface_type]);
+ DEBUG(" <override>");
+ if (rule->override.is_face_type) {
+ DEBUG(" <face_type>%d</face_type>", rule->override.face_type);
+ }
+ if (rule->override.is_ignore) {
+ DEBUG(" <ignore>%d</ignore>", rule->override.ignore);
+ }
+ if (rule->override.is_discovery) {
+ DEBUG(" <discovery>%d</discovery>", rule->override.discovery);
+ }
+ if (rule->override.is_ipv4) {
+ DEBUG(" <ipv4>%d</ipv4>", rule->override.ipv4);
+ }
+ if (rule->override.is_ipv6) {
+ DEBUG(" <ipv6>%d</ipv6>", rule->override.ipv6);
+ }
+ DEBUG(" <overlays>");
+ if (rule->override.overlays.v4) {
+ DEBUG(" <ipv4>");
+ if (rule->override.overlays.v4->is_local_addr) {
+ char buf[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
+ &rule->override.overlays.v4->local_addr, AF_INET);
+ DEBUG(" <local_addr>%s</local_addr>", buf);
+ }
+ if (rule->override.overlays.v4->is_local_port) {
+ DEBUG(" <local_port>%d</local_port>",
+ rule->override.overlays.v4->local_port);
+ }
+ if (rule->override.overlays.v4->is_remote_addr) {
+ char buf[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
+ &rule->override.overlays.v4->remote_addr, AF_INET);
+ DEBUG(" <remote_addr>%s</remote_addr>", buf);
+ }
+ if (rule->override.overlays.v4->is_remote_port) {
+ DEBUG(" <remote_port>%d</remote_port>",
+ rule->override.overlays.v4->remote_port);
+ }
+ DEBUG(" </ipv4>");
+ }
+ if (rule->override.overlays.v6) {
+ DEBUG(" <ipv6>");
+ if (rule->override.overlays.v6->is_local_addr) {
+ char buf[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
+ &rule->override.overlays.v6->local_addr, AF_INET6);
+ DEBUG(" <local_addr>%s</local_addr>", buf);
+ }
+ if (rule->override.overlays.v6->is_local_port) {
+ DEBUG(" <local_port>%d</local_port>",
+ rule->override.overlays.v6->local_port);
+ }
+ if (rule->override.overlays.v6->is_remote_addr) {
+ char buf[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
+ &rule->override.overlays.v6->remote_addr, AF_INET6);
+ DEBUG(" <remote_addr>%s</remote_addr>", buf);
+ }
+ if (rule->override.overlays.v6->is_remote_port) {
+ DEBUG(" <remote_port>%d</remote_port>",
+ rule->override.overlays.v6->remote_port);
+ }
+ DEBUG(" </ipv6>");
+ }
+ DEBUG(" </overlays>");
+ DEBUG(" </override>");
+ DEBUG(" </rule>");
+}
+
+int
+facemgr_cfg_rule_set_match(facemgr_cfg_rule_t * rule, const char * interface_name,
+ netdevice_type_t interface_type)
+{
+ rule->match.interface_name = interface_name ? strdup(interface_name) : NULL;
+ rule->match.interface_type = interface_type;
+ return 0;
+}
+
+int
+facemgr_cfg_rule_set_face_type(facemgr_cfg_rule_t * rule, facemgr_face_type_t * face_type)
+{
+ rule->override.is_face_type = true;
+ rule->override.face_type = *face_type;
+ return 0;
+}
+
+int
+facemgr_cfg_rule_unset_face_type(facemgr_cfg_rule_t * rule)
+{
+ rule->override.is_face_type = false;
+ rule->override.face_type = FACEMGR_FACE_TYPE_UNDEFINED; /* optional */
+ return 0;
+}
+
+int
+facemgr_cfg_rule_set_discovery(facemgr_cfg_rule_t * rule, bool status)
+{
+ rule->override.is_discovery = true;
+ rule->override.discovery = status;
+ return 0;
+}
+
+int
+facemgr_cfg_rule_unset_discovery(facemgr_cfg_rule_t * rule)
+{
+ rule->override.is_discovery = false;
+ return 0;
+}
+
+int
+facemgr_cfg_rule_set_ignore(facemgr_cfg_rule_t * rule, bool status)
+{
+ rule->override.is_ignore = true;
+ rule->override.ignore = status;
+ return 0;
+}
+
+int
+facemgr_cfg_rule_unset_ignore(facemgr_cfg_rule_t * rule)
+{
+ rule->override.is_ignore = false;
+ return 0;
+}
+
+int
+facemgr_cfg_rule_set_ipv4(facemgr_cfg_rule_t * rule, bool status)
+{
+ rule->override.is_ipv4 = true;
+ rule->override.ipv4 = status;
+ return 0;
+}
+
+int
+facemgr_cfg_rule_unset_ipv4(facemgr_cfg_rule_t * rule)
+{
+ rule->override.is_ipv4 = false;
+ return 0;
+}
+
+int
+facemgr_cfg_rule_set_ipv6(facemgr_cfg_rule_t * rule, bool status)
+{
+ rule->override.is_ipv6 = true;
+ rule->override.ipv6 = status;
+ return 0;
+}
+
+int
+facemgr_cfg_rule_unset_ipv6(facemgr_cfg_rule_t * rule)
+{
+ rule->override.is_ipv6 = false;
+ return 0;
+}
+
+int
+facemgr_cfg_rule_set_overlay(facemgr_cfg_rule_t * rule, int family,
+ ip_address_t * local_addr, uint16_t local_port,
+ ip_address_t * remote_addr, uint16_t remote_port) {
+ if ((family != AF_INET) && (family != AF_INET6))
+ return -1;
+
+ facemgr_cfg_overlay_t * overlay = facemgr_cfg_overlay_create();
+ if (local_addr) {
+ overlay->is_local_addr = true;
+ overlay->local_addr = *local_addr;
+ }
+ if (IS_VALID_PORT(local_port)) {
+ overlay->is_local_port = true;
+ overlay->local_port = local_port;
+ }
+ if (remote_addr) {
+ overlay->is_remote_addr = true;
+ overlay->remote_addr = *remote_addr;
+ }
+ if (IS_VALID_PORT(remote_port)) {
+ overlay->is_remote_port = true;
+ overlay->remote_port = remote_port;
+ }
+
+ switch(family) {
+ case AF_INET:
+ rule->override.overlays.v4 = overlay;
+ break;
+
+ case AF_INET6:
+ rule->override.overlays.v6 = overlay;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+facemgr_rule_unset_overlay(facemgr_cfg_rule_t * rule, int family)
+{
+ if ((family != AF_INET) && (family != AF_INET6) && (family != AF_UNSPEC))
+ return -1;
+
+ if ((family == AF_UNSPEC) || (family == AF_INET)) {
+ if (rule->override.overlays.v4) {
+ facemgr_cfg_overlay_free(rule->override.overlays.v4);
+ rule->override.overlays.v4 = NULL;
+ }
+ }
+ if ((family == AF_UNSPEC) || (family == AF_INET6)) {
+ if (rule->override.overlays.v6) {
+ facemgr_cfg_overlay_free(rule->override.overlays.v6);
+ rule->override.overlays.v6 = NULL;
+ }
+ }
+ return 0;
+}
+
+int
+facemgr_cfg_rule_cmp(const facemgr_cfg_rule_t * r1, const facemgr_cfg_rule_t * r2)
+{
+ /*
+ * We implement a lexicographic order on the tuple (interface_name,
+ * interface_type)
+ */
+
+ /* We need to handle NULL cases out of strcmp */
+ if (!r1->match.interface_name) {
+ if (r2->match.interface_name)
+ return 1;
+ else
+ goto BOTH_NULL;
+ } else {
+ if (!r2->match.interface_name)
+ return -1;
+ }
+
+
+ /* Only if both are non-NULL, we proceed to strcmp */
+ int rc = strcmp(r1->match.interface_name, r2->match.interface_name);
+ if (rc != 0)
+ return rc;
+
+BOTH_NULL:
+ return r1->match.interface_type - r2->match.interface_type;
+}
+
+/* General */
+
+TYPEDEF_SET_H(facemgr_cfg_rule_set, facemgr_cfg_rule_t *);
+TYPEDEF_SET(facemgr_cfg_rule_set, facemgr_cfg_rule_t *, facemgr_cfg_rule_cmp, generic_snprintf);
+
+struct facemgr_cfg_s {
+ facemgr_cfg_override_t global;
+ facemgr_cfg_rule_set_t * rule_set;
+ //log_cfg_t log;
+};
+
+facemgr_cfg_t * facemgr_cfg_create()
+{
+ facemgr_cfg_t * cfg = malloc(sizeof(facemgr_cfg_t));
+ if (!cfg)
+ return NULL;
+
+ int rc = facemgr_cfg_initialize(cfg);
+ if (rc < 0) {
+ free(cfg);
+ return NULL;
+ }
+
+ return cfg;
+}
+
+void facemgr_cfg_free(facemgr_cfg_t * cfg)
+{
+ facemgr_cfg_finalize(cfg);
+ free(cfg);
+}
+
+int
+facemgr_cfg_initialize(facemgr_cfg_t * cfg)
+{
+ int rc = facemgr_cfg_override_initialize(&cfg->global);
+ if (rc < 0)
+ goto ERR_OVERRIDE;
+
+ cfg->rule_set = facemgr_cfg_rule_set_create();
+ if (!cfg->rule_set)
+ goto ERR_RULE_SET;
+
+ return 0;
+
+ERR_RULE_SET:
+ facemgr_cfg_override_finalize(&cfg->global);
+ERR_OVERRIDE:
+ return -1;
+}
+
+int
+facemgr_cfg_finalize(facemgr_cfg_t * cfg)
+{
+ /* TODO Free all rules */
+ facemgr_cfg_rule_set_free(cfg->rule_set);
+ return facemgr_cfg_override_finalize(&cfg->global);
+}
+
+void facemgr_cfg_dump(facemgr_cfg_t * cfg)
+{
+ return; /* NOT IMPLEMENTED */
+}
+
+/* General */
+int
+facemgr_cfg_set_face_type(facemgr_cfg_t * cfg, facemgr_face_type_t * face_type)
+{
+ cfg->global.is_face_type = true;
+ cfg->global.face_type = *face_type;
+ return 0;
+}
+
+int
+facemgr_cfg_unset_face_type(facemgr_cfg_t * cfg)
+{
+ cfg->global.is_face_type = false;
+ cfg->global.face_type = FACEMGR_FACE_TYPE_UNDEFINED; /* optional */
+ return 0;
+}
+
+int
+facemgr_cfg_set_discovery(facemgr_cfg_t * cfg, bool status)
+{
+ cfg->global.is_discovery = true;
+ cfg->global.discovery = status;
+ return 0;
+}
+
+int
+facemgr_cfg_unset_discovery(facemgr_cfg_t * cfg)
+{
+ cfg->global.is_discovery = false;
+ return 0;
+}
+
+int
+facemgr_cfg_set_overlay(facemgr_cfg_t * cfg, int family,
+ ip_address_t * local_addr, uint16_t local_port,
+ ip_address_t * remote_addr, uint16_t remote_port)
+{
+ if ((family != AF_INET) && (family != AF_INET6))
+ return -1;
+
+ facemgr_cfg_overlay_t * overlay = facemgr_cfg_overlay_create();
+ if (local_addr) {
+ overlay->is_local_addr = true;
+ overlay->local_addr = *local_addr;
+ }
+ if (IS_VALID_PORT(local_port)) {
+ overlay->is_local_port = true;
+ overlay->local_port = local_port;
+ }
+ if (remote_addr) {
+ overlay->is_remote_addr = true;
+ overlay->remote_addr = *remote_addr;
+ }
+ if (IS_VALID_PORT(remote_port)) {
+ overlay->is_remote_port = true;
+ overlay->remote_port = remote_port;
+ }
+
+ DEBUG("facemgr_cfg_set_overlay");
+
+ switch(family) {
+ case AF_INET:
+ cfg->global.overlays.v4 = overlay;
+ break;
+
+ case AF_INET6:
+ cfg->global.overlays.v6 = overlay;
+ break;
+
+ default:
+ return -1;
+ }
+
+ DEBUG("<global>");
+ DEBUG(" <overlay>");
+ if (overlay) {
+ DEBUG(" <ipv4>");
+ if (overlay->is_local_addr) {
+ char buf[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
+ &overlay->local_addr, AF_INET);
+ DEBUG(" <local_addr>%s</local_addr>", buf);
+ }
+ if (overlay->is_local_port) {
+ DEBUG(" <local_port>%d</local_port>",
+ overlay->local_port);
+ }
+ if (overlay->is_remote_addr) {
+ char buf[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
+ &overlay->remote_addr, AF_INET);
+ DEBUG(" <remote_addr>%s</remote_addr>", buf);
+ }
+ if (overlay->is_remote_port) {
+ DEBUG(" <remote_port>%d</remote_port>",
+ overlay->remote_port);
+ }
+ DEBUG(" </ipv4>");
+ }
+ DEBUG(" </overlay>");
+ DEBUG("</global>");
+
+ return 0;
+}
+
+int
+facemgr_cfg_unset_overlay(facemgr_cfg_t * cfg, int family)
+{
+ if ((family != AF_INET) && (family != AF_INET6) && (family != AF_UNSPEC))
+ return -1;
+
+ if ((family == AF_UNSPEC) || (family == AF_INET)) {
+ if (cfg->global.overlays.v4) {
+ facemgr_cfg_overlay_free(cfg->global.overlays.v4);
+ cfg->global.overlays.v4 = NULL;
+ }
+ }
+ if ((family == AF_UNSPEC) || (family == AF_INET6)) {
+ if (cfg->global.overlays.v6) {
+ facemgr_cfg_overlay_free(cfg->global.overlays.v6);
+ cfg->global.overlays.v6 = NULL;
+ }
+ }
+ return 0;
+}
+
+int
+facemgr_cfg_add_rule(facemgr_cfg_t * cfg, facemgr_cfg_rule_t * rule)
+{
+ facemgr_cfg_rule_dump(rule);
+ return facemgr_cfg_rule_set_add(cfg->rule_set, rule);
+}
+
+int
+facemgr_cfg_del_rule(facemgr_cfg_t * cfg, facemgr_cfg_rule_t * rule)
+{
+ return facemgr_cfg_rule_set_remove(cfg->rule_set, rule, NULL);
+}
+
+int facemgr_cfg_get_rule(const facemgr_cfg_t * cfg, const char * interface_name,
+ netdevice_type_t interface_type, facemgr_cfg_rule_t ** rule) {
+ facemgr_cfg_rule_t rule_search = {
+ .match = {
+ .interface_name = interface_name,
+ .interface_type = interface_type,
+ },
+ };
+ return facemgr_cfg_rule_set_get(cfg->rule_set, &rule_search, rule);
+}
+
+/* Query API */
+
+/*
+ * Check whether there are override rules for the given netdevice
+ *
+ * TODO:
+ * - until we have proper indexes we loop through the whole structure
+ */
+int
+facemgr_cfg_get_override(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ facemgr_cfg_override_t ** override)
+{
+ if (!netdevice) {
+ *override = NULL;
+ return 0;
+ }
+
+ facemgr_cfg_rule_t **rule_array;
+ int rc = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array);
+ if (rc < 0) {
+ ERROR("facemgr_cfg_rule_set_get_array failed");
+ return rc;
+ }
+ for (unsigned i = 0; i < rc; i++) {
+ const char * interface_name = rule_array[i]->match.interface_name;
+ /* Check match for interface name */
+ if (interface_name && (strcmp(interface_name, netdevice->name) != 0))
+ continue;
+ /* Check match for interface type */
+ if (rule_array[i]->match.interface_type != NETDEVICE_TYPE_UNDEFINED) {
+#ifdef __ANDROID__
+ if (netdevice_type != rule_array[i]->match.interface_type)
+ continue;
+#else
+ ERROR("Match on interface type is currently not implemented");
+ goto ERR_ARRAY;
+#endif /* __ANDROID__ */
+ }
+ /* Found match... do we have an override for face_type */
+ DEBUG("override found nd=%s, ndt=%s", rule_array[i]->match.interface_name, netdevice_type_str[rule_array[i]->match.interface_type]);
+ *override = &rule_array[i]->override;
+ goto FOUND;
+ }
+
+ DEBUG("override not found");
+ *override = NULL;
+
+FOUND:
+ free(rule_array);
+ return 0;
+
+#ifndef __ANDROID__
+ERR_ARRAY:
+ free(rule_array);
+ return -1;
+#endif /* __ANDROID__ */
+}
+
+int
+facemgr_cfg_get_face_type(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ facemgr_face_type_t * face_type)
+{
+ facemgr_cfg_override_t * override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
+ &override);
+ if (rc < 0) {
+ ERROR("get override failed");
+ return rc;
+ }
+
+ if ((override) && (override->is_face_type)) {
+ *face_type = override->face_type;
+ return 0;
+ }
+
+ *face_type = cfg->global.is_face_type
+ ? cfg->global.face_type
+ : FACEMGR_FACE_TYPE_DEFAULT;
+
+ return 0;
+}
+
+int
+facemgr_cfg_get_discovery(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ bool * discovery)
+{
+ facemgr_cfg_override_t * override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
+ &override);
+ if (rc < 0)
+ return rc;
+
+ if ((override) && (override->is_discovery)) {
+ *discovery = override->discovery;
+ return 0;
+ }
+
+ *discovery = cfg->global.is_discovery
+ ? cfg->global.discovery
+ : FACEMGR_CFG_DEFAULT_DISCOVERY;
+ return 0;
+}
+
+int
+facemgr_cfg_get_ipv4(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ bool * ipv4)
+{
+ facemgr_cfg_override_t * override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
+ &override);
+ if (rc < 0)
+ return rc;
+
+ if ((override) && (override->is_ipv4)) {
+ *ipv4 = override->ipv4;
+ return 0;
+ }
+
+ *ipv4 = cfg->global.is_ipv4
+ ? cfg->global.ipv4
+ : FACEMGR_CFG_DEFAULT_IPV4;
+ return 0;
+}
+
+int
+facemgr_cfg_get_ipv6(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ bool * ipv6)
+{
+ facemgr_cfg_override_t * override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
+ &override);
+ if (rc < 0)
+ return rc;
+
+ if ((override) && (override->is_ipv6)) {
+ *ipv6 = override->ipv6;
+ return 0;
+ }
+
+ *ipv6 = cfg->global.is_ipv6
+ ? cfg->global.ipv6
+ : FACEMGR_CFG_DEFAULT_IPV6;
+ return 0;
+}
+
+int
+facemgr_cfg_get_ignore(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ bool * ignore)
+{
+ facemgr_cfg_override_t * override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
+ &override);
+ if (rc < 0)
+ return rc;
+
+ if ((override) && (override->is_ignore)) {
+ *ignore = override->ignore;
+ return 0;
+ }
+
+ assert (!cfg->global.is_ignore);
+
+ *ignore = (netdevice && (netdevice->name[0] != '\0') && strcmp(netdevice->name, "lo") == 0);
+
+ return 0;
+}
+
+int
+facemgr_cfg_get_overlay_local_addr(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ int family, ip_address_t * addr)
+{
+ facemgr_cfg_override_t * override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
+ &override);
+ if (rc < 0)
+ return rc;
+
+ switch (family) {
+ case AF_INET:
+ if ((override) && (override->overlays.v4) && (override->overlays.v4->is_local_addr)) {
+ *addr = override->overlays.v4->local_addr;
+ return 0;
+ }
+ if ((cfg->global.overlays.v4) && (cfg->global.overlays.v4->is_local_addr)) {
+ *addr = cfg->global.overlays.v4->local_addr;
+ return 0;
+ }
+ break;
+ case AF_INET6:
+ if ((override) && (override->overlays.v6) && (override->overlays.v6->is_local_addr)) {
+ *addr = override->overlays.v6->local_addr;
+ return 0;
+ }
+ if ((cfg->global.overlays.v6) && (cfg->global.overlays.v6->is_local_addr)) {
+ *addr = cfg->global.overlays.v6->local_addr;
+ return 0;
+ }
+ break;
+ case AF_UNSPEC:
+ break;
+ default:
+ return -1;
+ }
+
+ *addr = IP_ADDRESS_EMPTY;
+ return 0;
+}
+
+int
+facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ int family, u16 * port)
+{
+ facemgr_cfg_override_t * override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
+ &override);
+ if (rc < 0)
+ return rc;
+
+ switch (family) {
+ case AF_INET:
+ if ((override) && (override->overlays.v4) && (override->overlays.v4->is_local_port)) {
+ *port = override->overlays.v4->local_port;
+ return 0;
+ }
+ if ((cfg->global.overlays.v4) && (cfg->global.overlays.v4->is_local_port)) {
+ *port = cfg->global.overlays.v4->local_port;
+ return 0;
+ }
+ break;
+ case AF_INET6:
+ if ((override) && (override->overlays.v6) && (override->overlays.v6->is_local_port)) {
+ *port = override->overlays.v6->local_port;
+ return 0;
+ }
+ if ((cfg->global.overlays.v6) && (cfg->global.overlays.v6->is_local_port)) {
+ *port = cfg->global.overlays.v6->local_port;
+ return 0;
+ }
+ break;
+ case AF_UNSPEC:
+ break;
+ default:
+ return -1;
+ }
+
+ *port = HICN_DEFAULT_PORT;
+ return 0;
+}
+
+int
+facemgr_cfg_get_overlay_remote_addr(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ int family, ip_address_t * addr)
+{
+ facemgr_cfg_override_t * override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
+ &override);
+ if (rc < 0)
+ return rc;
+
+ switch (family) {
+ case AF_INET:
+ if ((override) && (override->overlays.v4) && (override->overlays.v4->is_remote_addr)) {
+ DEBUG("remote addr v4 from override");
+ *addr = override->overlays.v4->remote_addr;
+ return 0;
+ }
+ if ((cfg->global.overlays.v4) && (cfg->global.overlays.v4->is_remote_addr)) {
+ DEBUG("remote addr v4 from global");
+ *addr = cfg->global.overlays.v4->remote_addr;
+ return 0;
+ }
+ break;
+ case AF_INET6:
+ if ((override) && (override->overlays.v6) && (override->overlays.v6->is_remote_addr)) {
+ DEBUG("remote addr v6 from override");
+ *addr = override->overlays.v6->remote_addr;
+ return 0;
+ }
+ if ((cfg->global.overlays.v6) && (cfg->global.overlays.v6->is_remote_addr)) {
+ DEBUG("remote addr v6 from global");
+ *addr = cfg->global.overlays.v6->remote_addr;
+ return 0;
+ }
+ break;
+ case AF_UNSPEC:
+ break;
+ default:
+ return -1;
+ }
+
+ DEBUG("remote addr empty");
+ *addr = IP_ADDRESS_EMPTY;
+ return 0;
+}
+
+int
+facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t * cfg,
+ const netdevice_t * netdevice, netdevice_type_t netdevice_type,
+ int family, u16 * port)
+{
+ facemgr_cfg_override_t * override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
+ &override);
+ if (rc < 0)
+ return rc;
+
+ switch (family) {
+ case AF_INET:
+ if ((override) && (override->overlays.v4) && (override->overlays.v4->is_remote_port)) {
+ *port = override->overlays.v4->remote_port;
+ return 0;
+ }
+ if ((cfg->global.overlays.v4) && (cfg->global.overlays.v4->is_remote_port)) {
+ *port = cfg->global.overlays.v4->remote_port;
+ return 0;
+ }
+ break;
+ case AF_INET6:
+ if ((override) && (override->overlays.v6) && (override->overlays.v6->is_remote_port)) {
+ *port = override->overlays.v6->remote_port;
+ return 0;
+ }
+ if ((cfg->global.overlays.v6) && (cfg->global.overlays.v6->is_remote_port)) {
+ *port = cfg->global.overlays.v6->remote_port;
+ return 0;
+ }
+ break;
+ case AF_UNSPEC:
+ break;
+ default:
+ return -1;
+ }
+
+ *port = HICN_DEFAULT_PORT;
+ return 0;
+}
diff --git a/ctrl/facemgr/src/common.h b/ctrl/facemgr/src/common.h
index a73964b6d..9d6e8ca87 100644
--- a/ctrl/facemgr/src/common.h
+++ b/ctrl/facemgr/src/common.h
@@ -22,18 +22,12 @@
#include <stdbool.h>
#include <stdint.h>
+#include <stdlib.h>
-#include "util/types.h"
-#include "util/ip_address.h"
-#include "util/token.h" // XXX debug
+#include <hicn/util/ip_address.h>
//#define DEBUG
-/* Return value conventions */
-#define FACEMGR_SUCCESS 0
-#define FACEMGR_FAILURE -1
-#define FACEMGR_IS_ERROR(rc) (rc < 0)
-
/* Useful types and macros for comparisons */
typedef int(*cmp_t)(const void * x, const void * y);
@@ -43,18 +37,35 @@ typedef int(*cmp_t)(const void * x, const void * y);
#define INDENT(n, fmt) "%*s" fmt, n, ""
#define printfi(n, fmt, ...) printf(INDENT(n*4, fmt), ##__VA_ARGS__)
+#define _unused(x) ((void)(x))
+
+/* Random strings */
+
+static inline
+void rand_str(char *dest, size_t length) {
+ char charset[] = "0123456789"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ while (length-- > 0) {
+ size_t index = (double) rand() / RAND_MAX * (sizeof charset - 1);
+ *dest++ = charset[index];
+ }
+ *dest = '\0';
+}
+
/* Boilerplate code */
#define NO_INITIALIZE(NAME) \
int \
NAME ## _initialize(NAME ## _t * obj) { \
- return FACEMGR_SUCCESS; \
+ return 0; \
}
#define NO_FINALIZE(NAME) \
int \
NAME ## _finalize(NAME ## _t * obj) { \
- return FACEMGR_SUCCESS; \
+ return 0; \
}
#define AUTOGENERATE_CREATE_FREE(NAME) \
@@ -66,7 +77,7 @@ NAME ## _create() \
if (!obj) \
goto ERR_MALLOC; \
\
- if (FACEMGR_IS_ERROR(NAME ## _initialize(obj))) \
+ if (NAME ## _initialize(obj) < 0) \
goto ERR_INIT; \
\
return obj; \
@@ -80,7 +91,7 @@ ERR_MALLOC: \
void \
NAME ## _free(NAME ## _t * obj) \
{ \
- if (FACEMGR_IS_ERROR(NAME ## _finalize(obj))) \
+ if (NAME ## _finalize(obj) < 0) \
(void)0; /* XXX */ \
free(obj); \
} \
diff --git a/ctrl/facemgr/src/event.c b/ctrl/facemgr/src/event.c
deleted file mode 100644
index 446c51c22..000000000
--- a/ctrl/facemgr/src/event.c
+++ /dev/null
@@ -1,39 +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 event.h
- * \brief Implementatino of face events
- */
-
-#include "common.h"
-#include "event.h"
-#include "interface.h"
-#include "util/token.h"
-
-const char * event_type_str[] = {
-#define _(x) [EVENT_TYPE_ ## x] = STRINGIZE(x),
-foreach_event_type
-#undef _
-};
-
-int
-event_raise(event_type_t type, const face_t * face, const interface_t * interface)
-{
- event_t event = { .type = type, .face = face };
- if (interface->callback)
- interface->callback(interface->callback_data, &event);
- return FACEMGR_SUCCESS;
-}
diff --git a/ctrl/facemgr/src/event.h b/ctrl/facemgr/src/event.h
deleted file mode 100644
index 53295d009..000000000
--- a/ctrl/facemgr/src/event.h
+++ /dev/null
@@ -1,59 +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 event.h
- * \brief Face event
- */
-#ifndef FACEMGR_EVENT_H
-#define FACEMGR_EVENT_H
-
-#include "face.h"
-#include "interface.h"
-
-#define foreach_event_type \
- _(UNDEFINED) \
- _(CREATE) \
- _(UPDATE) \
- _(DELETE) \
- _(SET_PARAMS) \
- _(SET_UP) \
- _(SET_DOWN) \
- _(SET_TAGS) \
- _(CLEAR_TAGS) \
- _(ADD_TAG) \
- _(REMOVE_TAG) \
- _(N)
-
-#define MAXSZ_EVENT_TYPE_ 10
-#define MAXSZ_EVENT_TYPE MAXSZ_EVENT_TYPE_ + 1
-
-typedef enum {
-#define _(x) EVENT_TYPE_ ## x,
-foreach_event_type
-#undef _
-} event_type_t;
-
-extern const char * event_type_str[];
-
-typedef struct event_s {
- event_type_t type;
- const face_t * face; /* + bitfield for face fields ? */
-} event_t;
-
-int
-event_raise(event_type_t type, const face_t * face, const interface_t * interface);
-
-#endif /* FACEMGR_EVENT_H */
diff --git a/ctrl/facemgr/src/face.c b/ctrl/facemgr/src/face.c
deleted file mode 100644
index 270a6fa9f..000000000
--- a/ctrl/facemgr/src/face.c
+++ /dev/null
@@ -1,262 +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 face.c
- * \brief Implementation of face abstraction
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "face.h"
-#include "util/hash.h"
-#include "util/token.h"
-
-#ifndef bzero
-#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
-#endif
-
-#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 _
-};
-
-
-/* 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 */
-
-int
-face_initialize(face_t * face)
-{
- bzero(face, sizeof(face_t)); /* 0'ed for hash */
- return 1;
-}
-
-int
-face_initialize_udp(face_t * face, const ip_address_t * local_addr,
- u16 local_port, const ip_address_t * remote_addr, u16 remote_port,
- int family)
-{
- if (!local_addr)
- return -1;
-
- *face = (face_t) {
- .type = FACE_TYPE_UDP,
- .params.tunnel = {
- .family = family,
- .local_addr = *local_addr,
- .local_port = local_port,
- .remote_addr = remote_addr ? *remote_addr : IP_ADDRESS_EMPTY,
- .remote_port = remote_port,
- },
- };
- return 1;
-}
-
-int
-face_initialize_udp_sa(face_t * face, 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,
- .params.tunnel = {
- .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->params.tunnel.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,
- .params.tunnel = {
- .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->params.tunnel.remote_addr.v6.as_in6addr = rsai->sin6_addr;
- }
- break;
- default:
- return -1;
- }
- 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 ip_address_t * local_addr, u16 local_port,
- const ip_address_t * remote_addr, u16 remote_port, int family)
-{
- face_t * face = face_create();
- if (face_initialize_udp(face, 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 struct sockaddr * local_addr,
- const struct sockaddr * remote_addr)
-{
- face_t * face = face_create();
- if (face_initialize_udp_sa(face, local_addr, remote_addr) < 0)
- goto ERR_INIT;
- return face;
-
-ERR_INIT:
- free(face);
- return NULL;
-}
-
-void face_free(face_t * face)
-{
- free(face);
-}
-
-#define face_param_cmp(f1, f2, face_param_type) \
- memcmp(&f1->type, &f2->type, \
- member_size(face_params_t, face_param_type));
-
-/**
- * \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)
-{
- if (f1->type != f2->type)
- return false;
-
- switch(f1->type) {
- case FACE_TYPE_HICN:
- return face_param_cmp(f1, f2, hicn);
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- return face_param_cmp(f1, f2, tunnel);
- default:
- return false;
- }
-}
-
-hash_t
-face_hash(const face_t * face)
-{
- /* Assuming the unused part of the struct is set to zero */
- return hash_struct(face);
-}
-
-/* /!\ Please update constants in header file upon changes */
-size_t
-face_snprintf(char * s, size_t size, const face_t * face)
-{
- switch(face->type) {
- case FACE_TYPE_HICN:
- return 0; // XXX Not implemented
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- {
- char local[MAXSZ_IP_ADDRESS];
- char remote[MAXSZ_IP_ADDRESS];
- char tags[MAXSZ_POLICY_TAGS];
-
- ip_address_snprintf(local, MAXSZ_IP_ADDRESS,
- &face->params.tunnel.local_addr,
- face->params.tunnel.family);
- ip_address_snprintf(remote, MAXSZ_IP_ADDRESS,
- &face->params.tunnel.remote_addr,
- face->params.tunnel.family);
- policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->tags);
-
- return snprintf(s, size, "%s [%s:%d -> %s:%d] [%s]",
- face_type_str[face->type],
- local,
- face->params.tunnel.local_port,
- remote,
- face->params.tunnel.remote_port,
- tags);
- }
- break;
- default:
- return 0;
- }
-
-}
-
-int
-face_set_tags(face_t * face, policy_tags_t tags)
-{
- face->tags = tags;
- return 1;
-}
diff --git a/ctrl/facemgr/src/face.h b/ctrl/facemgr/src/face.h
deleted file mode 100644
index 8b553f685..000000000
--- a/ctrl/facemgr/src/face.h
+++ /dev/null
@@ -1,177 +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 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 "util/ip_address.h"
-#include "util/policy.h"
-#include "util/types.h"
-
-
-/* Netdevice type */
-
-#include <net/if.h> // IFNAMSIZ
-
-#define foreach_netdevice_type \
- _(UNDEFINED) \
- _(WIRED) \
- _(WIFI) \
- _(CELLULAR) \
- _(VPN) \
- _(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;
-
-extern const char * netdevice_type_str[];
-
-
-/* Netdevice */
-
-typedef struct {
- u32 index;
- char name[IFNAMSIZ];
-} netdevice_t;
-
-#define NETDEVICE_UNDEFINED_INDEX 0
-
-/* Face state */
-
-#define foreach_face_state \
- _(UNDEFINED) \
- _(PENDING_UP) \
- _(UP) \
- _(PENDING_DOWN) \
- _(DOWN) \
- _(ERROR) \
- _(N)
-
-#define MAXSZ_FACE_STATE_ 12
-#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[];
-
-
-/* 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;
-
-extern const char * face_type_str[];
-
-#define MAXSZ_FACE_ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_IP_ADDRESS_ + 2 * MAXSZ_PORT_ + 9 + MAXSZ_POLICY_TAGS_
-#define MAXSZ_FACE MAXSZ_FACE_ + 1
-
-/* Face */
-
-typedef union {
- int family; /* To access family independently of face type */
- struct {
- int family;
- netdevice_t netdevice;
- ip_address_t local_addr;
- ip_address_t remote_addr;
- } hicn;
- struct {
- int family;
- ip_address_t local_addr;
- u16 local_port;
- ip_address_t remote_addr;
- u16 remote_port;
- } tunnel;
-} face_params_t;
-
-typedef struct {
- face_type_t type;
- face_params_t params;
- face_state_t admin_state;
- face_state_t state;
-#ifdef WITH_POLICY
- policy_tags_t tags; /**< \see policy_tag_t */
-#endif /* WITH_POLICY */
-} face_t;
-
-int face_initialize(face_t * face);
-int face_initialize_udp(face_t * face, const ip_address_t * local_addr,
- u16 local_port, const ip_address_t * remote_addr, u16 remote_port,
- int family);
-int face_initialize_udp_sa(face_t * face,
- const struct sockaddr * local_addr, const struct sockaddr * remote_addr);
-
-face_t * face_create();
-face_t * face_create_udp(const ip_address_t * local_addr, u16 local_port,
- const ip_address_t * remote_addr, u16 remote_port, int family);
-face_t * face_create_udp_sa(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);
-hash_t face_hash(const face_t * face);
-
-size_t
-face_snprintf(char * s, size_t size, const face_t * face);
-
-int face_set_tags(face_t * face, policy_tags_t tags);
-
-#endif /* HICN_FACE_H */
-
diff --git a/ctrl/facemgr/src/face_cache.h b/ctrl/facemgr/src/face_cache.h
deleted file mode 100644
index caefb7e22..000000000
--- a/ctrl/facemgr/src/face_cache.h
+++ /dev/null
@@ -1,24 +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.
- */
-
-#ifndef FACE_CACHE_H
-#define FACE_CACHE_H
-
-#include "face.h"
-#include "util/set.h"
-
-TYPEDEF_SET_H(face_cache, face_t *);
-
-#endif /* FACE_CACHE_H */
diff --git a/ctrl/facemgr/src/face_rules.c b/ctrl/facemgr/src/face_rules.c
deleted file mode 100644
index ddefc15f9..000000000
--- a/ctrl/facemgr/src/face_rules.c
+++ /dev/null
@@ -1,21 +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.
- */
-
-#include "face_rules.h"
-
-#include <string.h>
-#include "util/policy.h"
-
-TYPEDEF_MAP(face_rules, const char *, policy_tags_t, strcmp, string_snprintf, policy_tags_snprintf);
diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c
new file mode 100644
index 000000000..8a3074d2a
--- /dev/null
+++ b/ctrl/facemgr/src/facelet.c
@@ -0,0 +1,1008 @@
+/*
+ * 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 facelet.c
+ * \brief Implementation of facelet
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <hicn/ctrl/face.h>
+#include <hicn/facemgr/cfg.h>
+#include <hicn/util/log.h>
+
+#include "facelet.h"
+
+const char * face_type_layer_str[] = {
+#define _(x) [FACE_TYPE_LAYER_ ## x] = STRINGIZE(x),
+ foreach_face_type_layer
+#undef _
+};
+
+const char * face_type_encap_str[] = {
+#define _(x) [FACE_TYPE_ENCAP_ ## x] = STRINGIZE(x),
+ foreach_face_type_encap
+#undef _
+};
+
+#define FACEMGR_FACE_TYPE_STR(x) \
+ face_type_layer_str[x.layer], face_type_encap_str[x.encap]
+
+
+const char * facelet_status_str[] = {
+#define _(x) [FACELET_STATUS_ ## x] = STRINGIZE(x),
+ foreach_facelet_status
+#undef _
+};
+
+/* Facelet attribute status */
+
+
+const char * facelet_attr_status_str[] = {
+#define _(x, str) [FACELET_ATTR_STATUS_ ## x] = STRINGIZE(x),
+ foreach_facelet_attr_status
+#undef _
+};
+
+const char * facelet_attr_status_str_short[] = {
+#define _(x, str) [FACELET_ATTR_STATUS_ ## x] = STRINGIZE(str),
+ foreach_facelet_attr_status
+#undef _
+};
+
+
+/* Facelet */
+
+struct facelet_s {
+#define _(TYPE, NAME) TYPE NAME;
+ foreach_facelet_attr
+#undef _
+#define _(TYPE, NAME) facelet_attr_status_t NAME ## _status;
+ foreach_facelet_attr
+#undef _
+
+ facelet_status_t status;
+ facelet_event_t event;
+
+ /* Joins */
+ bool bj_done;
+ bool au_done;
+ int num_pending;
+};
+
+const char * facelet_event_str[] = {
+#define _(x) [FACELET_EVENT_ ## x] = STRINGIZE(x),
+foreach_facelet_event
+#undef _
+};
+
+facelet_t *
+facelet_create()
+{
+ facelet_t * facelet = calloc(1, sizeof(facelet_t));
+ if (!facelet)
+ goto ERR_MALLOC;
+
+ facelet->netdevice_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->netdevice_type_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->family_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->local_port_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->state_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->face_type_status = FACELET_ATTR_STATUS_UNSET;
+
+ facelet->status = FACELET_STATUS_NEW;
+
+ facelet->bj_done = false;
+ facelet->au_done = false;
+ facelet->num_pending = 0;
+
+ facelet->event = FACELET_EVENT_UNDEFINED;
+
+ return facelet;
+
+ERR_MALLOC:
+ return NULL;
+}
+
+facelet_t *
+facelet_create_from_netdevice(netdevice_t * netdevice)
+{
+ facelet_t * facelet = facelet_create();
+ if (!facelet)
+ goto ERR_FACELET;
+
+ int rc = facelet_set_netdevice(facelet, *netdevice);
+ if (rc < 0)
+ goto ERR_NETDEV;
+
+ return facelet;
+
+ERR_NETDEV:
+ facelet_free(facelet);
+ERR_FACELET:
+ return NULL;
+}
+
+/**
+ * \brief Validate whether the facelet has all required fields to construct a
+ * face of the given type
+ * \param [in) facelet - Pointer to the facelet to verify
+ * \return 0 in case of success, -1 otherwise
+ */
+int
+facelet_validate_face(const facelet_t * facelet)
+{
+ if (!facelet_has_face_type(facelet))
+ return false;
+ switch(facelet->face_type.layer) {
+ case FACE_TYPE_LAYER_4:
+ if (!facelet_has_remote_port(facelet))
+ return false;
+ if (!facelet_has_remote_addr(facelet))
+ return false;
+ case FACE_TYPE_LAYER_3:
+ if (!facelet_has_local_addr(facelet))
+ return false;
+ if (!facelet_has_netdevice(facelet))
+ return false;
+ return true;
+
+ default:
+ return false; /* Error */
+ }
+ // FIXME Not implemented
+ return 0;
+}
+
+
+netdevice_type_t
+netdevice_type_from_face_tags(const face_t * face)
+{
+ policy_tags_t tags = face->tags;
+ if (policy_tags_has(tags, POLICY_TAG_WIRED))
+ return NETDEVICE_TYPE_WIRED;
+ else if (policy_tags_has(tags, POLICY_TAG_WIFI))
+ return NETDEVICE_TYPE_WIFI;
+ else if (policy_tags_has(tags, POLICY_TAG_CELLULAR))
+ return NETDEVICE_TYPE_CELLULAR;
+ return NETDEVICE_TYPE_UNDEFINED;
+}
+
+facelet_t *
+facelet_create_from_face(face_t * face)
+{
+ facelet_t * facelet = malloc(sizeof(facelet_t));
+ if (!facelet)
+ goto ERR_MALLOC;
+
+ /* Go through the face attributes to update the local representation */
+
+ /* Attribute : netdevice */
+ /* NOTE index is not set */
+ if (IS_VALID_NETDEVICE(face->netdevice)) {
+ facelet->netdevice = face->netdevice;
+ facelet->netdevice_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->netdevice_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Attribute : netdevice_type */
+ facelet->netdevice_type = netdevice_type_from_face_tags(face);
+ if (facelet->netdevice_type != NETDEVICE_TYPE_UNDEFINED) {
+ facelet->netdevice_type_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->netdevice = NETDEVICE_EMPTY;
+ facelet->netdevice_type_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Attribute : family */
+ if (IS_VALID_FAMILY(face->family)) {
+ facelet->family = face->family;
+ facelet->family_status = FACELET_ATTR_STATUS_CLEAN;
+
+ /* Attribute : local_addr */
+ if (ip_address_cmp(&face->local_addr, &IP_ADDRESS_EMPTY, face->family) != 0) {
+ facelet->local_addr = face->local_addr;
+ facelet->local_addr_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Attribute : local_port */
+ if (IS_VALID_PORT(face->local_port)) {
+ facelet->local_port = face->local_port;
+ facelet->local_port_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->local_port_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Attribute : remote_addr */
+ if (ip_address_cmp(&face->remote_addr, &IP_ADDRESS_EMPTY, face->family) != 0) {
+ facelet->remote_addr = face->remote_addr;
+ facelet->remote_addr_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Attribute : remote_port */
+ if (IS_VALID_PORT(face->remote_port)) {
+ facelet->remote_port = face->remote_port;
+ facelet->remote_port_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ } else {
+ facelet->family_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->local_port_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Attribute : admin_state */
+ if ((face->admin_state == FACE_STATE_UP) ||
+ (face->admin_state == FACE_STATE_DOWN)) {
+ facelet->admin_state = face->admin_state;
+ facelet->admin_state_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Attribute : state */
+ if ((face->state == FACE_STATE_UP) ||
+ (face->state == FACE_STATE_DOWN)) {
+ facelet->state = face->state;
+ facelet->state_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->state_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Attribute : face_type */
+ if ((face->type != FACE_TYPE_UNDEFINED) && (face->type != FACE_TYPE_N)) {
+ switch(face->type) {
+ case FACE_TYPE_UDP:
+ facelet->face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+ break;
+ case FACE_TYPE_TCP:
+ facelet->face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
+ break;
+ case FACE_TYPE_HICN:
+ facelet->face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+ break;
+ default:
+ ERROR("[facelet_create_from_face] Face type not (yet) implemented");
+ goto ERR_FACE;
+ }
+ facelet->face_type_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->face_type_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Status */
+ facelet->status = FACELET_STATUS_CLEAN;
+
+ /* TODO Consistency check between face type and found attributes */
+ if (facelet_validate_face(facelet) < 0)
+ goto ERR_FACE;
+
+ facelet->bj_done = false;
+ facelet->au_done = false;
+ facelet->num_pending = 0;
+
+ facelet->event = FACELET_EVENT_UNDEFINED;
+
+ return facelet;
+
+ERR_FACE:
+ free(facelet);
+ERR_MALLOC:
+ return NULL;
+}
+
+
+void
+facelet_free(facelet_t * facelet)
+{
+ free(facelet);
+}
+
+facelet_t *
+facelet_dup(const facelet_t * current_facelet)
+{
+ facelet_t * facelet = facelet_create();
+ if (!facelet)
+ goto ERR_CREATE;
+
+#define _(TYPE, NAME) facelet-> NAME = current_facelet-> NAME;
+ foreach_facelet_attr
+#undef _
+#define _(TYPE, NAME) facelet-> NAME ## _status = current_facelet-> NAME ## _status;
+ foreach_facelet_attr
+#undef _
+
+ facelet->status = current_facelet->status;
+ facelet->event = current_facelet->event;
+
+ facelet->bj_done = current_facelet->bj_done;
+ facelet->au_done = current_facelet->au_done;
+ facelet->num_pending = current_facelet->num_pending;
+
+ return facelet;
+
+ERR_CREATE:
+ return NULL;
+}
+
+int
+facelet_cmp(const facelet_t * f1, const facelet_t * f2)
+{
+ /*
+ * Under the assumption we only create a face per physical interface, a
+ * facelet is uniquely identified by its netdevice attribute, and address
+ * family if any.
+ *
+ * This function is mostly used for lookups into the cache, and the face
+ * thus needs to have a netdevice associated, and optionally, an address
+ * family.
+ *
+ * For other situations, the `facelet_match` function is more appropriate.
+ */
+
+ if ((f1->netdevice_status != FACELET_ATTR_STATUS_UNSET) &&
+ (f2->netdevice_status != FACELET_ATTR_STATUS_UNSET)) {
+ int rc = netdevice_cmp(&f1->netdevice, &f2->netdevice);
+ if (rc != 0)
+ return rc;
+
+ } else {
+ /* Both unset : we might have the face without netdevice due to hicn
+ * light not returning it currently, but we cannot skip it in the match
+ * otherwise we cannot distinguish with other faces except matching on
+ * other fields which might unfortunately not be determined yet...
+ */
+ return (f1->netdevice_status == FACELET_ATTR_STATUS_UNSET) ? -1 : 1;
+ }
+
+ assert(f1->family_status != FACELET_ATTR_STATUS_UNSET);
+ assert(f2->family_status != FACELET_ATTR_STATUS_UNSET);
+
+ if ((f1->family == AF_UNSPEC) || (f2->family == AF_UNSPEC))
+ return 0;
+ int diff = f1->family - f2->family;
+ return (diff > 0) ? 1 :
+ (diff < 0) ? -1 : 0;
+}
+
+/*
+ * If the match has a field set, then the facelet only matches iif it has the
+ * same field set, and both values are equal
+ */
+#define MATCH_ATTRIBUTE(TYPE, NAME) \
+do { \
+ if (facelet_match->NAME ## _status == FACELET_ATTR_STATUS_CLEAN) { \
+ if (facelet_has_ ## NAME(facelet_match)) { \
+ TYPE NAME; \
+ TYPE NAME ## _match; \
+ if (!facelet_has_ ## NAME(facelet)) \
+ return false; \
+ if (facelet_get_ ## NAME (facelet, & NAME) < 0) \
+ return false; \
+ if (facelet_get_ ## NAME (facelet_match, & NAME ## _match) < 0) \
+ return false; \
+ if (memcmp(& NAME, & NAME ## _match, sizeof(NAME)) != 0) \
+ return false; \
+ } \
+ } \
+} while(0)
+
+/* facelet_match is the incoming one */
+bool
+facelet_match(const facelet_t * facelet, const facelet_t * facelet_match)
+{
+#define _(TYPE, NAME) MATCH_ATTRIBUTE(TYPE, NAME);
+ foreach_facelet_attr
+#undef _
+ return true;
+}
+
+bool facelet_has_key(const facelet_t * facelet) {
+ return (facelet_has_netdevice(facelet) && facelet_has_family(facelet));
+}
+
+/*
+ * Implementation note:
+ * - facelet_set_* is equivalent to merge with a CLEAN remote attribute
+ */
+#define FACELET_ACCESSORS(TYPE, NAME) \
+bool \
+facelet_has_ ## NAME(const facelet_t * facelet) \
+{ \
+ assert(facelet); \
+ assert(facelet->NAME ## _status != FACELET_ATTR_STATUS_UNDEFINED); \
+ assert(facelet->NAME ## _status != FACELET_ATTR_STATUS_N); \
+ return ((facelet-> NAME ## _status != FACELET_ATTR_STATUS_UNSET)); \
+} \
+ \
+facelet_attr_status_t \
+facelet_get_ ## NAME ## _status(const facelet_t * facelet) \
+{ \
+ return (facelet->NAME ## _status); \
+} \
+ \
+int \
+facelet_get_ ## NAME(const facelet_t * facelet, TYPE * NAME) \
+{ \
+ assert(facelet); \
+ if (!facelet_has_ ## NAME(facelet)) \
+ return -1; \
+ *NAME = facelet-> NAME; \
+ return 0; \
+} \
+ \
+int \
+facelet_set_local_ ## NAME(facelet_t * facelet, TYPE NAME) \
+{ \
+ assert(facelet); \
+ switch(facelet->NAME ## _status) { \
+ case FACELET_ATTR_STATUS_UNSET: \
+ case FACELET_ATTR_STATUS_CLEAN: \
+ case FACELET_ATTR_STATUS_DIRTY: \
+ case FACELET_ATTR_STATUS_PENDING: \
+ facelet-> NAME = NAME; \
+ facelet->NAME ## _status = FACELET_ATTR_STATUS_DIRTY; \
+ if (facelet->status == FACELET_STATUS_CLEAN) \
+ facelet->status = FACELET_STATUS_DIRTY; \
+ break; \
+ case FACELET_ATTR_STATUS_CONFLICT: \
+ break; \
+ case FACELET_ATTR_STATUS_UNDEFINED: \
+ case FACELET_ATTR_STATUS_N: \
+ ERROR("Unexpected attribute status value"); \
+ return -1; \
+ } \
+ return 0; \
+} \
+ \
+int \
+facelet_set_remote_ ## NAME(facelet_t * facelet, TYPE NAME) \
+{ \
+ assert(facelet); \
+ switch(facelet->NAME ## _status) { \
+ case FACELET_ATTR_STATUS_UNSET: \
+ facelet-> NAME = NAME; \
+ facelet->NAME ## _status = FACELET_ATTR_STATUS_CLEAN; \
+ break; \
+ case FACELET_ATTR_STATUS_CLEAN: \
+ facelet->NAME = NAME; \
+ break; \
+ case FACELET_ATTR_STATUS_DIRTY: \
+ ERROR("Discarded remote value for status reasons"); \
+ break; \
+ case FACELET_ATTR_STATUS_PENDING: \
+ ERROR("Received remote value on pending attribute"); \
+ facelet->NAME ## _status = FACELET_ATTR_STATUS_CONFLICT; \
+ if (facelet->status != FACELET_STATUS_CONFLICT) \
+ facelet->status = FACELET_STATUS_CONFLICT; \
+ break; \
+ case FACELET_ATTR_STATUS_CONFLICT: \
+ return -1; \
+ case FACELET_ATTR_STATUS_UNDEFINED: \
+ case FACELET_ATTR_STATUS_N: \
+ ERROR("Unexpected attribute status value"); \
+ return -1; \
+ } \
+ return 0; \
+} \
+ \
+int \
+facelet_set_ ## NAME(facelet_t * facelet, TYPE NAME) \
+{ \
+ return facelet_set_local_ ## NAME(facelet, NAME); \
+} \
+ \
+
+#define _(TYPE, NAME) FACELET_ACCESSORS(TYPE, NAME)
+foreach_facelet_attr
+#undef _
+
+/*
+ * This function is called for every facelet attribute. It is responsible for
+ * comparing both the current and new value, and set the attribute and facelet
+ * status appropriately.
+ */
+
+// FIXME CLEAN for key fields, dirty for fields to update.
+
+#define MERGE_ATTRIBUTE(TYPE, NAME) \
+do { \
+ switch(facelet_to_merge->NAME ## _status) { \
+ case FACELET_ATTR_STATUS_UNDEFINED: \
+ case FACELET_ATTR_STATUS_N: \
+ case FACELET_ATTR_STATUS_PENDING: \
+ case FACELET_ATTR_STATUS_CONFLICT: \
+ ERROR("Unexpected facelet attribute status"); \
+ return -1; \
+ case FACELET_ATTR_STATUS_UNSET: \
+ break; \
+ case FACELET_ATTR_STATUS_CLEAN: \
+ case FACELET_ATTR_STATUS_DIRTY: \
+ facelet_set_ ## NAME(facelet, facelet_to_merge-> NAME); \
+ break; \
+ } \
+} while (0)
+
+int facelet_merge(facelet_t * facelet, const facelet_t * facelet_to_merge)
+{
+ assert(facelet && facelet_to_merge);
+#define _(TYPE, NAME) MERGE_ATTRIBUTE(TYPE, NAME);
+ foreach_facelet_attr
+#undef _
+ facelet->event = facelet_to_merge->event;
+ return 0;
+}
+
+#define MERGE_ATTRIBUTE_REMOTE(TYPE, NAME) \
+do { \
+ switch(facelet_to_merge->NAME ## _status) { \
+ case FACELET_ATTR_STATUS_UNDEFINED: \
+ case FACELET_ATTR_STATUS_N: \
+ case FACELET_ATTR_STATUS_DIRTY: \
+ case FACELET_ATTR_STATUS_PENDING: \
+ case FACELET_ATTR_STATUS_CONFLICT: \
+ ERROR("Unexpected facelet attribute status"); \
+ return -1; \
+ case FACELET_ATTR_STATUS_UNSET: \
+ break; \
+ case FACELET_ATTR_STATUS_CLEAN: \
+ facelet_set_ ## NAME(facelet, facelet_to_merge-> NAME); \
+ break; \
+ \
+ } \
+} while (0)
+
+int facelet_merge_remote(facelet_t * facelet, const facelet_t * facelet_to_merge)
+{
+ assert(facelet && facelet_to_merge);
+#define _(TYPE, NAME) MERGE_ATTRIBUTE_REMOTE(TYPE, NAME);
+ foreach_facelet_attr
+#undef _
+ facelet->event = facelet_to_merge->event;
+ return 0;
+}
+
+int
+facelet_get_face(const facelet_t * facelet, face_t ** pface)
+{
+ assert(pface);
+
+ /* Facelet has all the required information to create a face */
+ if (facelet_validate_face(facelet) < 0)
+ return 0;
+
+ face_t * face = face_create();
+ if (!face)
+ goto ERR_CREATE;
+
+ assert(facelet_has_netdevice(facelet));
+ face->netdevice = facelet->netdevice;
+
+ /* Face type */
+ switch(facelet->face_type.layer) {
+ case FACE_TYPE_LAYER_4:
+ switch(facelet->face_type.encap) {
+ case FACE_TYPE_ENCAP_UDP:
+ face->type = FACE_TYPE_UDP;
+ break;
+ case FACE_TYPE_ENCAP_TCP:
+ face->type = FACE_TYPE_TCP;
+ break;
+ case FACE_TYPE_ENCAP_UNDEFINED:
+ case FACE_TYPE_ENCAP_N:
+ ERROR("[facelet_get_face] Unsupported face encapsulation");
+ goto ERR;
+ }
+
+ if (facelet_get_family(facelet, &face->family) < 0)
+ goto ERR;
+ if (facelet_get_local_addr(facelet, &face->local_addr) < 0)
+ goto ERR;
+ if (facelet_get_local_port(facelet, &face->local_port) < 0)
+ goto ERR;
+ if (facelet_get_remote_addr(facelet, &face->remote_addr) < 0)
+ goto ERR;
+ if (facelet_get_remote_port(facelet, &face->remote_port) < 0)
+ goto ERR;
+ break;
+
+ case FACE_TYPE_LAYER_3:
+ ERROR("{facelet_get_face] hICN face not (yet) implemented");
+ goto ERR;
+
+ case FACE_TYPE_LAYER_UNDEFINED:
+ case FACE_TYPE_LAYER_N:
+ ERROR("[facelet_get_face] Unsupported face type");
+ goto ERR;
+ }
+
+ if (facelet_has_admin_state(facelet)) {
+ if (facelet_get_admin_state(facelet, &face->admin_state) < 0)
+ goto ERR;
+ } else {
+ face->admin_state = FACE_STATE_UP;
+ }
+
+ if (facelet_has_state(facelet)) {
+ if (facelet_get_state(facelet, &face->state) < 0)
+ goto ERR;
+ } else {
+ face->state = FACE_STATE_UP;
+ }
+
+ /* Tags */
+
+ /* - based on netdevice type */
+ policy_tags_t tags = POLICY_TAGS_EMPTY;
+ if (facelet_has_netdevice_type(facelet)) {
+ netdevice_type_t netdevice_type;
+ if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
+ ERROR("error getting netdevice_type");
+ goto ERR;
+ }
+
+
+ switch(netdevice_type) {
+ case NETDEVICE_TYPE_UNDEFINED:
+ case NETDEVICE_TYPE_LOOPBACK:
+ break;
+ case NETDEVICE_TYPE_WIRED:
+ policy_tags_add(&tags, POLICY_TAG_WIRED);
+ break;
+ case NETDEVICE_TYPE_WIFI:
+ policy_tags_add(&tags, POLICY_TAG_WIFI);
+ break;
+ case NETDEVICE_TYPE_CELLULAR:
+ policy_tags_add(&tags, POLICY_TAG_CELLULAR);
+ break;
+ default:
+ goto ERR;
+ }
+ }
+#ifdef __linux__
+#ifndef __ANDROID__
+ else {
+ /*
+ * Heuristics to determine face type based on name, until a better
+ * solution is found
+ */
+ if (strncmp(facelet->netdevice.name, "eth", 3) == 0) {
+ policy_tags_add(&tags, POLICY_TAG_WIRED);
+ goto DONE;
+ }
+ if (strncmp(facelet->netdevice.name, "en", 2) == 0) {
+ policy_tags_add(&tags, POLICY_TAG_WIRED);
+ goto DONE;
+ }
+ if (strncmp(facelet->netdevice.name, "wl", 2) == 0) {
+ /* wlan* wlp* wlx* */
+ policy_tags_add(&tags, POLICY_TAG_WIFI);
+ goto DONE;
+ }
+
+DONE:
+ ;
+ }
+#endif /* ! __ANDROID__ */
+#endif /* __linux__ */
+ face->tags = tags;
+
+ *pface = face;
+
+ return 0;
+
+ERR:
+ free(face);
+ERR_CREATE:
+ *pface = NULL;
+ return -1;
+}
+
+facelet_status_t
+facelet_get_status(const facelet_t * facelet)
+{
+ return facelet->status;
+}
+
+#define SET_ATTR_STATUS_CLEAN(TYPE, NAME) \
+do { \
+ if (facelet->NAME ## _status == FACELET_ATTR_STATUS_DIRTY) \
+ facelet->NAME ## _status = FACELET_ATTR_STATUS_CLEAN; \
+} while (0)
+
+void
+facelet_set_status(facelet_t * facelet, facelet_status_t status)
+{
+ if (status == FACELET_STATUS_CLEAN) {
+#define _(TYPE, NAME) SET_ATTR_STATUS_CLEAN(TYPE, NAME);
+ foreach_facelet_attr
+#undef _
+ }
+ facelet->status = status;
+}
+
+int
+facelet_add_pending(facelet_t * facelet)
+{
+ assert(facelet);
+ facelet->num_pending++;
+ return 0;
+}
+
+int
+facelet_remove_pending(facelet_t * facelet)
+{
+ assert(facelet);
+ if (facelet->num_pending == 0)
+ return -1;
+ facelet->num_pending--;
+ return 0;
+}
+
+bool
+facelet_has_pending(const facelet_t * facelet)
+{
+ assert(facelet);
+ DEBUG("num pending=%d\n", facelet->num_pending);
+ return (facelet->num_pending > 0);
+}
+
+void
+facelet_set_bj_done(facelet_t * facelet)
+{
+ facelet->bj_done = true;
+}
+
+bool
+facelet_is_bj_done(const facelet_t * facelet)
+{
+ return facelet->bj_done;
+}
+
+void
+facelet_set_au_done(facelet_t * facelet)
+{
+ facelet->au_done = true;
+}
+
+bool
+facelet_is_au_done(const facelet_t * facelet)
+{
+ return facelet->au_done;
+}
+
+facelet_event_t
+facelet_get_event(const facelet_t * facelet)
+{
+ return facelet->event;
+}
+
+void
+facelet_set_event(facelet_t * facelet, facelet_event_t event)
+{
+ facelet->event = event;
+}
+
+int
+facelet_raise_event(facelet_t * facelet, const interface_t * interface)
+{
+ if (interface->callback)
+ interface->callback(interface->callback_data, facelet);
+ return 0;
+}
+
+int
+facelet_snprintf(char * s, size_t size, facelet_t * facelet)
+{
+ char * cur = s;
+ int rc;
+
+ assert(facelet);
+
+ /* Header + key attributes (netdevice + family) */
+ rc = snprintf(cur, s + size - cur, "<Facelet %s (%s) [%d]",
+ // FIXME, better than the event would be the action to be performed next
+ facelet_event_str[facelet->event],
+ (facelet->family == AF_INET) ? "AF_INET" :
+ (facelet->family == AF_INET6) ? "AF_INET6" :
+ (facelet->family == AF_UNSPEC) ? "AF_UNSPEC" :
+ "unknown",
+ facelet->num_pending);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+
+ /* Netdevice */
+ if (facelet_has_netdevice(facelet)) {
+ rc = snprintf(cur, s + size - cur, " netdevice=%s",
+ facelet->netdevice.name[0] ? facelet->netdevice.name : "*");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+
+ rc = snprintf(cur, s + size - cur, "/%d", facelet->netdevice.index);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+
+ } else {
+ rc = snprintf(cur, s + size - cur, " netdevice=*/*");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+ }
+
+ /* Netdevice type */
+ if (facelet_has_netdevice_type(facelet)) {
+ rc = snprintf(cur, s + size - cur, " type=%s",
+ netdevice_type_str[facelet->netdevice_type]);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+ }
+#ifdef __linux__
+#ifndef __ANDROID__
+ else {
+ /*
+ * Heuristics to determine face type based on name, until a better
+ * solution is found
+ */
+ if ((strncmp(facelet->netdevice.name, "eth", 3) == 0) ||
+ (strncmp(facelet->netdevice.name, "en", 2) == 0)) {
+ rc = snprintf(cur, s + size - cur, " [type=WIRED]");
+ goto HEURISTIC_DONE;
+ }
+ if (strncmp(facelet->netdevice.name, "wl", 2) == 0) {
+ /* wlan* wlp* wlx* */
+ rc = snprintf(cur, s + size - cur, " [type=WIFI]");
+ goto HEURISTIC_DONE;
+ }
+ goto HEURISTIC_END;
+
+HEURISTIC_DONE:
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+HEURISTIC_END:
+ ;
+ }
+#endif /* ! __ANDROID__ */
+#endif /* __linux__ */
+
+ /* Local ip address */
+ if (facelet_has_local_addr(facelet)) {
+ rc = snprintf(cur, s + size - cur, " local_addr=");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+
+ rc = ip_address_snprintf(cur, s + size - cur, &facelet->local_addr,
+ facelet->family);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+ }
+
+ /* Local port */
+ if (facelet_has_local_port(facelet)) {
+ rc = snprintf(cur, s + size - cur, " local_port=%d",
+ facelet->local_port);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+ }
+
+ /* Remote ip address */
+ if (facelet_has_remote_addr(facelet)) {
+ rc = snprintf(cur, s + size - cur, " remote_addr=");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+
+ rc = ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr,
+ facelet->family);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+ }
+
+ /* Remote port */
+ if (facelet_has_remote_port(facelet)) {
+ rc = snprintf(cur, s + size - cur, " remote_port=%d",
+ facelet->remote_port);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+ }
+
+ /* Admin state */
+ if (facelet_has_admin_state(facelet)) {
+ rc = snprintf(cur, s + size - cur, " admin_state=%s",
+ face_state_str[facelet->admin_state]);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+ }
+
+ /* State */
+ if (facelet_has_state(facelet)) {
+ rc = snprintf(cur, s + size - cur, " state=%s",
+ face_state_str[facelet->state]);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+ }
+
+ if (facelet_has_face_type(facelet)) {
+ rc = snprintf(cur, s + size - cur, " face_type=IP%s/%s",
+ FACEMGR_FACE_TYPE_STR(facelet->face_type));
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+ }
+
+ rc = snprintf(cur, s + size - cur, ">");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+
+ return cur - s;
+}
diff --git a/ctrl/facemgr/src/facelet.h b/ctrl/facemgr/src/facelet.h
new file mode 100644
index 000000000..fecee8641
--- /dev/null
+++ b/ctrl/facemgr/src/facelet.h
@@ -0,0 +1,198 @@
+/*
+ * 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 facelet.h
+ * \brief Facelet
+ *
+ * A facelet consists in partial information and annotations collected towards
+ * the contruction of the final face that will be sent to the forwarder.
+ *
+ * It might also consist in a pattern allowing the deletion of a group of face
+ * for instance.
+ */
+#ifndef FACEMGR_FACELET_H
+#define FACEMGR_FACELET_H
+
+#include <stdbool.h>
+
+#include <hicn/ctrl/face.h>
+#include <hicn/facemgr.h>
+
+#include "interface.h"
+
+/* NOTE: Any test should be sufficient */
+#define IS_VALID_NETDEVICE(netdevice) ((netdevice.index != 0) && (netdevice.name[0] != '\0'))
+
+typedef struct facelet_s facelet_t;
+
+/* Facelet status */
+#define foreach_facelet_status \
+ _(UNDEFINED) \
+ _(NEW) \
+ _(CLEAN) \
+ _(DIRTY) \
+ _(CONFLICT) \
+ _(DELETED) \
+ _(N)
+
+typedef enum {
+#define _(x) FACELET_STATUS_ ## x,
+ foreach_facelet_status
+#undef _
+} facelet_status_t;
+
+extern const char * facelet_status_str[];
+
+/* Facelet attribute status */
+
+/*
+ * We expect an attribute in the cache to be able to take any value but
+ * UNDEFINED and N, which facelet events should either be UNSET or CLEAN
+ */
+#define foreach_facelet_attr_status \
+ _(UNDEFINED, '?') \
+ _(UNSET, 'X') \
+ _(CLEAN, ' ') \
+ _(DIRTY, '*') \
+ _(PENDING, 'P') \
+ _(CONFLICT, '!') \
+ _(N, '-')
+
+typedef enum {
+#define _(x, y) FACELET_ATTR_STATUS_ ## x,
+ foreach_facelet_attr_status
+#undef _
+} facelet_attr_status_t;
+
+extern const char * facelet_attr_status_str[];
+extern const char * facelet_attr_status_str_short[];
+
+/* Facelet attribute */
+
+#define foreach_facelet_attr \
+ _(netdevice_type_t, netdevice_type) \
+ _(netdevice_t, netdevice) \
+ _(int, family) \
+ _(ip_address_t, local_addr) \
+ _(u16, local_port) \
+ _(ip_address_t, remote_addr) \
+ _(u16, remote_port) \
+ _(face_state_t, admin_state) \
+ _(face_state_t, state) \
+ _(facemgr_face_type_t, face_type)
+
+#define foreach_facelet_event \
+ _(UNDEFINED) \
+ _(GET) \
+ _(CREATE) \
+ _(UPDATE) \
+ _(DELETE) \
+ _(SET_PARAMS) \
+ _(SET_UP) \
+ _(SET_DOWN) \
+ _(SET_TAGS) \
+ _(CLEAR_TAGS) \
+ _(ADD_TAG) \
+ _(REMOVE_TAG) \
+ _(N)
+
+#define MAXSZ_EVENT__ 10
+#define MAXSZ_EVENT_ MAXSZ_EVENT_ + 1
+
+/**
+ * \brief Enumeration of the possible types of event
+ */
+typedef enum {
+#define _(x) FACELET_EVENT_ ## x,
+foreach_facelet_event
+#undef _
+} facelet_event_t;
+
+extern const char * facelet_event_str[];
+
+/**
+ * \brief Create a facelet.
+ */
+facelet_t * facelet_create();
+
+facelet_t * facelet_create_from_netdevice(netdevice_t * netdevice);
+
+int facelet_validate_face(const facelet_t * facelet);
+
+facelet_t * facelet_create_from_face(face_t * face);
+
+void facelet_free(facelet_t * facelet);
+
+facelet_t * facelet_dup(const facelet_t * current_facelet);
+
+int facelet_cmp(const facelet_t * f1, const facelet_t * f2);
+
+/* NOTE: only clean attributes are matched */
+bool facelet_match(const facelet_t * facelet, const facelet_t * facelet_match);
+
+/**
+ * \brief Returns whether the specified facelet has all key attributes defined.
+ *
+ * Key attributes are netdevice and family. If both are present, this allows to
+ * uniquely identify a facelet, otherwise it is a 'wildcard' facelet
+ * specification and might match several facelets.
+ */
+bool facelet_has_key(const facelet_t * facelet);
+
+
+#define FACELET_ACCESSORS_H(TYPE, NAME) \
+bool facelet_has_ ## NAME(const facelet_t * facelet); \
+facelet_attr_status_t facelet_get_ ## NAME ## _status(const facelet_t * facelet);\
+int facelet_get_ ## NAME(const facelet_t * facelet, TYPE * NAME); \
+int facelet_set_ ## NAME(facelet_t * facelet, TYPE NAME);
+
+#define _(TYPE, NAME) FACELET_ACCESSORS_H(TYPE, NAME)
+foreach_facelet_attr
+#undef _
+
+int facelet_get_face(const facelet_t * facelet, face_t ** pface);
+
+int facelet_merge(facelet_t * facelet, const facelet_t * facelet_to_merge);
+
+facelet_status_t facelet_get_status(const facelet_t * facelet);
+void facelet_set_status(facelet_t * facelet, facelet_status_t status);
+
+int facelet_add_pending(facelet_t * facelet);
+int facelet_remove_pending(facelet_t * facelet);
+bool facelet_has_pending(const facelet_t * facelet);
+
+void facelet_set_bj_done(facelet_t * facelet);
+bool facelet_is_bj_done(const facelet_t * facelet);
+void facelet_set_au_done(facelet_t * facelet);
+bool facelet_is_au_done(const facelet_t * facelet);
+
+facelet_event_t facelet_get_event(const facelet_t * facelet);
+void facelet_set_event(facelet_t * facelet, facelet_event_t event);
+
+/**
+ * \brief Create and raises an event to the face manager
+ * \param [in] event_type - Type of the event to create
+ * \param [in] facelet - Facelet to communicate with the event
+ * \param [in] interface - Interface that raised the event (or NULL if it was
+ * created but the face manager itself, or is a joined event)
+ */
+int facelet_raise_event(facelet_t * facelet, const interface_t * interface);
+
+int facelet_snprintf(char * buf, size_t size, facelet_t * facelet);
+
+#define MAXSZ_FACELET 1024
+
+#endif /* FACEMGR_FACELET_H */
diff --git a/ctrl/facemgr/src/facemgr.c b/ctrl/facemgr/src/facemgr.c
deleted file mode 100644
index 41e30de56..000000000
--- a/ctrl/facemgr/src/facemgr.c
+++ /dev/null
@@ -1,298 +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 facemgr.c
- * \brief Implementation of Face manager library interface
- */
-
-#include <stdio.h>
-
-#include "common.h"
-#include "event.h"
-#include "facemgr.h"
-#include "interface.h"
-#include "util/log.h"
-
-#ifdef __APPLE__
-extern interface_ops_t network_framework_ops;
-#endif
-#ifdef __linux__
-extern interface_ops_t netlink_ops;
-#endif
-#if 0
-extern interface_ops_t dummy_ops;
-#endif
-extern interface_ops_t hicn_light_ops;
-
-int
-facemgr_initialize(facemgr_t * facemgr)
-{
- int rc;
-
- rc = interface_map_initialize(&facemgr->interface_map);
- if (FACEMGR_IS_ERROR(rc))
- goto ERR_INTERFACE_MAP;
-
- rc = face_cache_initialize(&facemgr->face_cache);
- if (FACEMGR_IS_ERROR(rc))
- goto ERR_FACE_SET;
-
- rc = face_rules_initialize(&facemgr->rules);
- if (FACEMGR_IS_ERROR(rc))
- goto ERR_FACE_SET;
-
- return FACEMGR_SUCCESS;
-
-ERR_FACE_SET:
- interface_map_finalize(&facemgr->interface_map);
-
-ERR_INTERFACE_MAP:
- return FACEMGR_FAILURE;
-}
-
-int
-facemgr_finalize(facemgr_t * facemgr)
-{
- int rc;
-
- /* XXX Free all interfaces: pass free to map */
- rc = interface_map_finalize(&facemgr->interface_map);
- if (FACEMGR_IS_ERROR(rc))
- goto ERR;
-
- rc = face_cache_finalize(&facemgr->face_cache);
- if (FACEMGR_IS_ERROR(rc))
- goto ERR;
-
- rc = face_rules_finalize(&facemgr->rules);
- if (FACEMGR_IS_ERROR(rc))
- goto ERR;
-
- return FACEMGR_SUCCESS;
-
-ERR:
- return FACEMGR_FAILURE;
-}
-
-AUTOGENERATE_CREATE_FREE(facemgr);
-
-int
-facemgr_on_event(facemgr_t * facemgr, event_t * event)
-{
- int rc;
- char face_s[MAXSZ_FACE];
- face_t * cached_face;
-
- if (!event->face) {
- printf("Event with empty face\n");
- return -1;
- }
-
- face_t face = *event->face;
-
- /* Complement unbound UDP faces */
- switch(face.type) {
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- switch (face.params.tunnel.family) {
- case AF_INET:
- if ((ip_address_empty(&face.params.tunnel.remote_addr)) &&
- (!ip_address_empty(&facemgr->overlay_v4_remote_addr)))
- face.params.tunnel.remote_addr = facemgr->overlay_v4_remote_addr;
- if ((face.params.tunnel.local_port == 0) && (facemgr->overlay_v4_local_port != 0))
- face.params.tunnel.local_port = facemgr->overlay_v4_local_port;
- if ((face.params.tunnel.remote_port == 0) && (facemgr->overlay_v4_remote_port != 0))
- face.params.tunnel.remote_port = facemgr->overlay_v4_remote_port;
- break;
- case AF_INET6:
- if ((ip_address_empty(&face.params.tunnel.remote_addr)) &&
- (!ip_address_empty(&facemgr->overlay_v6_remote_addr)))
- face.params.tunnel.remote_addr = facemgr->overlay_v6_remote_addr;
- if ((face.params.tunnel.local_port == 0) && (facemgr->overlay_v6_local_port != 0))
- face.params.tunnel.local_port = facemgr->overlay_v6_local_port;
- if ((face.params.tunnel.remote_port == 0) && (facemgr->overlay_v6_remote_port != 0))
- face.params.tunnel.remote_port = facemgr->overlay_v6_remote_port;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- face_snprintf(face_s, MAXSZ_FACE, &face);
-
- /* TODO Here, we need to filter events based on our cache, and update the cache
- * based on our actions if they are successful */
-
- switch(event->type) {
- case EVENT_TYPE_CREATE:
- rc = face_cache_get(&facemgr->face_cache, &face, &cached_face);
- if (!FACEMGR_IS_ERROR(rc)) {
- DEBUG("Face found in cache");
- goto IGNORE_EVENT;
- }
- rc = face_cache_add(&facemgr->face_cache, &face);
- if (FACEMGR_IS_ERROR(rc))
- WARN("Failed to add face to cache");
- break;
- case EVENT_TYPE_DELETE:
- rc = face_cache_remove(&facemgr->face_cache, &face, &cached_face);
- if (FACEMGR_IS_ERROR(rc))
- WARN("Face not found in cache");
- break;
- case EVENT_TYPE_SET_UP:
- case EVENT_TYPE_SET_DOWN:
- /* TODO We need a return code to update the cache */
- break;
- default:
- printf("Not implemented!\n");
- break;
- }
-
- /* Process event */
- printf("[ FACE %s ] %s\n", event_type_str[event->type], face_s);
- /* Hardcoded hicn-light */
- rc = interface_on_event(facemgr->hl, event);
- if (FACEMGR_IS_ERROR(rc))
- goto ERR;
-
-IGNORE_EVENT:
- return FACEMGR_SUCCESS;
-
-ERR:
- return FACEMGR_FAILURE;
-}
-
-#ifdef __linux__
-void interface_callback(evutil_socket_t fd, short what, void * arg) {
- interface_t * interface = (interface_t *)arg;
- interface->ops->callback(interface);
-}
-#endif /* __linux__ */
-
-int
-facemgr_create_interface(facemgr_t * facemgr, const char * name, const char * type, interface_t ** interface)
-{
- int fd, rc;
-
- INFO("Creating interface %s [%s]...\n", name, type);
- *interface = interface_create(name, type);
- if (!*interface) {
- ERROR("Error creating interface %s [%s]\n", name, type);
- return -1;
- }
- interface_set_callback(*interface, facemgr_on_event, facemgr);
-
- fd = interface_initialize(*interface, &facemgr->rules);
- if (fd < 0)
- return -2;
- if (fd != 0) {
-#ifdef __linux__
- evutil_make_socket_nonblocking(fd);
- struct event * event = event_new(facemgr->loop, fd, EV_READ | EV_PERSIST, interface_callback, *interface);
- if (!event) {
- return -3;
- }
-
- if (event_add(event, NULL) < 0) {
- return -4;
- }
-#else
- ERROR("Not implemented\n");
- return FACEMGR_FAILURE;
-#endif /* __linux__ */
- }
-
- rc = interface_map_add(&facemgr->interface_map, (*interface)->name, *interface);
- if (FACEMGR_IS_ERROR(rc))
- return -5;
-
- DEBUG("Interface created successfully.\n");
- return FACEMGR_SUCCESS;
-}
-
-int
-facemgr_bootstrap(facemgr_t * facemgr)
-{
- int rc;
-
- DEBUG("Registering interfaces...");
- rc = interface_register(&hicn_light_ops);
- if (FACEMGR_IS_ERROR(rc)) {
- ERROR("Could not register interfaces");
- goto ERR_REGISTER;
- }
-
-#ifdef __APPLE__
- rc = interface_register(&network_framework_ops);
- if (FACEMGR_IS_ERROR(rc))
- goto ERR_REGISTER;
-#endif /* __APPLE__ */
-
-#ifdef __linux__
- rc = interface_register(&netlink_ops);
- if (FACEMGR_IS_ERROR(rc))
- goto ERR_REGISTER;
-#endif /* __linux__ */
-
-#if 0
- rc = interface_register(&dummy_ops);
- if (FACEMGR_IS_ERROR(rc))
- goto ERR_REGISTER;
-#endif
-
- rc = facemgr_create_interface(facemgr, "hl", "hicn_light", &facemgr->hl);
- if (rc < 0) {
- ERROR("Error creating 'hICN forwarder (hicn-light)' interface\n");
- goto ERR_HL_CREATE;
- }
-
-#ifdef __APPLE__
- rc = facemgr_create_interface(facemgr, "nf", "network_framework", &facemgr->nf);
- if (rc < 0) {
- ERROR("Error creating 'Apple Network Framework' interface\n");
- goto ERR_NF_CREATE;
- }
-#endif /* __APPLE__ */
-
-#ifdef __linux__
- rc = facemgr_create_interface(facemgr, "nl", "netlink", &facemgr->nl);
- if (rc < 0) {
- ERROR("Error creating 'Netlink' interface\n");
- goto ERR_NF_CREATE;
- }
-#endif /* __linux__ */
-
-#if 0
- rc = facemgr_create_interface(facemgr, "dummy", "dummy", &facemgr->dummy);
- if (rc < 0) {
- ERROR("Error creating 'Dummy' interface\n");
- goto ERR_NF_CREATE;
- }
-#endif
-
- DEBUG("Facemgr successfully initialized...");
-
- return FACEMGR_SUCCESS;
-
-ERR_NF_CREATE:
- interface_free(facemgr->hl);
-ERR_HL_CREATE:
- //interface_map_remove(&facemgr->interface_map, data->nf->name);
-ERR_REGISTER:
- return FACEMGR_FAILURE;
-}
diff --git a/ctrl/facemgr/src/facemgr.h b/ctrl/facemgr/src/facemgr.h
deleted file mode 100644
index 6505a1bd8..000000000
--- a/ctrl/facemgr/src/facemgr.h
+++ /dev/null
@@ -1,77 +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 facemgr.h
- * \brief Face manager library interface
- */
-#ifndef FACEMGR_H
-#define FACEMGR_H
-
-#include <string.h>
-#include "common.h"
-#include "face.h"
-#include "face_cache.h"
-#include "face_rules.h"
-#include "interface.h"
-#include "interface_map.h"
-#include "util/ip_address.h"
-#include "util/map.h"
-#include "util/policy.h"
-#ifndef __APPLE__
-#include <event2/event.h>
-#endif /* __APPLE__ */
-
-/*
- * \brief Face manager context
- */
-typedef struct {
-#ifndef APPLE
- /* Event loop */
- struct event_base * loop;
-#endif /* APPLE */
-
- interface_map_t interface_map;
- interface_t * hl;
-
-#ifdef __APPLE__
- interface_t * nf;
-#endif /* __APPLE__ */
-
-#ifdef __linux__
- interface_t * nl;
-#endif /* __linux__ */
-
-#if 0
- interface_t * dummy;
-#endif
-
- /* Overlay management */
- uint16_t overlay_v4_local_port;
- ip_address_t overlay_v4_remote_addr;
- uint16_t overlay_v4_remote_port;
- uint16_t overlay_v6_local_port;
- ip_address_t overlay_v6_remote_addr;
- uint16_t overlay_v6_remote_port;
-
- face_rules_t rules;
- face_cache_t face_cache;
-} facemgr_t;
-
-AUTOGENERATE_DEFS(facemgr);
-
-int facemgr_bootstrap(facemgr_t * facemgr);
-
-#endif /* FACEMGR_H */
diff --git a/ctrl/facemgr/src/interface.c b/ctrl/facemgr/src/interface.c
index af9f666a7..3e6bc0854 100644
--- a/ctrl/facemgr/src/interface.c
+++ b/ctrl/facemgr/src/interface.c
@@ -20,12 +20,13 @@
#include <stdlib.h>
#include <string.h>
-#include "event.h"
-#include "face_rules.h"
+#include "facelet.h"
#include "interface.h"
-#include "interface_ops_map.h"
#include "util/map.h"
+TYPEDEF_MAP_H(interface_ops_map, const char *, const interface_ops_t *);
+TYPEDEF_MAP(interface_ops_map, const char *, const interface_ops_t *, strcmp, string_snprintf, generic_snprintf);
+
static interface_ops_map_t * interface_ops_map = NULL;
int
@@ -34,19 +35,19 @@ interface_register(const interface_ops_t * ops)
if (!interface_ops_map) {
interface_ops_map = interface_ops_map_create();
if (!interface_ops_map)
- return FACEMGR_FAILURE;
+ return -1;
}
interface_ops_map_add(interface_ops_map, ops->type, ops);
- return FACEMGR_SUCCESS;
+ return 0;
}
interface_t *
interface_create(const char * name, const char * type)
{
- interface_ops_t * ops;
+ const interface_ops_t * ops = NULL;
int rc = interface_ops_map_get(interface_ops_map, type, &ops);
- if (FACEMGR_IS_ERROR(rc)) {
+ if (rc < 0) {
printf("Interface type not found %s\n", type);
return NULL;
}
@@ -80,25 +81,25 @@ _interface_set_callback(interface_t * interface, callback_t callback, void * cal
}
int
-interface_initialize(interface_t * interface, struct face_rules_s * rules)
+interface_initialize(interface_t * interface, void * cfg)
{
if (!interface->ops->initialize)
- return FACEMGR_FAILURE;
- return interface->ops->initialize(interface, rules, &interface->data);
+ return -1;
+ return interface->ops->initialize(interface, cfg);
}
int
interface_finalize(interface_t * interface)
{
if (!interface->ops->finalize)
- return FACEMGR_FAILURE;
+ return -1;
return interface->ops->finalize(interface);
}
int
-interface_on_event(interface_t * interface, const event_t * event)
+interface_on_event(interface_t * interface, const facelet_t * facelet)
{
if (!interface->ops->on_event)
- return FACEMGR_FAILURE;
- return interface->ops->on_event(interface, event);
+ return -1;
+ return interface->ops->on_event(interface, facelet);
}
diff --git a/ctrl/facemgr/src/interface.h b/ctrl/facemgr/src/interface.h
index f38313182..331312bde 100644
--- a/ctrl/facemgr/src/interface.h
+++ b/ctrl/facemgr/src/interface.h
@@ -30,27 +30,30 @@
#include <stdbool.h>
-struct event_s;
-typedef int (*callback_t)(struct event_s * event, void * callback_data);
+struct facelet_s;
+typedef int (*callback_t)(struct facelet_s * facelet, void * callback_data);
struct interface_s;
-struct face_rules_s;
/**
* \brief Interface operations
*/
typedef struct {
+ /** The type given to the interfaces */
char * type;
- bool is_singleton;
- int (*initialize)(struct interface_s * interface, struct face_rules_s * rules, void ** pdata);
+ /* Constructor */
+ int (*initialize)(struct interface_s * interface, void * cfg);
+ /* Destructor */
int (*finalize)(struct interface_s * interface);
+ /* Callback upon file descriptor event (iif previously registered) */
int (*callback)(struct interface_s * interface);
- int (*on_event)(struct interface_s * interface, const struct event_s * event);
+ /* Callback upon face events coming from the face manager */
+ int (*on_event)(struct interface_s * interface, const struct facelet_s * facelet);
} interface_ops_t;
typedef struct interface_s {
char * name;
- interface_ops_t * ops;
+ const interface_ops_t * ops;
callback_t callback;
void * callback_data;
void * data;
@@ -90,9 +93,9 @@ void _interface_set_callback(interface_t * interface, callback_t callback, void
#define interface_set_callback(interface, callback, callback_data) \
_interface_set_callback(interface, (callback_t)callback, (void*)callback_data)
-int interface_initialize(interface_t * interface, struct face_rules_s * rules);
+int interface_initialize(interface_t * interface, void * cfg);
int interface_finalize(interface_t * interface);
-int interface_on_event(interface_t * interface, const struct event_s * event);
+int interface_on_event(interface_t * interface, const struct facelet_s * facelet);
#endif /* FACEMGR_INTERFACE_H */
diff --git a/ctrl/facemgr/src/interface_map.c b/ctrl/facemgr/src/interface_map.c
deleted file mode 100644
index 9f7c20cab..000000000
--- a/ctrl/facemgr/src/interface_map.c
+++ /dev/null
@@ -1,21 +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.
- */
-
-#include "interface_map.h"
-
-#include <string.h>
-#include "interface.h"
-
-TYPEDEF_MAP(interface_map, const char *, interface_t *, strcmp, string_snprintf, generic_snprintf);
diff --git a/ctrl/facemgr/src/interface_ops_map.c b/ctrl/facemgr/src/interface_ops_map.c
deleted file mode 100644
index 373f5d22f..000000000
--- a/ctrl/facemgr/src/interface_ops_map.c
+++ /dev/null
@@ -1,21 +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.
- */
-
-#include "interface_ops_map.h"
-
-#include <string.h>
-#include "util/map.h"
-
-TYPEDEF_MAP(interface_ops_map, const char *, interface_ops_t *, strcmp, string_snprintf, generic_snprintf);
diff --git a/ctrl/facemgr/src/interfaces/CMakeLists.txt b/ctrl/facemgr/src/interfaces/CMakeLists.txt
index e5a26177a..8d079612a 100644
--- a/ctrl/facemgr/src/interfaces/CMakeLists.txt
+++ b/ctrl/facemgr/src/interfaces/CMakeLists.txt
@@ -24,12 +24,21 @@ endif()
if(LINUX)
add_subdirectory(netlink)
+add_subdirectory(bonjour)
endif()
-if(false)
+if(ANDROID)
+add_subdirectory(android_utility)
+endif()
+
+if(WITH_EXAMPLE_DUMMY)
add_subdirectory(dummy)
endif()
+if(WITH_EXAMPLE_UPDOWN)
+add_subdirectory(updown)
+endif()
+
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
set(INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE)
diff --git a/ctrl/facemgr/src/interfaces/android_utility/CMakeLists.txt b/ctrl/facemgr/src/interfaces/android_utility/CMakeLists.txt
new file mode 100644
index 000000000..0ebe87745
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/android_utility/CMakeLists.txt
@@ -0,0 +1,27 @@
+# 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.
+
+list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/android_utility.c
+)
+
+list(APPEND INCLUDE_DIRS
+)
+
+list(APPEND LIBRARIES
+)
+
+set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
+set(INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE)
+set(LIBRARIES ${LIBRARIES} PARENT_SCOPE)
diff --git a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
new file mode 100644
index 000000000..bb612507f
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
@@ -0,0 +1,138 @@
+/*
+ * 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 interfaces/android_utility/android_utility.c
+ * \brief Implementation of Android utility.
+ */
+
+#include <assert.h>
+
+#include <hicn/facemgr.h>
+#include <hicn/ctrl/face.h>
+#include <hicn/util/log.h>
+#include "../../common.h"
+#include "../../facelet.h"
+#include "../../interface.h"
+#include <hicn/android_utility/android_utility.h>
+
+#define FACEMGR_ANDROID_UTILITY_CLASS "com/cisco/hicn/forwarder/supportlibrary/AndroidUtility"
+
+#define AU_INTERFACE_TYPE_UNDEFINED 0
+#define AU_INTERFACE_TYPE_WIRED 1
+#define AU_INTERFACE_TYPE_WIFI 2
+#define AU_INTERFACE_TYPE_CELLULAR 3
+#define AU_INTERFACE_TYPE_LOOPBACK 4 /* not supported yet */
+
+#define ERR_STR_JAVA "Java VM parameters are required in the interface configuration."
+
+typedef struct {
+ android_utility_cfg_t cfg;
+} au_data_t;
+
+int au_initialize(interface_t * interface, void * cfg)
+{
+ au_data_t * data = malloc(sizeof(au_data_t));
+ if (!data)
+ return -1;
+ interface->data = data;
+
+ if (!cfg)
+ goto ERR_CFG;
+
+ data->cfg = * (android_utility_cfg_t *) cfg;
+
+ if (!data->cfg.jvm)
+ goto ERR_CFG;
+
+ return 0;
+
+ERR_CFG:
+ fprintf(stderr, ERR_STR_JAVA);
+ return -1;
+}
+
+int au_finalize(interface_t * interface)
+{
+ /* Nothing to do */
+ return 0;
+}
+
+int au_on_event(interface_t * interface, const facelet_t * facelet)
+{
+ /*
+ * This function is responsible to annotate every face we receive with the
+ * correct interface type, based on the value returned by the Android
+ * utility shipped with the Android forwarder.
+ */
+ DEBUG("Android utility received request");
+ au_data_t * data = (au_data_t*)interface->data;
+
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ int rc = facelet_get_netdevice(facelet, &netdevice);
+ if (rc < 0)
+ return -1;
+ DEBUG("[au_on_event] netdevice=%s", netdevice.name);
+
+ JNIEnv *env;
+ JavaVM *jvm = data->cfg.jvm;
+ (*jvm)->AttachCurrentThread(jvm, &env, NULL);
+ jclass cls = (*env)->FindClass(env, FACEMGR_ANDROID_UTILITY_CLASS);
+ jmethodID getNetworkType = (*env)->GetStaticMethodID(env, cls,
+ "getNetworkType", "(Ljava/lang/String;)I");
+ jint interface_type = (*env)->CallStaticIntMethod(env, cls, getNetworkType,
+ (*env)->NewStringUTF(env, netdevice.name));
+
+ DEBUG("Processing results for interface %s", netdevice.name);
+
+ netdevice_type_t netdevice_type = AU_INTERFACE_TYPE_UNDEFINED;
+ switch(interface_type) {
+ case AU_INTERFACE_TYPE_UNDEFINED:
+ break;
+ case AU_INTERFACE_TYPE_WIRED:
+ netdevice_type = NETDEVICE_TYPE_WIRED;
+ break;
+ case AU_INTERFACE_TYPE_WIFI:
+ netdevice_type = NETDEVICE_TYPE_WIFI;
+ break;
+ case AU_INTERFACE_TYPE_CELLULAR:
+ netdevice_type = NETDEVICE_TYPE_CELLULAR;
+ break;
+ case AU_INTERFACE_TYPE_LOOPBACK:
+ netdevice_type = NETDEVICE_TYPE_LOOPBACK;
+ break;
+ default:
+ return -1;
+ }
+
+ facelet_t * facelet_new = facelet_create();
+ facelet_set_netdevice(facelet_new, netdevice);
+ facelet_set_status(facelet_new, FACELET_STATUS_CLEAN);
+ facelet_set_netdevice_type(facelet_new, netdevice_type);
+
+ DEBUG("sending AU udpate");
+ facelet_set_event(facelet_new, FACELET_EVENT_UPDATE);
+ facelet_raise_event(facelet_new, interface);
+
+ return 0;
+}
+
+const interface_ops_t android_utility_ops = {
+ .type = "android_utility",
+ .initialize = au_initialize,
+ .finalize = au_finalize,
+ .callback = NULL,
+ .on_event = au_on_event,
+};
diff --git a/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt b/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt
new file mode 100644
index 000000000..8a0ddc888
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt
@@ -0,0 +1,32 @@
+# 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.
+
+list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/bonjour.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/mdns/mdns.h
+)
+
+list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/bonjour.c
+)
+
+list(APPEND LIBRARIES
+)
+
+list(APPEND INCLUDE_DIRS
+)
+
+set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
+set(INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE)
+set(LIBRARIES ${LIBRARIES} PARENT_SCOPE)
diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c
new file mode 100644
index 000000000..d7b27b995
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c
@@ -0,0 +1,408 @@
+/*
+ * 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 interfaces/bonjour/bonjour.c
+ * \brief Implementation of Bonjour interface
+ *
+ * TODO:
+ * - concurrent queries
+ * - interface binding
+ */
+
+#include <hicn/facemgr.h>
+#include <hicn/util/log.h>
+
+#include "../../common.h"
+#include "../../facelet.h"
+#include "../../interface.h"
+#include "../../util/map.h"
+#include "mdns/mdns.h"
+
+#include "bonjour.h"
+
+#define DEFAULT_BUFFER_SIZE 2048
+#define SERVICE_STRING_SIZE 256
+
+#define DEFAULT_SERVICE_NAME "hicn"
+#define DEFAULT_SERVICE_PROTOCOL "udp"
+#define DEFAULT_SERVICE_DOMAIN "local"
+
+typedef struct {
+ bonjour_cfg_t cfg;
+ int sock;
+ size_t buffer_size;
+ void* buffer;
+
+ /* The face being resolved, non-NULL values indicate interface is busy... */
+ face_t * face;
+} bj_data_t;
+
+int bj_initialize(interface_t * interface, void * cfg)
+{
+ bj_data_t * data = malloc(sizeof(bj_data_t));
+ if (!data)
+ goto ERR_MALLOC;
+ interface->data = data;
+
+ if (cfg) {
+#ifndef __linux__
+ if (cfg->netdevice)
+ WARN("Binding to interface is (currently) only supported on Linux");
+#endif /* ! __linux__ */
+ data->cfg = * (bonjour_cfg_t *) cfg;
+ } else {
+ memset(&data->cfg, 0, sizeof(bonjour_cfg_t));
+ }
+
+ if (!data->cfg.service_name)
+ data->cfg.service_name = DEFAULT_SERVICE_NAME;
+
+ if (!data->cfg.service_protocol)
+ data->cfg.service_protocol = DEFAULT_SERVICE_PROTOCOL;
+
+ if (!data->cfg.service_domain)
+ data->cfg.service_domain = DEFAULT_SERVICE_DOMAIN;
+
+ data->sock = mdns_socket_open_ipv4();
+ if (data->sock < 0) {
+ printf("Failed to open socket: %s\n", strerror(errno));
+ goto ERR_SOCK;
+ }
+
+ /* Netdevice configuration */
+#ifdef __linux__
+#ifndef __ANDROID__
+ if (IS_VALID_NETDEVICE(data->cfg.netdevice)) {
+ int rc = setsockopt(data->sock, SOL_SOCKET, SO_BINDTODEVICE,
+ &data->cfg.netdevice.name, strlen(data->cfg.netdevice.name) + 1);
+ if (rc == -1) {
+ ERROR("setsockopt");
+ goto ERR_SOCK_OPT;
+ }
+ }
+#endif
+#endif /* __linux__ */
+
+ data->buffer_size = DEFAULT_BUFFER_SIZE;
+ data->buffer = malloc(data->buffer_size);
+ if (!data->buffer)
+ goto ERR_BUFFER;
+
+#ifdef _WIN32
+ WORD versionWanted = MAKEWORD(1, 1);
+ WSADATA wsaData;
+ WSAStartup(versionWanted, &wsaData);
+#endif
+
+ return data->sock;
+
+ERR_BUFFER:
+#ifndef __ANDROID__
+ERR_SOCK_OPT:
+#endif
+ mdns_socket_close(data->sock);
+#ifdef _WIN32
+ WSACleanup();
+#endif
+ERR_SOCK:
+ free(data);
+ERR_MALLOC:
+ return -1;
+}
+
+/*
+ * We reuse the callback to be triggered upon external events
+ * TODO: move to a cleaner interface architecture later...
+ */
+int bj_on_event(interface_t * interface, const facelet_t * facelet)
+{
+ bj_data_t * data = (bj_data_t*)interface->data;
+
+ /*
+ printf("Sending DNS-SD discovery\n");
+ if (mdns_discovery_send(sock)) {
+ printf("Failed to send DNS-DS discovery: %s\n", strerror(errno));
+ goto quit;
+ }
+
+ printf("Reading DNS-SD replies\n");
+ for (int i = 0; i < 10; ++i) {
+ records = mdns_discovery_recv(sock, buffer, capacity, callback,
+ user_data);
+ sleep(1);
+ }
+ */
+
+ DEBUG("Sending mDNS query");
+ char service_string[SERVICE_STRING_SIZE];
+
+ int rc = snprintf(service_string, SERVICE_STRING_SIZE, "_%s._%s.%s.",
+ data->cfg.service_name, data->cfg.service_protocol,
+ data->cfg.service_domain);
+ if (rc < 0)
+ ; // error
+ else if (rc >= SERVICE_STRING_SIZE)
+ ; //truncated
+
+ if (mdns_query_send(data->sock, MDNS_RECORDTYPE_PTR,
+ service_string,
+ strlen(service_string),
+ data->buffer, data->buffer_size)) {
+ printf("Failed to send mDNS query: %s\n", strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+static char addrbuffer[64];
+static char namebuffer[256];
+static mdns_record_txt_t txtbuffer[128];
+
+static mdns_string_t
+ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr) {
+ char host[NI_MAXHOST] = {0};
+ char service[NI_MAXSERV] = {0};
+ int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in),
+ host, NI_MAXHOST, service, NI_MAXSERV,
+ NI_NUMERICSERV | NI_NUMERICHOST);
+ int len = 0;
+ if (ret == 0) {
+ if (addr->sin_port != 0)
+ len = snprintf(buffer, capacity, "%s:%s", host, service);
+ else
+ len = snprintf(buffer, capacity, "%s", host);
+ }
+ if (len >= (int)capacity)
+ len = (int)capacity - 1;
+ mdns_string_t str = {buffer, len};
+ return str;
+}
+
+static mdns_string_t
+ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr) {
+ char host[NI_MAXHOST] = {0};
+ char service[NI_MAXSERV] = {0};
+ int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in6),
+ host, NI_MAXHOST, service, NI_MAXSERV,
+ NI_NUMERICSERV | NI_NUMERICHOST);
+ int len = 0;
+ if (ret == 0) {
+ if (addr->sin6_port != 0)
+ len = snprintf(buffer, capacity, "[%s]:%s", host, service);
+ else
+ len = snprintf(buffer, capacity, "%s", host);
+ }
+ if (len >= (int)capacity)
+ len = (int)capacity - 1;
+ mdns_string_t str = {buffer, len};
+ return str;
+}
+
+static mdns_string_t
+ip_address_to_string(char* buffer, size_t capacity, const struct sockaddr* addr) {
+ if (addr->sa_family == AF_INET6)
+ return ipv6_address_to_string(buffer, capacity, (const struct sockaddr_in6*)addr);
+ return ipv4_address_to_string(buffer, capacity, (const struct sockaddr_in*)addr);
+}
+
+int
+ip_address_set_sockaddr(ip_address_t * ip_address, struct sockaddr * sa)
+{
+ switch(sa->sa_family) {
+ case AF_INET:
+ ip_address->v4.as_inaddr = ((struct sockaddr_in *)sa)->sin_addr;
+ break;
+ case AF_INET6:
+ ip_address->v6.as_in6addr = ((struct sockaddr_in6 *)sa)->sin6_addr;
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+callback(const struct sockaddr* from, mdns_entry_type_t entry, uint16_t type,
+ uint16_t rclass, uint32_t ttl, const void* data, size_t size, size_t
+ offset, size_t length, void* user_data)
+{
+ interface_t * interface = (interface_t*)user_data;
+ bj_data_t * bj_data = (bj_data_t *)interface->data;
+
+ struct sockaddr_storage addr;
+
+ mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from);
+ const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" :
+ ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional");
+
+ switch(type) {
+ case MDNS_RECORDTYPE_A:
+ {
+ ip_address_t ip_address;
+ mdns_record_parse_a(data, size, offset, length, (struct sockaddr_in*)&addr);
+ ip_address_set_sockaddr(&ip_address, (struct sockaddr *)&addr);
+
+ mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), (struct sockaddr_in *)&addr);
+ DEBUG("%.*s : %s A %.*s",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(addrstr));
+
+ facelet_t * facelet = facelet_create();
+ facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
+ facelet_set_family(facelet, AF_INET);
+ facelet_set_remote_addr(facelet, ip_address);
+ //facelet_set_remote_port(facelet, ((struct sockaddr_in*)&addr)->sin_port);
+
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ facelet_raise_event(facelet, interface);
+ break;
+ }
+
+ case MDNS_RECORDTYPE_AAAA:
+ {
+ ip_address_t ip_address;
+ mdns_record_parse_aaaa(data, size, offset, length, (struct sockaddr_in6*)&addr);
+ ip_address_set_sockaddr(&ip_address, (struct sockaddr *)&addr);
+
+ mdns_string_t addrstr = ipv6_address_to_string(namebuffer,
+ sizeof(namebuffer), (struct sockaddr_in6*)&addr);
+ DEBUG("%.*s : %s AAAA %.*s",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(addrstr));
+
+ facelet_t * facelet = facelet_create();
+ facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
+ facelet_set_family(facelet, AF_INET6);
+ facelet_set_remote_addr(facelet, ip_address);
+ //facelet_set_remote_port(facelet, ((struct sockaddr_in6*)&addr)->sin6_port);
+
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ facelet_raise_event(facelet, interface);
+ break;
+ }
+
+ case MDNS_RECORDTYPE_SRV: /* same port for both v4 and v6 */
+ {
+ mdns_record_srv_t srv = mdns_record_parse_srv(data, size, offset, length,
+ namebuffer, sizeof(namebuffer));
+
+ DEBUG("%.*s : %s SRV %.*s priority %d weight %d port %d",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port);
+
+ /* We raise both v4 and v6
+ *
+ * Unless we choose whether we query A and/or AAAA, this might leave
+ * us with an unused pending facelet, eg. we might not have an IPv6
+ * but we raise an IPv6 bonjour event...
+ */
+
+ facelet_t * facelet = facelet_create();
+ facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
+ facelet_set_family(facelet, AF_INET);
+ facelet_set_remote_port(facelet, srv.port);
+
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ facelet_raise_event(facelet, interface);
+
+ facelet = facelet_create();
+ facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
+ facelet_set_family(facelet, AF_INET6);
+ facelet_set_remote_port(facelet, srv.port);
+
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ facelet_raise_event(facelet, interface);
+ break;
+ }
+
+ case MDNS_RECORDTYPE_PTR:
+ {
+ mdns_string_t namestr = mdns_record_parse_ptr(data, size, offset, length,
+ namebuffer, sizeof(namebuffer));
+ DEBUG("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length);
+ break;
+ }
+
+ case MDNS_RECORDTYPE_TXT:
+ {
+ size_t parsed = mdns_record_parse_txt(data, size, offset, length,
+ txtbuffer, sizeof(txtbuffer) / sizeof(mdns_record_txt_t));
+ for (size_t itxt = 0; itxt < parsed; ++itxt) {
+ if (txtbuffer[itxt].value.length) {
+ DEBUG("%.*s : %s TXT %.*s = %.*s",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(txtbuffer[itxt].key),
+ MDNS_STRING_FORMAT(txtbuffer[itxt].value));
+ }
+ else {
+ DEBUG("%.*s : %s TXT %.*s",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(txtbuffer[itxt].key));
+ }
+ }
+ break;
+ }
+
+ default:
+ /* Silently ignore the received record */
+ DEBUG("%.*s : %s type %u rclass 0x%x ttl %u length %d",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ type, rclass, ttl, (int)length);
+ return 0;
+ }
+ return 0;
+
+}
+
+/*
+ * The fact we use a single fd does not allow us to get user_data associated to
+ * the query.
+ */
+int bj_callback(interface_t * interface)
+{
+ bj_data_t * data = (bj_data_t*)interface->data;
+ DEBUG("Got an mDNS reply");
+ /* size_t records = */ mdns_query_recv(data->sock, data->buffer, data->buffer_size, callback, interface, 1);
+
+ return 0;
+}
+
+int bj_finalize(interface_t * interface)
+{
+ bj_data_t * data = (bj_data_t*)interface->data;
+
+ free(data->buffer);
+ mdns_socket_close(data->sock);
+
+#ifdef _WIN32
+ WSACleanup();
+#endif
+
+ return 0;
+
+}
+
+const interface_ops_t bonjour_ops = {
+ .type = "bonjour",
+ .initialize = bj_initialize,
+ .on_event = bj_on_event,
+ .callback = bj_callback,
+ .finalize = bj_finalize,
+ // .on_event = NULL,
+};
diff --git a/ctrl/facemgr/src/face_rules.h b/ctrl/facemgr/src/interfaces/bonjour/bonjour.h
index 28f5391a0..fe053079d 100644
--- a/ctrl/facemgr/src/face_rules.h
+++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.h
@@ -13,19 +13,23 @@
* limitations under the License.
*/
-#ifndef FACE_RULES_H
-#define FACE_RULES_H
-
-#include "util/map.h"
-#include "util/policy.h"
-
-/*
- * Face creation rules
+/**
+ * \file interfaces/bonjour/bonjour.h
+ * \brief Bonjour interface
*
- * For now, face creations rules are very simple and consist in a map between
- * the physical interface name, and the associated list of tags that will
- * preempt those assigned by the system.
+ * NOTES:
+ * - shall we support multiple service names, or instanciate multiple instances
+ * of the interface ?
+ * - interface list ?
+ * - ideally we should register here events that will trigger bonjour
+ * queries...
*/
-TYPEDEF_MAP_H(face_rules, const char *, policy_tags_t);
-#endif /* FACE_RULES_H */
+#include <hicn/ctrl/face.h> /* netdevice_t */
+
+typedef struct {
+ netdevice_t netdevice;
+ char * service_name;
+ char * service_protocol;
+ char * service_domain;
+} bonjour_cfg_t;
diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/LICENSE b/ctrl/facemgr/src/interfaces/bonjour/mdns/LICENSE
new file mode 100644
index 000000000..cf1ab25da
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/LICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+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 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.
+
+For more information, please refer to <http://unlicense.org>
diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/README.md b/ctrl/facemgr/src/interfaces/bonjour/mdns/README.md
new file mode 100644
index 000000000..1bee49c08
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/README.md
@@ -0,0 +1,9 @@
+# Public domain mDNS/DNS-SD library in C
+
+This library provides a cross-platform mDNS and DNS-DS library in C. The latest source code is always available at
+
+https://github.com/mjansson/mdns
+
+This library is put in the public domain; you can redistribute it and/or modify it without any restrictions.
+
+Created by Mattias Jansson ([@maniccoder](https://twitter.com/maniccoder))
diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c
new file mode 100644
index 000000000..a8e97e8e0
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c
@@ -0,0 +1,192 @@
+
+#ifdef _WIN32
+# define _CRT_SECURE_NO_WARNINGS 1
+#endif
+
+#include "mdns.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+#ifdef _WIN32
+# define sleep(x) Sleep(x * 1000)
+#else
+# include <netdb.h>
+#endif
+
+static char addrbuffer[64];
+static char namebuffer[256];
+static mdns_record_txt_t txtbuffer[128];
+
+static mdns_string_t
+ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr) {
+ char host[NI_MAXHOST] = {0};
+ char service[NI_MAXSERV] = {0};
+ int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in),
+ host, NI_MAXHOST, service, NI_MAXSERV,
+ NI_NUMERICSERV | NI_NUMERICHOST);
+ int len = 0;
+ if (ret == 0) {
+ if (addr->sin_port != 0)
+ len = snprintf(buffer, capacity, "%s:%s", host, service);
+ else
+ len = snprintf(buffer, capacity, "%s", host);
+ }
+ if (len >= (int)capacity)
+ len = (int)capacity - 1;
+ mdns_string_t str = {buffer, len};
+ return str;
+}
+
+static mdns_string_t
+ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr) {
+ char host[NI_MAXHOST] = {0};
+ char service[NI_MAXSERV] = {0};
+ int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in6),
+ host, NI_MAXHOST, service, NI_MAXSERV,
+ NI_NUMERICSERV | NI_NUMERICHOST);
+ int len = 0;
+ if (ret == 0) {
+ if (addr->sin6_port != 0)
+ len = snprintf(buffer, capacity, "[%s]:%s", host, service);
+ else
+ len = snprintf(buffer, capacity, "%s", host);
+ }
+ if (len >= (int)capacity)
+ len = (int)capacity - 1;
+ mdns_string_t str = {buffer, len};
+ return str;
+}
+
+static mdns_string_t
+ip_address_to_string(char* buffer, size_t capacity, const struct sockaddr* addr) {
+ if (addr->sa_family == AF_INET6)
+ return ipv6_address_to_string(buffer, capacity, (const struct sockaddr_in6*)addr);
+ return ipv4_address_to_string(buffer, capacity, (const struct sockaddr_in*)addr);
+}
+
+static int
+callback(const struct sockaddr* from,
+ mdns_entry_type_t entry, uint16_t type,
+ uint16_t rclass, uint32_t ttl,
+ const void* data, size_t size, size_t offset, size_t length,
+ void* user_data) {
+ mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from);
+ const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" :
+ ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional");
+ if (type == MDNS_RECORDTYPE_PTR) {
+ mdns_string_t namestr = mdns_record_parse_ptr(data, size, offset, length,
+ namebuffer, sizeof(namebuffer));
+ INFO("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length);
+ }
+ else if (type == MDNS_RECORDTYPE_SRV) {
+ mdns_record_srv_t srv = mdns_record_parse_srv(data, size, offset, length,
+ namebuffer, sizeof(namebuffer));
+ INFO("%.*s : %s SRV %.*s priority %d weight %d port %d\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port);
+ }
+ else if (type == MDNS_RECORDTYPE_A) {
+ struct sockaddr_in addr;
+ mdns_record_parse_a(data, size, offset, length, &addr);
+ mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), &addr);
+ INFO("%.*s : %s A %.*s\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(addrstr));
+ }
+ else if (type == MDNS_RECORDTYPE_AAAA) {
+ struct sockaddr_in6 addr;
+ mdns_record_parse_aaaa(data, size, offset, length, &addr);
+ mdns_string_t addrstr = ipv6_address_to_string(namebuffer, sizeof(namebuffer), &addr);
+ INFO("%.*s : %s AAAA %.*s\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(addrstr));
+ }
+ else if (type == MDNS_RECORDTYPE_TXT) {
+ size_t parsed = mdns_record_parse_txt(data, size, offset, length,
+ txtbuffer, sizeof(txtbuffer) / sizeof(mdns_record_txt_t));
+ for (size_t itxt = 0; itxt < parsed; ++itxt) {
+ if (txtbuffer[itxt].value.length) {
+ INFO("%.*s : %s TXT %.*s = %.*s\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(txtbuffer[itxt].key),
+ MDNS_STRING_FORMAT(txtbuffer[itxt].value));
+ }
+ else {
+ INFO("%.*s : %s TXT %.*s\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(txtbuffer[itxt].key));
+ }
+ }
+ }
+ else {
+ INFO("%.*s : %s type %u rclass 0x%x ttl %u length %d\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ type, rclass, ttl, (int)length);
+ }
+ return 0;
+}
+
+int
+main() {
+ size_t capacity = 2048;
+ void* buffer = 0;
+ void* user_data = 0;
+ size_t records;
+
+#ifdef _WIN32
+ WORD versionWanted = MAKEWORD(1, 1);
+ WSADATA wsaData;
+ WSAStartup(versionWanted, &wsaData);
+#endif
+
+ int sock = mdns_socket_open_ipv4();
+ if (sock < 0) {
+ INFO("Failed to open socket: %s\n", strerror(errno));
+ return -1;
+ }
+ INFO("Opened IPv4 socket for mDNS/DNS-SD\n");
+ buffer = malloc(capacity);
+/*
+ INFO("Sending DNS-SD discovery\n");
+ if (mdns_discovery_send(sock)) {
+ INFO("Failed to send DNS-DS discovery: %s\n", strerror(errno));
+ goto quit;
+ }
+
+ INFO("Reading DNS-SD replies\n");
+ for (int i = 0; i < 10; ++i) {
+ records = mdns_discovery_recv(sock, buffer, capacity, callback,
+ user_data);
+ sleep(1);
+ }
+ */
+
+ INFO("Sending mDNS query\n");
+ if (mdns_query_send(sock, MDNS_RECORDTYPE_PTR,
+ MDNS_STRING_CONST("_hicn._udp.local."),
+ buffer, capacity)) {
+ INFO("Failed to send mDNS query: %s\n", strerror(errno));
+ goto quit;
+ }
+
+ INFO("Reading mDNS replies\n");
+ for (int i = 0; i < 10; ++i) {
+ records = mdns_query_recv(sock, buffer, capacity, callback, user_data, 1);
+ sleep(1);
+ }
+
+quit:
+ free(buffer);
+
+ mdns_socket_close(sock);
+ INFO("Closed socket\n");
+
+#ifdef _WIN32
+ WSACleanup();
+#endif
+
+ return 0;
+}
diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h
new file mode 100644
index 000000000..ff04b5d72
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h
@@ -0,0 +1,879 @@
+/* mdns.h - mDNS/DNS-SD library - Public Domain - 2017 Mattias Jansson
+ *
+ * This library provides a cross-platform mDNS and DNS-SD library in C.
+ * The implementation is based on RFC 6762 and RFC 6763.
+ *
+ * The latest source code is always available at
+ *
+ * https://github.com/mjansson/mdns
+ *
+ * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions.
+ *
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcntl.h>
+#ifdef _WIN32
+#include <Winsock2.h>
+#include <Ws2tcpip.h>
+#define strncasecmp _strnicmp
+#else
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+
+#define MDNS_INVALID_POS ((size_t)-1)
+
+#define MDNS_STRING_CONST(s) (s), (sizeof((s))-1)
+#define MDNS_STRING_FORMAT(s) (int)((s).length), s.str
+
+enum mdns_record_type {
+ MDNS_RECORDTYPE_IGNORE = 0,
+ //Address
+ MDNS_RECORDTYPE_A = 1,
+ //Domain Name pointer
+ MDNS_RECORDTYPE_PTR = 12,
+ //Arbitrary text string
+ MDNS_RECORDTYPE_TXT = 16,
+ //IP6 Address [Thomson]
+ MDNS_RECORDTYPE_AAAA = 28,
+ //Server Selection [RFC2782]
+ MDNS_RECORDTYPE_SRV = 33
+};
+
+enum mdns_entry_type {
+ MDNS_ENTRYTYPE_ANSWER = 1,
+ MDNS_ENTRYTYPE_AUTHORITY = 2,
+ MDNS_ENTRYTYPE_ADDITIONAL = 3
+};
+
+enum mdns_class {
+ MDNS_CLASS_IN = 1
+};
+
+typedef enum mdns_record_type mdns_record_type_t;
+typedef enum mdns_entry_type mdns_entry_type_t;
+typedef enum mdns_class mdns_class_t;
+
+typedef int (* mdns_record_callback_fn)(const struct sockaddr* from,
+ mdns_entry_type_t entry, uint16_t type,
+ uint16_t rclass, uint32_t ttl,
+ const void* data, size_t size, size_t offset, size_t length,
+ void* user_data);
+
+typedef struct mdns_string_t mdns_string_t;
+typedef struct mdns_string_pair_t mdns_string_pair_t;
+typedef struct mdns_record_srv_t mdns_record_srv_t;
+typedef struct mdns_record_txt_t mdns_record_txt_t;
+
+struct mdns_string_t {
+ const char* str;
+ size_t length;
+};
+
+struct mdns_string_pair_t {
+ size_t offset;
+ size_t length;
+ int ref;
+};
+
+struct mdns_record_srv_t {
+ uint16_t priority;
+ uint16_t weight;
+ uint16_t port;
+ mdns_string_t name;
+};
+
+struct mdns_record_txt_t {
+ mdns_string_t key;
+ mdns_string_t value;
+};
+
+static int
+mdns_socket_open_ipv4(void);
+
+static int
+mdns_socket_setup_ipv4(int sock);
+
+#if 0
+static int
+mdns_socket_open_ipv6(void);
+
+
+
+static int
+mdns_socket_setup_ipv6(int sock);
+#endif
+
+static void
+mdns_socket_close(int sock);
+
+#if 0
+static int
+mdns_discovery_send(int sock);
+
+
+static size_t
+mdns_discovery_recv(int sock, void* buffer, size_t capacity,
+ mdns_record_callback_fn callback, void* user_data);
+#endif
+
+static int
+mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length,
+ void* buffer, size_t capacity);
+
+static size_t
+mdns_query_recv(int sock, void* buffer, size_t capacity,
+ mdns_record_callback_fn callback, void* user_data,
+ uint8_t one_shot);
+
+static mdns_string_t
+mdns_string_extract(const void* buffer, size_t size, size_t* offset,
+ char* str, size_t capacity);
+
+static int
+mdns_string_skip(const void* buffer, size_t size, size_t* offset);
+
+#if 0
+static int
+mdns_string_equal(const void* buffer_lhs, size_t size_lhs, size_t* ofs_lhs,
+ const void* buffer_rhs, size_t size_rhs, size_t* ofs_rhs);
+#endif
+
+static void*
+mdns_string_make(void* data, size_t capacity, const char* name, size_t length);
+
+static mdns_string_t
+mdns_record_parse_ptr(const void* buffer, size_t size, size_t offset, size_t length,
+ char* strbuffer, size_t capacity);
+
+static mdns_record_srv_t
+mdns_record_parse_srv(const void* buffer, size_t size, size_t offset, size_t length,
+ char* strbuffer, size_t capacity);
+
+static struct sockaddr_in*
+mdns_record_parse_a(const void* buffer, size_t size, size_t offset, size_t length,
+ struct sockaddr_in* addr);
+
+static struct sockaddr_in6*
+mdns_record_parse_aaaa(const void* buffer, size_t size, size_t offset, size_t length,
+ struct sockaddr_in6* addr);
+
+static size_t
+mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t length,
+ mdns_record_txt_t* records, size_t capacity);
+
+// Implementations
+
+static int
+mdns_socket_open_ipv4(void) {
+ int sock = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 0)
+ return -1;
+ if (mdns_socket_setup_ipv4(sock)) {
+ mdns_socket_close(sock);
+ return -1;
+ }
+ return sock;
+}
+
+static int
+mdns_socket_setup_ipv4(int sock) {
+ struct sockaddr_in saddr;
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = INADDR_ANY;
+#ifdef __APPLE__
+ saddr.sin_len = sizeof(saddr);
+#endif
+
+ if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr)))
+ return -1;
+
+#ifdef _WIN32
+ unsigned long param = 1;
+ ioctlsocket(sock, FIONBIO, &param);
+#else
+ const int flags = fcntl(sock, F_GETFL, 0);
+ fcntl(sock, F_SETFL, flags | O_NONBLOCK);
+#endif
+
+ unsigned char ttl = 1;
+ unsigned char loopback = 1;
+ struct ip_mreq req;
+
+ setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof(ttl));
+ setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, sizeof(loopback));
+
+ memset(&req, 0, sizeof(req));
+ req.imr_multiaddr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U));
+ req.imr_interface.s_addr = INADDR_ANY;
+ if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&req, sizeof(req)))
+ return -1;
+
+ return 0;
+}
+
+#if 0
+static int
+mdns_socket_open_ipv6(void) {
+ int sock = (int)socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 0)
+ return -1;
+ if (mdns_socket_setup_ipv6(sock)) {
+ mdns_socket_close(sock);
+ return -1;
+ }
+ return sock;
+}
+
+
+static int
+mdns_socket_setup_ipv6(int sock) {
+ struct sockaddr_in6 saddr;
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.sin6_family = AF_INET6;
+ saddr.sin6_addr = in6addr_any;
+#ifdef __APPLE__
+ saddr.sin6_len = sizeof(saddr);
+#endif
+
+ if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr)))
+ return -1;
+
+#ifdef _WIN32
+ unsigned long param = 1;
+ ioctlsocket(sock, FIONBIO, &param);
+#else
+ const int flags = fcntl(sock, F_GETFL, 0);
+ fcntl(sock, F_SETFL, flags | O_NONBLOCK);
+#endif
+
+ int hops = 1;
+ unsigned int loopback = 1;
+ struct ipv6_mreq req;
+
+ setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char*)&hops, sizeof(hops));
+ setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const char*)&loopback, sizeof(loopback));
+
+ memset(&req, 0, sizeof(req));
+ req.ipv6mr_multiaddr.s6_addr[0] = 0xFF;
+ req.ipv6mr_multiaddr.s6_addr[1] = 0x02;
+ req.ipv6mr_multiaddr.s6_addr[15] = 0xFB;
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char*)&req, sizeof(req)))
+ return -1;
+
+ return 0;
+}
+#endif
+
+static void
+mdns_socket_close(int sock) {
+#ifdef _WIN32
+ closesocket(sock);
+#else
+ close(sock);
+#endif
+}
+
+static int
+mdns_is_string_ref(uint8_t val) {
+ return (0xC0 == (val & 0xC0));
+}
+
+static mdns_string_pair_t
+mdns_get_next_substring(const void* rawdata, size_t size, size_t offset) {
+ const uint8_t* buffer = rawdata;
+ mdns_string_pair_t pair = {MDNS_INVALID_POS, 0, 0};
+ if (!buffer[offset]) {
+ pair.offset = offset;
+ return pair;
+ }
+ if (mdns_is_string_ref(buffer[offset])) {
+ if (size < offset + 2)
+ return pair;
+
+ offset = (((size_t)(0x3f & buffer[offset]) << 8) | (size_t)buffer[offset + 1]);
+ if (offset >= size)
+ return pair;
+
+ pair.ref = 1;
+ }
+
+ size_t length = (size_t)buffer[offset++];
+ if (size < offset + length)
+ return pair;
+
+ pair.offset = offset;
+ pair.length = length;
+
+ return pair;
+}
+
+static int
+mdns_string_skip(const void* buffer, size_t size, size_t* offset) {
+ size_t cur = *offset;
+ mdns_string_pair_t substr;
+ do {
+ substr = mdns_get_next_substring(buffer, size, cur);
+ if (substr.offset == MDNS_INVALID_POS)
+ return 0;
+ if (substr.ref) {
+ *offset = cur + 2;
+ return 1;
+ }
+ cur = substr.offset + substr.length;
+ }
+ while (substr.length);
+
+ *offset = cur + 1;
+ return 1;
+}
+
+#if 0
+static int
+mdns_string_equal(const void* buffer_lhs, size_t size_lhs, size_t* ofs_lhs,
+ const void* buffer_rhs, size_t size_rhs, size_t* ofs_rhs) {
+ size_t lhs_cur = *ofs_lhs;
+ size_t rhs_cur = *ofs_rhs;
+ size_t lhs_end = MDNS_INVALID_POS;
+ size_t rhs_end = MDNS_INVALID_POS;
+ mdns_string_pair_t lhs_substr;
+ mdns_string_pair_t rhs_substr;
+ do {
+ lhs_substr = mdns_get_next_substring(buffer_lhs, size_lhs, lhs_cur);
+ rhs_substr = mdns_get_next_substring(buffer_rhs, size_rhs, rhs_cur);
+ if ((lhs_substr.offset == MDNS_INVALID_POS) || (rhs_substr.offset == MDNS_INVALID_POS))
+ return 0;
+ if (lhs_substr.length != rhs_substr.length)
+ return 0;
+ if (strncasecmp((const char*)buffer_rhs + rhs_substr.offset,
+ (const char*)buffer_lhs + lhs_substr.offset, rhs_substr.length))
+ return 0;
+ if (lhs_substr.ref && (lhs_end == MDNS_INVALID_POS))
+ lhs_end = lhs_cur + 2;
+ if (rhs_substr.ref && (rhs_end == MDNS_INVALID_POS))
+ rhs_end = rhs_cur + 2;
+ lhs_cur = lhs_substr.offset + lhs_substr.length;
+ rhs_cur = rhs_substr.offset + rhs_substr.length;
+ }
+ while (lhs_substr.length);
+
+ if (lhs_end == MDNS_INVALID_POS)
+ lhs_end = lhs_cur + 1;
+ *ofs_lhs = lhs_end;
+
+ if (rhs_end == MDNS_INVALID_POS)
+ rhs_end = rhs_cur + 1;
+ *ofs_rhs = rhs_end;
+
+ return 1;
+}
+#endif
+
+static mdns_string_t
+mdns_string_extract(const void* buffer, size_t size, size_t* offset,
+ char* str, size_t capacity) {
+ size_t cur = *offset;
+ size_t end = MDNS_INVALID_POS;
+ mdns_string_pair_t substr;
+ mdns_string_t result = {str, 0};
+ char* dst = str;
+ size_t remain = capacity;
+ do {
+ substr = mdns_get_next_substring(buffer, size, cur);
+ if (substr.offset == MDNS_INVALID_POS)
+ return result;
+ if (substr.ref && (end == MDNS_INVALID_POS))
+ end = cur + 2;
+ if (substr.length) {
+ size_t to_copy = (substr.length < remain) ? substr.length : remain;
+ memcpy(dst, (const char*)buffer + substr.offset, to_copy);
+ dst += to_copy;
+ remain -= to_copy;
+ if (remain) {
+ *dst++ = '.';
+ --remain;
+ }
+ }
+ cur = substr.offset + substr.length;
+ }
+ while (substr.length);
+
+ if (end == MDNS_INVALID_POS)
+ end = cur + 1;
+ *offset = end;
+
+ result.length = capacity - remain;
+ return result;
+}
+
+static size_t
+mdns_string_find(const char* str, size_t length, char c, size_t offset) {
+ const void* found;
+ if (offset >= length)
+ return MDNS_INVALID_POS;
+ found = memchr(str + offset, c, length - offset);
+ if (found)
+ return (size_t)((const char*)found - str);
+ return MDNS_INVALID_POS;
+}
+
+static void*
+mdns_string_make(void* data, size_t capacity, const char* name, size_t length) {
+ size_t pos = 0;
+ size_t last_pos = 0;
+ size_t remain = capacity;
+ unsigned char* dest = data;
+ while ((last_pos < length) && ((pos = mdns_string_find(name, length, '.', last_pos)) != MDNS_INVALID_POS)) {
+ size_t sublength = pos - last_pos;
+ if (sublength < remain) {
+ *dest = (unsigned char)sublength;
+ memcpy(dest + 1, name + last_pos, sublength);
+ dest += sublength + 1;
+ remain -= sublength + 1;
+ }
+ else {
+ return 0;
+ }
+ last_pos = pos + 1;
+ }
+ if (last_pos < length) {
+ size_t sublength = length - last_pos;
+ if (sublength < capacity) {
+ *dest = (unsigned char)sublength;
+ memcpy(dest + 1, name + last_pos, sublength);
+ dest += sublength + 1;
+ remain -= sublength + 1;
+ }
+ else {
+ return 0;
+ }
+ }
+ if (!remain)
+ return 0;
+ *dest++ = 0;
+ return dest;
+}
+
+static size_t
+mdns_records_parse(const struct sockaddr* from, const void* buffer, size_t size, size_t* offset,
+ mdns_entry_type_t type, size_t records, mdns_record_callback_fn callback,
+ void* user_data) {
+ size_t parsed = 0;
+ int do_callback = 1;
+ for (size_t i = 0; i < records; ++i) {
+ mdns_string_skip(buffer, size, offset);
+ const uint16_t* data = (const uint16_t*)((const char*)buffer + (*offset));
+
+ uint16_t rtype = ntohs(*data++);
+ uint16_t rclass = ntohs(*data++);
+ uint32_t ttl = ntohs(*(const uint32_t*)(const void*)data); data += 2;
+ uint16_t length = ntohs(*data++);
+
+ *offset += 10;
+
+ if (do_callback) {
+ ++parsed;
+ if (callback(from, type, rtype, rclass, ttl, buffer, size, *offset, length,
+ user_data))
+ do_callback = 0;
+ }
+
+ *offset += length;
+ }
+ return parsed;
+}
+
+static const uint8_t mdns_services_query[] = {
+ // Transaction ID
+ 0x00, 0x00,
+ // Flags
+ 0x00, 0x00,
+ // 1 question
+ 0x00, 0x01,
+ // No answer, authority or additional RRs
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ // _services._dns-sd._udp.local.
+ 0x09, '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's',
+ 0x07, '_', 'd', 'n', 's', '-', 's', 'd',
+ 0x04, '_', 'u', 'd', 'p',
+ 0x05, 'l', 'o', 'c', 'a', 'l',
+ 0x00,
+ // PTR record
+ 0x00, MDNS_RECORDTYPE_PTR,
+ // QU (unicast response) and class IN
+ 0x80, MDNS_CLASS_IN
+};
+
+#if 0
+static int
+mdns_discovery_send(int sock) {
+ struct sockaddr_storage addr_storage;
+ struct sockaddr_in addr;
+ struct sockaddr_in6 addr6;
+ struct sockaddr* saddr = (struct sockaddr*)&addr_storage;
+ socklen_t saddrlen = sizeof(struct sockaddr_storage);
+ if (getsockname(sock, saddr, &saddrlen))
+ return -1;
+ if (saddr->sa_family == AF_INET6) {
+ memset(&addr6, 0, sizeof(struct sockaddr_in6));
+ addr6.sin6_family = AF_INET6;
+#ifdef __APPLE__
+ addr6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+ addr6.sin6_addr.s6_addr[0] = 0xFF;
+ addr6.sin6_addr.s6_addr[1] = 0x02;
+ addr6.sin6_addr.s6_addr[15] = 0xFB;
+ addr6.sin6_port = htons((unsigned short)5353);
+ saddr = (struct sockaddr*)&addr6;
+ saddrlen = sizeof(struct sockaddr_in6);
+ }
+ else {
+ memset(&addr, 0, sizeof(struct sockaddr_in));
+ addr.sin_family = AF_INET;
+#ifdef __APPLE__
+ addr.sin_len = sizeof(struct sockaddr_in);
+#endif
+ addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U));
+ addr.sin_port = htons((unsigned short)5353);
+ saddr = (struct sockaddr*)&addr;
+ saddrlen = sizeof(struct sockaddr_in);
+ }
+
+ if (sendto(sock, mdns_services_query, sizeof(mdns_services_query), 0,
+ saddr, saddrlen) < 0)
+ return -1;
+ return 0;
+}
+
+static size_t
+mdns_discovery_recv(int sock, void* buffer, size_t capacity,
+ mdns_record_callback_fn callback, void* user_data) {
+ struct sockaddr_in6 addr;
+ struct sockaddr* saddr = (struct sockaddr*)&addr;
+ memset(&addr, 0, sizeof(addr));
+ saddr->sa_family = AF_INET;
+#ifdef __APPLE__
+ saddr->sa_len = sizeof(addr);
+#endif
+ socklen_t addrlen = sizeof(addr);
+ int ret = recvfrom(sock, buffer, capacity, 0,
+ saddr, &addrlen);
+ if (ret <= 0)
+ return 0;
+
+ size_t data_size = (size_t)ret;
+ size_t records = 0;
+ uint16_t* data = (uint16_t*)buffer;
+
+ uint16_t transaction_id = ntohs(*data++);
+ uint16_t flags = ntohs(*data++);
+ uint16_t questions = ntohs(*data++);
+ uint16_t answer_rrs = ntohs(*data++);
+ uint16_t authority_rrs = ntohs(*data++);
+ uint16_t additional_rrs = ntohs(*data++);
+
+ if (transaction_id || (flags != 0x8400))
+ return 0; //Not a reply to our question
+
+ if (questions > 1)
+ return 0;
+
+ int i;
+ for (i = 0; i < questions; ++i) {
+ size_t ofs = (size_t)((char*)data - (char*)buffer);
+ size_t verify_ofs = 12;
+ //Verify it's our question, _services._dns-sd._udp.local.
+ if (!mdns_string_equal(buffer, data_size, &ofs,
+ mdns_services_query, sizeof(mdns_services_query), &verify_ofs))
+ return 0;
+ data = (uint16_t*)((char*)buffer + ofs);
+
+ uint16_t type = ntohs(*data++);
+ uint16_t rclass = ntohs(*data++);
+
+ //Make sure we get a reply based on our PTR question for class IN
+ if ((type != MDNS_RECORDTYPE_PTR) || ((rclass & 0x7FFF) != MDNS_CLASS_IN))
+ return 0;
+ }
+
+ int do_callback = 1;
+ for (i = 0; i < answer_rrs; ++i) {
+ size_t ofs = (size_t)((char*)data - (char*)buffer);
+ size_t verify_ofs = 12;
+ //Verify it's an answer to our question, _services._dns-sd._udp.local.
+ int is_answer = mdns_string_equal(buffer, data_size, &ofs,
+ mdns_services_query, sizeof(mdns_services_query), &verify_ofs);
+ data = (uint16_t*)((char*)buffer + ofs);
+
+ uint16_t type = ntohs(*data++);
+ uint16_t rclass = ntohs(*data++);
+ uint32_t ttl = ntohl(*(uint32_t*)(void*)data); data += 2;
+ uint16_t length = ntohs(*data++);
+
+ if (is_answer && do_callback) {
+ ++records;
+ if (callback(saddr, MDNS_ENTRYTYPE_ANSWER, type, rclass, ttl, buffer,
+ data_size, (size_t)((char*)data - (char*)buffer), length,
+ user_data))
+ do_callback = 0;
+ }
+ data = (void*)((char*)data + length);
+ }
+
+ size_t offset = (size_t)((char*)data - (char*)buffer);
+ records += mdns_records_parse(saddr, buffer, data_size, &offset,
+ MDNS_ENTRYTYPE_AUTHORITY, authority_rrs,
+ callback, user_data);
+ records += mdns_records_parse(saddr, buffer, data_size, &offset,
+ MDNS_ENTRYTYPE_ADDITIONAL, additional_rrs,
+ callback, user_data);
+
+ return records;
+}
+#endif
+
+static uint16_t mdns_transaction_id = 0;
+
+static int
+mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length,
+ void* buffer, size_t capacity) {
+ if (capacity < (17 + length))
+ return -1;
+
+ uint16_t* data = buffer;
+ //Transaction ID
+ *data++ = htons(++mdns_transaction_id);
+ //Flags
+ *data++ = 0;
+ //Questions
+ *data++ = htons(1);
+ //No answer, authority or additional RRs
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ //Name string
+ data = mdns_string_make(data, capacity - 17, name, length);
+ if (!data)
+ return -1;
+ //Record type
+ *data++ = htons(type);
+ //! Unicast response, class IN
+ *data++ = htons(0x8000U | MDNS_CLASS_IN);
+
+ struct sockaddr_storage addr_storage;
+ struct sockaddr_in addr;
+ struct sockaddr_in6 addr6;
+ struct sockaddr* saddr = (struct sockaddr*)&addr_storage;
+ socklen_t saddrlen = sizeof(struct sockaddr_storage);
+ if (getsockname(sock, saddr, &saddrlen))
+ return -1;
+ if (saddr->sa_family == AF_INET6) {
+ memset(&addr6, 0, sizeof(struct sockaddr_in6));
+ addr6.sin6_family = AF_INET6;
+#ifdef __APPLE__
+ addr6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+ addr6.sin6_addr.s6_addr[0] = 0xFF;
+ addr6.sin6_addr.s6_addr[1] = 0x02;
+ addr6.sin6_addr.s6_addr[15] = 0xFB;
+ addr6.sin6_port = htons((unsigned short)5353);
+ saddr = (struct sockaddr*)&addr6;
+ saddrlen = sizeof(struct sockaddr_in6);
+ }
+ else {
+ memset(&addr, 0, sizeof(struct sockaddr_in));
+ addr.sin_family = AF_INET;
+#ifdef __APPLE__
+ addr.sin_len = sizeof(struct sockaddr_in);
+#endif
+ addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U));
+ addr.sin_port = htons((unsigned short)5353);
+ saddr = (struct sockaddr*)&addr;
+ saddrlen = sizeof(struct sockaddr_in);
+ }
+
+ if (sendto(sock, buffer, (char*)data - (char*)buffer, 0,
+ saddr, saddrlen) < 0)
+ return -1;
+ return 0;
+}
+
+static size_t
+mdns_query_recv(int sock, void* buffer, size_t capacity,
+ mdns_record_callback_fn callback, void* user_data,
+ uint8_t one_shot) {
+ struct sockaddr_in6 addr;
+ struct sockaddr* saddr = (struct sockaddr*)&addr;
+ memset(&addr, 0, sizeof(addr));
+ saddr->sa_family = AF_INET;
+#ifdef __APPLE__
+ saddr->sa_len = sizeof(addr);
+#endif
+ socklen_t addrlen = sizeof(addr);
+ int ret = recvfrom(sock, buffer, capacity, 0,
+ saddr, &addrlen);
+ if (ret <= 0)
+ return 0;
+
+ size_t data_size = (size_t)ret;
+ uint16_t* data = (uint16_t*)buffer;
+
+ uint16_t transaction_id = ntohs(*data++);
+ ++data;// uint16_t flags = ntohs(*data++);
+ uint16_t questions = ntohs(*data++);
+ uint16_t answer_rrs = ntohs(*data++);
+ uint16_t authority_rrs = ntohs(*data++);
+ uint16_t additional_rrs = ntohs(*data++);
+
+ if (one_shot && transaction_id != mdns_transaction_id)// || (flags != 0x8400))
+ return 0; //Not a reply to our last question
+
+ if (questions > 1)
+ return 0;
+
+ //Skip questions part
+ int i;
+ for (i = 0; i < questions; ++i) {
+ size_t ofs = (size_t)((char*)data - (char*)buffer);
+ if (!mdns_string_skip(buffer, data_size, &ofs))
+ return 0;
+ data = (void*)((char*)buffer + ofs);
+ ++data;
+ ++data;
+ }
+
+ size_t records = 0;
+ size_t offset = (size_t)((char*)data - (char*)buffer);
+ records += mdns_records_parse(saddr, buffer, data_size, &offset,
+ MDNS_ENTRYTYPE_ANSWER, answer_rrs,
+ callback, user_data);
+ records += mdns_records_parse(saddr, buffer, data_size, &offset,
+ MDNS_ENTRYTYPE_AUTHORITY, authority_rrs,
+ callback, user_data);
+ records += mdns_records_parse(saddr, buffer, data_size, &offset,
+ MDNS_ENTRYTYPE_ADDITIONAL, additional_rrs,
+ callback, user_data);
+ return records;
+}
+
+static mdns_string_t
+mdns_record_parse_ptr(const void* buffer, size_t size, size_t offset, size_t length,
+ char* strbuffer, size_t capacity) {
+ //PTR record is just a string
+ if ((size >= offset + length) && (length >= 2))
+ return mdns_string_extract(buffer, size, &offset, strbuffer, capacity);
+ mdns_string_t empty = {0, 0};
+ return empty;
+}
+
+static mdns_record_srv_t
+mdns_record_parse_srv(const void* buffer, size_t size, size_t offset, size_t length,
+ char* strbuffer, size_t capacity) {
+ mdns_record_srv_t srv;
+ memset(&srv, 0, sizeof(mdns_record_srv_t));
+ // Read the priority, weight, port number and the discovery name
+ // SRV record format (http://www.ietf.org/rfc/rfc2782.txt):
+ // 2 bytes network-order unsigned priority
+ // 2 bytes network-order unsigned weight
+ // 2 bytes network-order unsigned port
+ // string: discovery (domain) name, minimum 2 bytes when compressed
+ if ((size >= offset + length) && (length >= 8)) {
+ const uint16_t* recorddata = (const uint16_t*)((const char*)buffer + offset);
+ srv.priority = ntohs(*recorddata++);
+ srv.weight = ntohs(*recorddata++);
+ srv.port = ntohs(*recorddata++);
+ offset += 6;
+ srv.name = mdns_string_extract(buffer, size, &offset, strbuffer, capacity);
+ }
+ return srv;
+}
+
+static struct sockaddr_in*
+mdns_record_parse_a(const void* buffer, size_t size, size_t offset, size_t length,
+ struct sockaddr_in* addr) {
+ memset(addr, 0, sizeof(struct sockaddr_in));
+ addr->sin_family = AF_INET;
+#ifdef __APPLE__
+ addr->sin_len = sizeof(struct sockaddr_in);
+#endif
+ if ((size >= offset + length) && (length == 4))
+ addr->sin_addr.s_addr = *(const uint32_t*)((const char*)buffer + offset);
+ return addr;
+}
+
+static struct sockaddr_in6*
+mdns_record_parse_aaaa(const void* buffer, size_t size, size_t offset, size_t length,
+ struct sockaddr_in6* addr) {
+ memset(addr, 0, sizeof(struct sockaddr_in6));
+ addr->sin6_family = AF_INET6;
+#ifdef __APPLE__
+ addr->sin6_len = sizeof(struct sockaddr_in6);
+#endif
+ if ((size >= offset + length) && (length == 16))
+ addr->sin6_addr = *(const struct in6_addr*)((const char*)buffer + offset);
+ return addr;
+}
+
+static size_t
+mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t length,
+ mdns_record_txt_t* records, size_t capacity) {
+ size_t parsed = 0;
+ const char* strdata;
+ size_t separator, sublength;
+ size_t end = offset + length;
+
+ if (size < end)
+ end = size;
+
+ while ((offset < end) && (parsed < capacity)) {
+ strdata = (const char*)buffer + offset;
+ sublength = *(const unsigned char*)strdata;
+
+ ++strdata;
+ offset += sublength + 1;
+
+ separator = 0;
+ for (size_t c = 0; c < sublength; ++c) {
+ //DNS-SD TXT record keys MUST be printable US-ASCII, [0x20, 0x7E]
+ if ((strdata[c] < 0x20) || (strdata[c] > 0x7E))
+ break;
+ if (strdata[c] == '=') {
+ separator = c;
+ break;
+ }
+ }
+
+ if (!separator)
+ continue;
+
+ if (separator < sublength) {
+ records[parsed].key.str = strdata;
+ records[parsed].key.length = separator;
+ records[parsed].value.str = strdata + separator + 1;
+ records[parsed].value.length = sublength - (separator + 1);
+ }
+ else {
+ records[parsed].key.str = strdata;
+ records[parsed].key.length = sublength;
+ }
+
+ ++parsed;
+ }
+
+ return parsed;
+}
+
+#ifdef _WIN32
+#undef strncasecmp
+#endif
diff --git a/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt b/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt
index 1af3b4b2a..05276bc5a 100644
--- a/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt
+++ b/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt
@@ -12,6 +12,7 @@
# limitations under the License.
list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/dummy.h
)
list(APPEND SOURCE_FILES
diff --git a/ctrl/facemgr/src/interfaces/dummy/dummy.c b/ctrl/facemgr/src/interfaces/dummy/dummy.c
index b0c558388..6a21792a2 100644
--- a/ctrl/facemgr/src/interfaces/dummy/dummy.c
+++ b/ctrl/facemgr/src/interfaces/dummy/dummy.c
@@ -19,31 +19,101 @@
*/
#include <stdlib.h>
+#include <unistd.h> // close
+
+#include <hicn/facemgr.h>
-#include "../../interface.h"
#include "../../common.h"
-#include "../../event.h"
-#include "../../face.h"
-#include "../../facemgr.h"
+#include "../../facelet.h"
+#include "../../interface.h"
+
+#include "dummy.h"
#define DEFAULT_PORT 9695
-int dummy_initialize(interface_t * interface, face_rules_t * rules, void **pdata) {
- ip_address_t local = IPV4_LOOPBACK;
- ip_address_t remote = IPV4_LOOPBACK;
- face_t * face = face_create_udp(&local, DEFAULT_PORT, &remote, DEFAULT_PORT, AF_INET);
- event_raise(EVENT_TYPE_CREATE, face, interface);
- return FACEMGR_SUCCESS;
+#define UNUSED(x) ((void)x)
+
+/*
+ * Internal data
+ */
+typedef struct {
+ /* The configuration data will likely be allocated on the stack (or should
+ * be freed) by the caller, we recommend to make a copy of this data.
+ * This copy can further be altered with default values.
+ */
+ dummy_cfg_t cfg;
+
+ /* ... */
+
+ int fd; /* Sample internal data: file descriptor */
+} dummy_data_t;
+
+int dummy_initialize(interface_t * interface, void * cfg)
+{
+ dummy_data_t * data = malloc(sizeof(dummy_data_t));
+ if (!data)
+ goto ERR_MALLOC;
+ interface->data = data;
+
+ /* Use default values for unspecified configuration parameters */
+ if (cfg) {
+ data->cfg = *(dummy_cfg_t *)cfg;
+ } else {
+ memset(&data->cfg, 0, sizeof(data->cfg));
+ }
+
+ /* ... */
+
+ data->fd = 0;
+
+ /* ... */
+
+ /*
+ * We should return a negative value in case of error, and a positive value
+ * otherwise:
+ * - a file descriptor (>0) will be added to the event loop; or
+ * - 0 if we don't use any file descriptor
+ */
+ return data->fd;
+
+ERR_MALLOC:
+ return -1;
+}
+
+int dummy_finalize(interface_t * interface)
+{
+ dummy_data_t * data = (dummy_data_t*)interface->data;
+
+ if (data->fd > 0)
+ close(data->fd);
+
+ return 0;
}
-int dummy_finalize(interface_t * interface) {
- return FACEMGR_SUCCESS;
+int dummy_callback(interface_t * interface)
+{
+ dummy_data_t * data = (dummy_data_t*)interface->data;
+ UNUSED(data);
+
+ /* ... */
+
+ return 0;
+}
+
+int dummy_on_event(interface_t * interface, const facelet_t * facelet)
+{
+ dummy_data_t * data = (dummy_data_t*)interface->data;
+ UNUSED(data);
+
+ /* ... */
+
+ return 0;
}
interface_ops_t dummy_ops = {
.type = "dummy",
- .is_singleton = true,
.initialize = dummy_initialize,
.finalize = dummy_finalize,
- .on_event = NULL,
+ .callback = dummy_callback,
+ .on_event = dummy_on_event,
};
diff --git a/ctrl/facemgr/src/interface_ops_map.h b/ctrl/facemgr/src/interfaces/dummy/dummy.h
index 2d590390a..22fe5d1a6 100644
--- a/ctrl/facemgr/src/interface_ops_map.h
+++ b/ctrl/facemgr/src/interfaces/dummy/dummy.h
@@ -13,12 +13,22 @@
* limitations under the License.
*/
-#ifndef INTERFACE_OPS_MAP_H
-#define INTERFACE_OPS_MAP_H
+/**
+ * \file dummy.h
+ * \brief Dummy interface
+ *
+ * This class serves as a template to implement new face maanger interfaces, and
+ * can be used for test purposes.
+ */
-#include "interface.h"
-#include "util/map.h"
+#ifndef FACEMGR_INTERFACE_DUMMY_H
+#define FACEMGR_INTERFACE_DUMMY_H
-TYPEDEF_MAP_H(interface_ops_map, const char *, interface_ops_t *);
+/*
+ * Configuration data
+ */
+typedef struct {
+ /* ... */
+} dummy_cfg_t;
-#endif /* INTERFACE_OPS_MAP_H */
+#endif /* FACEMGR_INTERFACE_DUMMY_H */
diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
index 85694573d..e42c6c6ae 100644
--- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
+++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
@@ -18,27 +18,70 @@
* \brief hICN light interface
*/
#include <stdbool.h>
-#include <stdlib.h> // arc4random [random, rand]
#include <stdio.h> // snprintf
#include <time.h> // time
#include <hicn/ctrl.h>
+#include <hicn/facemgr.h>
+#include <hicn/util/ip_address.h>
+#include <hicn/util/log.h>
-#include "../../facemgr.h"
+#include "../../facelet.h"
#include "../../interface.h"
-#include "../../util/ip_address.h"
-#include "../../util/log.h"
#include "../../util/map.h"
-#include "../../event.h"
#define DEFAULT_ROUTE_COST 0
+typedef enum {
+ HL_STATE_UNDEFINED,
+ HL_STATE_FACES_SENT,
+ HL_STATE_DONE,
+} hl_state_t;
+
typedef struct {
hc_sock_t * s;
- bool busy;
+ hl_state_t state;
} hl_data_t;
-int hl_initialize(interface_t * interface, face_rules_t * rules, void ** pdata)
+int hl_process_state(interface_t * interface)
+{
+ hl_data_t * data = (hl_data_t *)interface->data;
+
+ hc_data_t * faces;
+#if 0
+ char buf[MAXSZ_FACE];
+#endif
+
+ switch(data->state)
+ {
+ case HL_STATE_UNDEFINED:
+ if (hc_face_list(data->s, &faces) < 0) {
+ /* Blocking call */
+ printf("Could not retrieve face list\n");
+ return -1;
+ }
+ foreach_face(f, faces) {
+#if 0
+ hc_face_snprintf(buf, MAXSZ_FACE, f);
+ printf("Face: %s\n", buf);
+#endif
+ facelet_t * facelet = facelet_create_from_face(&f->face);
+ facelet_set_event(facelet, FACELET_EVENT_GET);
+ facelet_raise_event(facelet, interface);
+ }
+ break;
+
+ case HL_STATE_FACES_SENT:
+ break;
+
+ default: /* HL_STATE_DONE never called */
+ break;
+ }
+
+ return 0;
+}
+
+int hl_initialize(interface_t * interface, void * cfg)
{
hl_data_t * data = malloc(sizeof(hl_data_t));
if (!data) {
@@ -57,51 +100,52 @@ int hl_initialize(interface_t * interface, face_rules_t * rules, void ** pdata)
goto ERR_CONNECT;
}
- data->busy = false;
+ data->state = HL_STATE_UNDEFINED;
+
+ interface->data = data;
- *pdata = data;
+ hl_process_state(interface);
- return FACEMGR_SUCCESS;
+ return 0;
ERR_CONNECT:
hc_sock_free(data->s);
ERR_SOCK:
free(data);
ERR_MALLOC:
- return FACEMGR_FAILURE;
+ return -1;
}
int hl_finalize(interface_t * interface)
{
//hc_data_t * data = interface->data;
//hc_sock_close(data->s);
- return FACEMGR_SUCCESS;
+ return 0;
}
-int hl_on_event(interface_t * interface, const event_t * event)
+int hl_on_event(interface_t * interface, const facelet_t * facelet)
{
- hc_face_t face;
+ hc_face_t hc_face;
hc_route_t route;
int rc;
hl_data_t * data = (hl_data_t *)interface->data;
- /* XXX We need a queue or a socket pool to process concurrent events */
- if (data->busy) {
- ERROR("[hicn_light] Busy !");
- return FACEMGR_FAILURE;
- }
+ face_t * face = NULL;
+ if (facelet_get_face(facelet, &face) < 0)
+ return -1;
+
+ switch(facelet_get_event(facelet)) {
- switch(event->type) {
- case EVENT_TYPE_CREATE:
+ case FACELET_EVENT_CREATE:
/* Create face */
- face.face = *event->face;
- rc = hc_face_create(data->s, &face);
+ hc_face.face = *face;
+ rc = hc_face_create(data->s, &hc_face);
if (rc < 0) {
ERROR("Failed to create face\n");
goto ERR;
}
- DEBUG("Created face id=%d\n", face.id);
+ INFO("Created face id=%d\n", hc_face.id);
#if 0
/* Add default route v4 */
@@ -134,88 +178,84 @@ int hl_on_event(interface_t * interface, const event_t * event)
}
#endif
-#if 1
- /* We add routes based on face tags */
-
- if (policy_tags_has(event->face->tags, POLICY_TAG_TRUSTED)) {
- route = (hc_route_t) {
- .face_id = face.id,
- .family = AF_INET6,
- .len = 16,
- .cost = DEFAULT_ROUTE_COST,
- };
- if (ip_address_pton("b001::", &route.remote_addr) < 0) {
- ERROR("Failed to convert prefix");
- goto ERR;
- }
- if (hc_route_create(data->s, &route) < 0) {
- ERROR("Failed to create hICN/IPv6 route");
- goto ERR;
- }
+ /* Adding default route */
+ route = (hc_route_t) {
+ .face_id = hc_face.id,
+ .family = AF_INET6,
+ .len = 0,
+ .cost = DEFAULT_ROUTE_COST,
+ };
+ if (ip_address_pton("::", &route.remote_addr) < 0) {
+ ERROR("Failed to convert prefix");
+ goto ERR;
+ }
+ if (hc_route_create(data->s, &route) < 0) {
+ ERROR("Failed to create hICN/IPv6 route");
+ goto ERR;
+ }
- route = (hc_route_t) {
- .face_id = face.id,
- .family = AF_INET6,
- .len = 16,
- .cost = DEFAULT_ROUTE_COST,
- };
- if (ip_address_pton("d001::", &route.remote_addr) < 0) {
- ERROR("Failed to convert prefix");
+ break;
+
+ case FACELET_EVENT_DELETE:
+ /* Removing a face should also remove associated routes */
+ /* Create face */
+ hc_face.face = *face;
+ rc = hc_face_delete(data->s, &hc_face);
+ if (rc < 0) {
+ ERROR("Failed to delete face\n");
+ goto ERR;
+ }
+ INFO("Deleted face id=%d\n", hc_face.id);
+ break;
+
+ case FACELET_EVENT_UPDATE:
+ /* Currently, only admin_state is supported */
+ if (facelet_get_admin_state_status(facelet) == FACELET_ATTR_STATUS_DIRTY) {
+ hc_face.face = *face;
+ hc_face_t * face_found;
+ rc = hc_face_get(data->s, &hc_face, &face_found);
+ if (rc < 0) {
+ ERROR("Failed to find face\n");
goto ERR;
}
- if (hc_route_create(data->s, &route) < 0) {
- ERROR("Failed to create hICN/IPv6 route");
+ if (!face_found) {
+ ERROR("Face to update has not been found");
goto ERR;
}
+ char conn_id_or_name[NAME_LEN];
+ snprintf(conn_id_or_name, NAME_LEN, "%d", face_found->id);
+ free(face_found);
+ printf("Face id = %d\n", face_found->id);
- } else {
-
- route = (hc_route_t) {
- .face_id = face.id,
- .family = AF_INET6,
- .len = 16,
- .cost = DEFAULT_ROUTE_COST,
- };
- if (ip_address_pton("c001::", &route.remote_addr) < 0) {
- ERROR("Failed to convert prefix");
+ face_state_t admin_state;
+ if (facelet_get_admin_state(facelet, &admin_state) < 0) {
+ ERROR("Failed to retrieve facelet admin state");
goto ERR;
}
- if (hc_route_create(data->s, &route) < 0) {
- ERROR("Failed to create hICN/IPv6 route");
+
+ printf("Setting admin state");
+ if (hc_connection_set_admin_state(data->s, conn_id_or_name, admin_state) < 0) {
+ ERROR("Failed to update admin state");
goto ERR;
}
+ INFO("Admin state updated");
}
-#endif
-
- break;
-
- case EVENT_TYPE_DELETE:
- /* Removing a face should also remove associated routes */
- /* Create face */
- face.face = *event->face;
- rc = hc_face_delete(data->s, &face);
- if (rc < 0) {
- ERROR("Failed to delete face\n");
- goto ERR;
- }
- INFO("Deleted face id=%d\n", face.id);
break;
default:
- ERROR("Unknown event %s\n", event_type_str[event->type]);
+ ERROR("Unknown event %s\n", facelet_event_str[facelet_get_event(facelet)]);
/* Unsupported events */
goto ERR;
}
- return FACEMGR_SUCCESS;
+ return 0;
ERR:
- return FACEMGR_FAILURE;
+ return -1;
}
const interface_ops_t hicn_light_ops = {
.type = "hicn_light",
- .is_singleton = false,
.initialize = hl_initialize,
.finalize = hl_finalize,
.on_event = hl_on_event,
diff --git a/ctrl/facemgr/src/interfaces/netlink/netlink.c b/ctrl/facemgr/src/interfaces/netlink/netlink.c
index 5bf0baf9f..08cbe4d3b 100644
--- a/ctrl/facemgr/src/interfaces/netlink/netlink.c
+++ b/ctrl/facemgr/src/interfaces/netlink/netlink.c
@@ -18,34 +18,120 @@
* \brief Netlink interface
*/
+#include <assert.h>
#include <linux/rtnetlink.h>
+#include <net/if_arp.h> // ARPHRD_LOOPBACK
#include <sys/types.h> // getpid
#include <unistd.h> // getpid
-#include "../../event.h"
-#include "../../facemgr.h"
+#include <hicn/facemgr.h>
+#include <hicn/util/ip_address.h>
+#include <hicn/util/log.h>
+
+#include "../../common.h"
+#include "../../facelet.h"
#include "../../interface.h"
+typedef enum {
+ NL_STATE_UNDEFINED,
+ NL_STATE_LINK_SENT,
+ NL_STATE_ADDR_SENT,
+ NL_STATE_DONE,
+} nl_state_t;
+
/* Internal data storage */
typedef struct {
int fd;
+ nl_state_t state;
} nl_data_t;
-// little helper to parsing message using netlink macroses
-void parseRtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+static inline void parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len,
+ unsigned short flags)
{
+ unsigned short type;
+
memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
+ while (RTA_OK(rta, len)) {
+ type = rta->rta_type & ~flags;
+ if (type <= max)
+ tb[type] = rta;
+ rta = RTA_NEXT(rta, len);
+ }
+}
+
+int nl_process_state(interface_t * interface)
+{
+ nl_data_t * data = (nl_data_t*)interface->data;
+ int rc;
+
+ switch(data->state) {
+ case NL_STATE_UNDEFINED:
+ {
+ struct {
+ struct nlmsghdr header;
+ struct rtgenmsg payload;
+ } msg2 = {
+ .header = {
+ .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
+ .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
+ .nlmsg_type = RTM_GETLINK,
+ .nlmsg_pid = getpid(),
+ .nlmsg_seq = 3,
+ },
+ .payload = {
+ .rtgen_family = AF_PACKET,
+ }
+ };
+
+ rc = send(data->fd, &msg2, msg2.header.nlmsg_len, 0);
+ if (rc < 0)
+ printf("E: Error sending netlink query\n");
+
+ data->state = NL_STATE_LINK_SENT;
+ break;
+ }
+
+ case NL_STATE_LINK_SENT:
+ {
+ /* Issue a first query to receive static state */
+ struct {
+ struct nlmsghdr header;
+ struct ifaddrmsg payload;
+ } msg = {
+ .header = {
+ .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
+ .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
+ .nlmsg_type = RTM_GETADDR,
+ .nlmsg_pid = getpid(),
+ .nlmsg_seq = 7,
+ },
+ .payload = {
+ .ifa_family = AF_INET,
+ }
+ };
+
+ rc = send(data->fd, &msg, msg.header.nlmsg_len, 0);
+ if (rc < 0)
+ printf("E: Error sending netlink query\n");
+
+ data->state = NL_STATE_ADDR_SENT;
+ break;
+ }
- while (RTA_OK(rta, len)) { // while not end of the message
- if (rta->rta_type <= max) {
- tb[rta->rta_type] = rta; // read attr
+ case NL_STATE_ADDR_SENT:
+ {
+ data->state = NL_STATE_DONE;
+ break;
}
- rta = RTA_NEXT(rta,len); // get next attr
+
+ default: /* NL_STATE_DONE never called */
+ break;
}
-}
+ return 0;
+}
-int nl_initialize(interface_t * interface, face_rules_t * rules, void ** pdata)
+int nl_initialize(interface_t * interface, void * cfg)
{
nl_data_t * data = malloc(sizeof(nl_data_t));
if (!data)
@@ -57,31 +143,194 @@ int nl_initialize(interface_t * interface, face_rules_t * rules, void ** pdata)
goto ERR_SOCKET;
}
+ data->state = NL_STATE_UNDEFINED;
+
struct sockaddr_nl local; // local addr struct
memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK; // set protocol family
- local.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE; // set groups we interested in
+ // NOTE: RTNLGRP_LINK replaces obsolete RTMGRP_LINK, etc
+ local.nl_groups = 0
+ | RTMGRP_LINK
+ | RTMGRP_IPV4_IFADDR
+ | RTMGRP_IPV6_IFADDR
+#if 0
+ | RTMGRP_IPV4_ROUTE;
+ | RTMGRP_IPV6_ROUTE;
+#endif
+ ;
local.nl_pid = getpid(); // set out id using current process id
-
if (bind(data->fd, (struct sockaddr*)&local, sizeof(local)) < 0) { // bind socket
printf("Failed to bind netlink socket: %s\n", (char*)strerror(errno));
goto ERR_BIND;
}
- /* Issue a first query to receive static state */
+ interface->data = data;
+ nl_process_state(interface);
- *pdata = data;
- return data->fd; // FACEMGR_SUCCESS;
+ return data->fd; // 0;
ERR_BIND:
close(data->fd);
ERR_SOCKET:
free(data);
ERR_MALLOC:
- *pdata = NULL;
- return FACEMGR_FAILURE;
+ return -1;
+}
+
+int parse_link(struct nlmsghdr * h, facelet_t ** facelet,
+ char * interface_name, size_t interface_name_size,
+ bool * up, bool * running)
+{
+ struct ifinfomsg *ifi; // structure for network interface info
+ struct rtattr *tb[IFLA_MAX + 1];
+
+ assert(facelet);
+
+ ifi = (struct ifinfomsg*) NLMSG_DATA(h); // get information about changed network interface
+ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(h), 1<<15);
+
+ if (interface_name) {
+ assert(tb[IFLA_IFNAME]);
+ snprintf(interface_name, interface_name_size, "%s", (char*)RTA_DATA(tb[IFLA_IFNAME]));
+ }
+
+ if (up)
+ *up = ifi->ifi_flags & IFF_UP;
+ if (running)
+ *running = ifi->ifi_flags & IFF_RUNNING;
+
+
+ *facelet = facelet_create();
+ netdevice_t * netdevice = netdevice_create_from_name(interface_name);
+ if (!netdevice)
+ goto ERROR;
+ int rc = facelet_set_netdevice(*facelet, *netdevice);
+ if (rc < 0)
+ goto ERROR;
+
+// FIXME Tags
+#if 0
+ /* This is the only opportunity to identify a loopback interface on both
+ * linux _and_ android, as NetworkCapabilities does not have a flag for
+ * LOOPBACK... */
+ if (ifi->ifi_type==ARPHRD_LOOPBACK) {
+ DEBUG("loopback");
+ }
+
+#ifdef IFLA_WIRELESS
+ /*
+ * This signals a wirless event, but it typically occurs _after_ a face is
+ * created... we might need to update an existing face by setting a tag...
+ * or find a way to exploit this flag before actually creating the face...
+ */
+ if (tb[IFLA_WIRELESS])
+ DEBUG("wireless!!!");
+#else
+#warning "IFLA_WIRELESS not supported on this platform"
+#endif /* IFLA_WIRELESS */
+
+#endif
+
+ // TODO
+ // - ifi_change
+ // - IFLA_PROTINFO
+
+ return 0;
+
+ERROR:
+ facelet_free(*facelet);
+ *facelet = NULL;
+
+ return -1;
+}
+
+int parse_addr(struct nlmsghdr * h, facelet_t ** facelet,
+ char * interface_name, size_t interface_name_size,
+ char * interface_address, size_t interface_address_size)
+{
+ ip_address_t local_addr = IP_ADDRESS_EMPTY;
+ struct ifaddrmsg *ifa; // structure for network interface data
+ struct rtattr *tba[IFA_MAX+1];
+
+ assert(facelet);
+
+ ifa = (struct ifaddrmsg*)NLMSG_DATA(h); // get data from the network interface
+
+ parse_rtattr(tba, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(h), 0);
+
+ /* FIXME
+ *
+ * IFA_LOCAL ok for v4, not there for v6
+ *
+ * IFA_ADDRESS seems to work for both but with the following precaution
+ *
+ * IFA_ADDRESS is prefix address, rather than local interface address.
+ * It makes no difference for normally configured broadcast interfaces,
+ * but for point-to-point IFA_ADDRESS is DESTINATION address,
+ * local address is supplied in IFA_LOCAL attribute.
+ */
+ if (!tba[IFA_ADDRESS]) {
+ ERROR("[netlink.parse_addr] No local address");
+ return -1;
+ }
+
+ switch(ifa->ifa_family) {
+ case AF_INET:
+ local_addr.v4.as_inaddr = *(struct in_addr*)RTA_DATA(tba[IFA_ADDRESS]);
+ break;
+ case AF_INET6:
+ local_addr.v6.as_in6addr = *(struct in6_addr*)RTA_DATA(tba[IFA_ADDRESS]);
+ break;
+ default:
+ return 0;
+ }
+
+#if 0 /* Not working for v6 */
+ if (interface_name) {
+ assert(tba[IFLA_IFNAME]);
+ snprintf(interface_name, interface_name_size, "%s", (char*)RTA_DATA(tba[IFLA_IFNAME]));
+ }
+#endif
+
+ /* See comment in parse_link */
+ if (interface_address) {
+ assert(tba[IFA_ADDRESS]);
+ ip_address_snprintf(interface_address, interface_address_size, &local_addr, ifa->ifa_family);
+ }
+
+ netdevice_t * netdevice = netdevice_create_from_index(ifa->ifa_index);
+ if (!netdevice) {
+ ERROR("[netlink.parse_addr] error creating netdevice '%s'", interface_name);
+ goto ERROR;
+ }
+
+ if (interface_name) {
+ snprintf(interface_name, interface_name_size, "%s", netdevice->name);
+ }
+
+ *facelet = facelet_create();
+ if (facelet_set_netdevice(*facelet, *netdevice) < 0) {
+ ERROR("[netlink.parse_addr] error setting netdevice");
+ goto ERROR;
+ }
+ if (facelet_set_family(*facelet, ifa->ifa_family) < 0) {
+ ERROR("[netlink.parse_addr] error setting family");
+ goto ERROR;
+ }
+ if (facelet_set_local_addr(*facelet, local_addr) < 0) {
+ ERROR("[netlink.parse_addr] error setting local address");
+ goto ERROR;
+ }
+
+ return 0;
+
+ERROR:
+ facelet_free(*facelet);
+ *facelet = NULL;
+
+ return -1;
}
int nl_callback(interface_t * interface)
@@ -97,13 +346,12 @@ int nl_callback(interface_t * interface)
iov.iov_len = sizeof(buf); // set size
// initialize protocol message header
- struct msghdr msg;
- {
- msg.msg_name = &local; // local address
- msg.msg_namelen = sizeof(local); // address size
- msg.msg_iov = &iov; // io vector
- msg.msg_iovlen = 1; // io size
- }
+ struct msghdr msg = {
+ .msg_name = &local, // local address
+ .msg_namelen = sizeof(local), // address size
+ .msg_iov = &iov, // io vector
+ .msg_iovlen = 1, // io size
+ };
ssize_t status = recvmsg(data->fd, &msg, 0);
@@ -115,12 +363,12 @@ int nl_callback(interface_t * interface)
*/
printf("Failed to read netlink: %s", (char*)strerror(errno));
- return FACEMGR_FAILURE;
+ return -1;
}
if (msg.msg_namelen != sizeof(local)) { // check message length, just in case
printf("Invalid length of the sender address struct\n");
- return FACEMGR_FAILURE;
+ return -1;
}
// message parser
@@ -129,103 +377,122 @@ int nl_callback(interface_t * interface)
for (h = (struct nlmsghdr*)buf; status >= (ssize_t)sizeof(*h); ) { // read all messagess headers
int len = h->nlmsg_len;
int l = len - sizeof(*h);
- char *ifName = NULL;
if ((l < 0) || (len > status)) {
printf("Invalid message length: %i\n", len);
continue;
}
- // now we can check message type
- if ((h->nlmsg_type == RTM_NEWROUTE) || (h->nlmsg_type == RTM_DELROUTE)) { // some changes in routing table
- printf("Routing table was changed\n");
- } else { // in other case we need to go deeper
- char *ifUpp;
- char *ifRunn;
- struct ifinfomsg *ifi; // structure for network interface info
- struct rtattr *tb[IFLA_MAX + 1];
-
- ifi = (struct ifinfomsg*) NLMSG_DATA(h); // get information about changed network interface
-
- parseRtattr(tb, IFLA_MAX, IFLA_RTA(ifi), h->nlmsg_len); // get attributes
-
- if (tb[IFLA_IFNAME]) { // validation
- ifName = (char*)RTA_DATA(tb[IFLA_IFNAME]); // get network interface name
- }
-
- if (ifi->ifi_flags & IFF_UP) { // get UP flag of the network interface
- ifUpp = (char*)"UP";
- } else {
- ifUpp = (char*)"DOWN";
- }
+ switch(h->nlmsg_type) {
+#if 0
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ DEBUG("Routing table was changed");
+ break;
+#endif
+
+ case RTM_DELADDR:
+ {
+ facelet_t * facelet = NULL;
+ char interface_name[IFNAMSIZ];
+ char interface_address[MAXSZ_IP_ADDRESS] = {0};
+
+ if (parse_addr(h, &facelet, interface_name, IFNAMSIZ,
+ interface_address, MAXSZ_IP_ADDRESS) < 0) {
+ ERROR("Error parsing address message");
+ break;
+ }
- if (ifi->ifi_flags & IFF_RUNNING) { // get RUNNING flag of the network interface
- ifRunn = (char*)"RUNNING";
- } else {
- ifRunn = (char*)"NOT RUNNING";
+ DEBUG("Interface %s: address was removed", interface_name);
+ if (facelet) {
+ facelet_set_event(facelet, FACELET_EVENT_DELETE);
+ facelet_raise_event(facelet, interface);
+ }
+ break;
}
- char ifAddress[256] = {0}; // network addr
- struct ifaddrmsg *ifa; // structure for network interface data
- struct rtattr *tba[IFA_MAX+1];
+ case RTM_NEWADDR:
+ {
+ facelet_t * facelet = NULL;
+ char interface_name[IFNAMSIZ];
+ char interface_address[MAXSZ_IP_ADDRESS] = {0};
- ifa = (struct ifaddrmsg*)NLMSG_DATA(h); // get data from the network interface
+ if (parse_addr(h, &facelet, interface_name, IFNAMSIZ,
+ interface_address, MAXSZ_IP_ADDRESS) < 0) {
+ ERROR("Error parsing address message");
+ break;
+ }
- parseRtattr(tba, IFA_MAX, IFA_RTA(ifa), h->nlmsg_len);
+ DEBUG("Interface %s: new address was assigned: %s", interface_name, interface_address);
- if (tba[IFA_LOCAL]) {
- inet_ntop(AF_INET, RTA_DATA(tba[IFA_LOCAL]), ifAddress, sizeof(ifAddress)); // get IP addr
+ if (facelet) {
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ facelet_raise_event(facelet, interface);
+ }
+ break;
}
- face_t * face;
-
- if (tba[IFA_LOCAL]) {
- ip_address_t local_addr = IP_ADDRESS_EMPTY;
- switch(ifa->ifa_family) {
- case AF_INET:
- local_addr.v4.as_inaddr = *(struct in_addr*)RTA_DATA(tba[IFA_LOCAL]);
- break;
- case AF_INET6:
- local_addr.v6.as_in6addr = *(struct in6_addr*)RTA_DATA(tba[IFA_LOCAL]);
- break;
- default:
- continue;
+ case RTM_DELLINK:
+ {
+ facelet_t * facelet = NULL;
+ char interface_name[IFNAMSIZ];
+ if (parse_link(h, &facelet, interface_name, IFNAMSIZ,
+ NULL, NULL) < 0) {
+ ERROR("Error parsing link message");
+ break;
+ }
+ if (facelet) {
+ facelet_set_event(facelet, FACELET_EVENT_DELETE);
+ facelet_raise_event(facelet, interface);
}
- face = face_create_udp(&local_addr, 0, &IP_ADDRESS_EMPTY, 0, ifa->ifa_family);
- } else {
- face = NULL;
+
+ DEBUG("Network interface %s was removed", interface_name);
+ break;
}
- switch (h->nlmsg_type) {
- case RTM_DELADDR:
- // DOES NOT SEEM TO BE TRIGGERED
- printf("Interface %s: address was removed\n", ifName);
- if (face)
- event_raise(EVENT_TYPE_DELETE, face, interface);
- break;
+ case RTM_NEWLINK:
+ {
+ facelet_t * facelet = NULL;
+ char interface_name[IFNAMSIZ];
+ bool up, running;
- case RTM_DELLINK:
- printf("Network interface %s was removed\n", ifName);
+ if (parse_link(h, &facelet, interface_name, IFNAMSIZ, &up, &running) < 0) {
+ ERROR("Error parsing link message");
break;
+ }
- case RTM_NEWLINK:
- printf("New network interface %s, state: %s %s\n", ifName, ifUpp, ifRunn);
- // UP RUNNING
- // UP NOT RUNNING
- // DOWN NOT RUNNING
- if (!(ifi->ifi_flags & IFF_UP) || (!(ifi->ifi_flags & IFF_RUNNING))) {
- if(face)
- event_raise(EVENT_TYPE_DELETE, face, interface);
+ // UP RUNNING
+ // UP NOT RUNNING
+ // DOWN NOT RUNNING
+ DEBUG("New network interface %s, state: %s %s", interface_name,
+ up ? "UP" : "DOWN",
+ running ? "RUNNING" : "NOT_RUNNING");
+
+ if (facelet && up && running) {
+ facelet_set_event(facelet, FACELET_EVENT_CREATE);
+ facelet_t * facelet6 = facelet_dup(facelet);
+ if (!facelet6) {
+ ERROR("Could not duplicate face for v6");
+ break;
}
- break;
- case RTM_NEWADDR:
- printf("Interface %s: new address was assigned: %s\n", ifName, ifAddress);
- printf("NEW FACE\n");
- if (face)
- event_raise(EVENT_TYPE_CREATE, face, interface);
- break;
+ facelet_set_family(facelet, AF_INET);
+ facelet_raise_event(facelet, interface);
+
+ facelet_set_family(facelet6, AF_INET6);
+ facelet_raise_event(facelet6, interface);
+ }
+ break;
}
+
+ case NLMSG_ERROR:
+ break;
+ case NLMSG_DONE:
+ nl_process_state(interface);
+ break;
+ default:
+ break;
+
}
status -= NLMSG_ALIGN(len); // align offsets by the message length, this is important
@@ -233,20 +500,19 @@ int nl_callback(interface_t * interface)
h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); // get next message
}
- return FACEMGR_SUCCESS;
+ return 0;
}
int nl_finalize(interface_t * interface)
{
nl_data_t * data = (nl_data_t*)interface->data;
close(data->fd);
- return FACEMGR_SUCCESS;
+ return 0;
}
const interface_ops_t netlink_ops = {
.type = "netlink",
- .is_singleton = true,
.initialize = nl_initialize,
.callback = nl_callback,
.finalize = nl_finalize,
diff --git a/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt b/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt
index ca6659342..e8b0144b1 100644
--- a/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt
+++ b/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt
@@ -17,6 +17,7 @@ if (NOT NETWORK_LIBRARY)
endif()
list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/network_framework.h
)
list(APPEND SOURCE_FILES
diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
index 8a33129b4..4a9d24f61 100644
--- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
+++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
@@ -24,14 +24,17 @@
#include <Network/Network.h>
#include <err.h>
+#include <hicn/facemgr.h>
+#include <hicn/util/token.h>
+#include <hicn/util/log.h>
+
#include "../../common.h"
-#include "../../event.h"
-#include "../../face.h"
-#include "../../facemgr.h"
+#include <hicn/ctrl/face.h>
+#include "../../facelet.h"
#include "../../interface.h"
#include "../../util/map.h"
-#include "../../util/token.h"
-#include "../../util/log.h"
+
+#include "network_framework.h"
/*
* Bonjour service discovery for hICN forwarder
@@ -107,7 +110,7 @@ cmp_iface(const nw_interface_t iface1, const nw_interface_t iface2)
//TYPEDEF_MAP(map_cnx, nw_interface_t, nw_connection_t, cmp_iface);
typedef struct {
- face_rules_t * rules; /**< Face creation rules */
+ network_framework_cfg_t cfg;
nw_path_monitor_t pm; /**< Main path monitor */
// map_cnx_t map_cnx; /**< Map: interface -> connection for face status */
} nf_data_t;
@@ -209,97 +212,90 @@ dump_connection(nw_connection_t connection, int indent)
nw_release(path);
}
-face_t *
-face_create_from_connection(nw_connection_t connection, face_rules_t * rules)
+facelet_t *
+facelet_create_from_connection(nw_connection_t connection)
{
- face_t * face;
- struct sockaddr_in * sin;
- struct sockaddr_in6 * sin6;
+ facelet_t * facelet;
+ ip_address_t local_addr, remote_addr;
+ uint16_t remote_port;
nw_path_t path = nw_connection_copy_current_path(connection);
nw_endpoint_t local = nw_path_copy_effective_local_endpoint(path);
nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path);
__block nw_interface_t interface;
- const struct sockaddr * local_addr = nw_endpoint_get_address(local);
- const struct sockaddr * remote_addr = nw_endpoint_get_address(remote);
+ const struct sockaddr * local_sa = nw_endpoint_get_address(local);
+ const struct sockaddr * remote_sa = nw_endpoint_get_address(remote);
- assert (local_addr->sa_family == remote_addr->sa_family);
- switch(local_addr->sa_family) {
+ assert (local_sa->sa_family == remote_sa->sa_family);
+ switch(local_sa->sa_family) {
case AF_INET:
- sin = (struct sockaddr_in *)local_addr;
- sin->sin_port = htons(DEFAULT_PORT);
- sin = (struct sockaddr_in *)remote_addr;
- sin->sin_port = htons(DEFAULT_PORT);
+ local_addr.v4.as_inaddr = ((struct sockaddr_in *)local_sa)->sin_addr;
+ remote_addr.v4.as_inaddr = ((struct sockaddr_in *)remote_sa)->sin_addr;
+ remote_port = ((struct sockaddr_in *)remote_sa)->sin_port;
break;
case AF_INET6:
- sin6 = (struct sockaddr_in6 *)local_addr;
- sin6->sin6_port = htons(DEFAULT_PORT);
- sin6 = (struct sockaddr_in6 *)remote_addr;
- sin6->sin6_port = htons(DEFAULT_PORT);
+ local_addr.v6.as_in6addr = ((struct sockaddr_in6 *)local_sa)->sin6_addr;
+ remote_addr.v6.as_in6addr = ((struct sockaddr_in6 *)remote_sa)->sin6_addr;
+ remote_port = ((struct sockaddr_in6 *)remote_sa)->sin6_port;
break;
default:
- ERROR("Unsupported address family: %d\n", local_addr->sa_family);
+ ERROR("Unsupported address family: %d\n", local_sa->sa_family);
return NULL;
}
- face = face_create_udp_sa(local_addr, remote_addr);
/* Retrieving path interface type (a single one expected */
nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t path_interface) {
interface = path_interface;
return false;
});
- nw_interface_type_t type = nw_interface_get_type(interface);
- const char * name = nw_interface_get_name(interface);
-
- policy_tags_t tags = POLICY_TAGS_EMPTY;
- if (rules) {
- if (!FACEMGR_IS_ERROR(face_rules_get(rules, name, &tags)))
- goto SET_TAGS;
+ const char * name = nw_interface_get_name(interface);
+ netdevice_t netdevice;
+ snprintf(netdevice.name, IFNAMSIZ, "%s", name);
+ netdevice_update_index(&netdevice);
- char tags[MAXSZ_POLICY_TAGS];
- policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->tags);
- }
+ netdevice_type_t netdevice_type;
+ nw_interface_type_t type = nw_interface_get_type(interface);
switch(type) {
case INTERFACE_TYPE_OTHER:
- policy_tags_add(&tags, POLICY_TAG_WIFI);
- policy_tags_add(&tags, POLICY_TAG_TRUSTED);
+ netdevice_type = NETDEVICE_TYPE_UNDEFINED;
break;
case INTERFACE_TYPE_WIFI:
- // XXX disambuiguate on interface name for now.
- policy_tags_add(&tags, POLICY_TAG_WIFI);
- policy_tags_add(&tags, POLICY_TAG_TRUSTED);
+ netdevice_type = NETDEVICE_TYPE_WIFI;
break;
case INTERFACE_TYPE_CELLULAR:
- policy_tags_add(&tags, POLICY_TAG_CELLULAR);
+ netdevice_type = NETDEVICE_TYPE_CELLULAR;
break;
case INTERFACE_TYPE_WIRED:
- /* Both VPN and USB WiFi are not well detected on MacOS. For USB
- * WiFi, we currently have no solution. For VPN, until we have
- * proper support of AnyC APIs, we need to have heuristics to
- * determine VPN interfaces. */
- policy_tags_add(&tags, POLICY_TAG_WIRED);
- policy_tags_add(&tags, POLICY_TAG_TRUSTED);
+ netdevice_type = NETDEVICE_TYPE_WIRED;
break;
case INTERFACE_TYPE_LOOPBACK:
- tags = POLICY_TAGS_EMPTY;
+ netdevice_type = NETDEVICE_TYPE_LOOPBACK;
break;
default:
break;
}
-SET_TAGS:
- face_set_tags(face, tags);
-
nw_release(local);
nw_release(remote);
nw_release(path);
- return face;
+ facelet = facelet_create();
+ if (!facelet)
+ return NULL;
+
+ facelet_set_netdevice(facelet, netdevice);
+ facelet_set_netdevice_type(facelet, netdevice_type);
+ facelet_set_family(facelet, local_sa->sa_family);
+ facelet_set_local_addr(facelet, local_addr);
+ facelet_set_remote_addr(facelet, remote_addr);
+ facelet_set_remote_port(facelet, remote_port);
+
+ return facelet;
}
void
@@ -340,9 +336,11 @@ on_connection_state_event(interface_t * interface, nw_interface_t iface,
dump_connection(cnx, 1);
});
#endif
- nf_data_t * data = (nf_data_t*)interface->data;
- face_t * face = face_create_from_connection(cnx, data->rules);
- event_raise(EVENT_TYPE_CREATE, face, interface);
+ facelet_t * facelet = facelet_create_from_connection(cnx);
+ if (!facelet)
+ return;
+ facelet_set_event(facelet, FACELET_EVENT_CREATE);
+ facelet_raise_event(facelet, interface);
break;
}
case nw_connection_state_failed:
@@ -482,14 +480,11 @@ void on_interface_event(interface_t * interface, nw_interface_t iface)
* This is the first time we have a connection with address and port
* and thus the full identification of an hICN face
*/
- nf_data_t * data = (nf_data_t*)interface->data;
- face_t * face = face_create_from_connection(connection, data->rules);
- //event_raise(value ? EVENT_TYPE_SET_UP : EVENT_TYPE_SET_DOWN, face, interface);
- if(value) {
- event_raise(EVENT_TYPE_CREATE, face, interface);
- } else {
- event_raise(EVENT_TYPE_DELETE, face, interface);
- }
+ facelet_t * facelet = facelet_create_from_connection(connection);
+ if (!facelet)
+ return;
+ facelet_set_event(facelet, value ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE);
+ facelet_raise_event(facelet, interface);
});
@@ -528,13 +523,16 @@ void on_path_event(interface_t * interface, nw_path_t path)
}
-int nf_initialize(interface_t * interface, face_rules_t * rules, void ** pdata)
+int nf_initialize(interface_t * interface, void * cfg)
{
nf_data_t * data = malloc(sizeof(nf_data_t));
if (!data)
goto ERR_MALLOC;
- data->rules = rules;
+ if (cfg)
+ data->cfg = * (network_framework_cfg_t *)cfg;
+ else
+ data->cfg.rules = NULL;
data->pm = nw_path_monitor_create();
if (!data->pm)
@@ -552,14 +550,13 @@ int nf_initialize(interface_t * interface, face_rules_t * rules, void ** pdata)
DEBUG("Starting network path monitor");
nw_path_monitor_start(data->pm);
- *pdata = data;
- return FACEMGR_SUCCESS;
+ interface->data = data;
+ return 0;
ERR_PM:
free(data);
ERR_MALLOC:
- *pdata = NULL;
- return FACEMGR_FAILURE;
+ return -1;
}
int nf_finalize(interface_t * interface)
@@ -569,12 +566,11 @@ int nf_finalize(interface_t * interface)
nw_path_monitor_cancel(data->pm);
data->pm = NULL;
}
- return FACEMGR_SUCCESS;
+ return 0;
}
const interface_ops_t network_framework_ops = {
.type = "network_framework",
- .is_singleton = true,
.initialize = nf_initialize,
.finalize = nf_finalize,
.on_event = NULL,
diff --git a/ctrl/facemgr/src/face_cache.c b/ctrl/facemgr/src/interfaces/network_framework/network_framework.h
index bee36af30..edb35e904 100644
--- a/ctrl/facemgr/src/face_cache.c
+++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.h
@@ -13,9 +13,10 @@
* limitations under the License.
*/
-#include "face_cache.h"
-
-#include "face.h"
-#include "util/set.h"
+/**
+ * \file network_framework.h
+ * \brief Network framework interface
+ */
-TYPEDEF_SET(face_cache, face_t *, face_cmp, face_snprintf);
+typedef struct {
+} network_framework_cfg_t;
diff --git a/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt b/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt
new file mode 100644
index 000000000..e5fd2167e
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt
@@ -0,0 +1,31 @@
+# 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.
+
+list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/updown.h
+)
+
+list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/updown.c
+)
+
+list(APPEND INCLUDE_DIRS
+)
+
+list(APPEND LIBRARIES
+)
+
+set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
+set(INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE)
+set(LIBRARIES ${LIBRARIES} PARENT_SCOPE)
diff --git a/ctrl/facemgr/src/interfaces/updown/updown.c b/ctrl/facemgr/src/interfaces/updown/updown.c
new file mode 100644
index 000000000..f5a813cd4
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/updown/updown.c
@@ -0,0 +1,138 @@
+/*
+ * 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 updown.c
+ * \brief Implementation of Example updown interface
+ */
+
+#include <assert.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <hicn/facemgr.h>
+
+#include "../../common.h"
+#include "../../facelet.h"
+#include "../../interface.h"
+
+/**
+ * \brief Default unix socket path (the leading \0 means using the abstract
+ * namespace instead of the filesystem).
+ */
+#define UNIX_PATH "\0updownsrv"
+
+typedef struct {
+ int fd; /* Unix client socket */
+} updown_data_t;
+
+int updown_initialize(interface_t * interface, void * cfg)
+{
+ struct sockaddr_un addr;
+ char * socket_path = UNIX_PATH;
+
+ updown_data_t * data = malloc(sizeof(updown_data_t));
+ if (!data)
+ goto ERR_MALLOC;
+ interface->data = data;
+
+ data->fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (data->fd == -1) {
+ perror("socket error");
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ if (*socket_path == '\0') {
+ *addr.sun_path = '\0';
+ strncpy(addr.sun_path+1, socket_path+1, sizeof(addr.sun_path)-2);
+ } else {
+ strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
+ }
+
+ if (connect(data->fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+ perror("connect error");
+ return -1;
+ }
+
+ return data->fd;
+
+ERR_MALLOC:
+ return -1;
+}
+
+int updown_finalize(interface_t * interface)
+{
+ updown_data_t * data = (updown_data_t*)interface->data;
+
+ if (data->fd > 0)
+ close(data->fd);
+
+ return 0;
+}
+
+int updown_callback(interface_t * interface)
+{
+ updown_data_t * data = (updown_data_t*)interface->data;
+ char buf[100];
+ int rc;
+
+ rc = read(data->fd, buf, sizeof(buf));
+ if (rc < 0)
+ return -1;
+
+ /*
+ * If the process is paused (eg. in a debugger, we might have more than one
+ * read.
+ * XXX how big is the buffer
+ * XXX shall we drain the queue if it exceeds buffer size ?
+ */
+ //assert(rc == 1);
+
+ /* Raise facelet update event */
+ facelet_t * facelet = facelet_create();
+ facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_WIFI); //CELLULAR);
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ switch(buf[0]) {
+ case '\0':
+ facelet_set_admin_state(facelet, FACE_STATE_DOWN);
+ break;
+ case '\1':
+ facelet_set_admin_state(facelet, FACE_STATE_UP);
+ break;
+ break;
+ default:
+ ERROR("Invalid data received from updown server. Ignoring...");
+ facelet_free(facelet);
+ return -1;
+ }
+
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+
+ facelet_raise_event(facelet, interface);
+
+ return 0;
+}
+
+interface_ops_t updown_ops = {
+ .type = "updown",
+ .initialize = updown_initialize,
+ .finalize = updown_finalize,
+ .callback = updown_callback,
+};
diff --git a/ctrl/facemgr/src/main.c b/ctrl/facemgr/src/main.c
index 6a80d806b..2a336db8f 100644
--- a/ctrl/facemgr/src/main.c
+++ b/ctrl/facemgr/src/main.c
@@ -18,8 +18,21 @@
* \brief Face manager daemon entry point
*/
+#ifdef WITH_THREAD
+#ifndef __linux__
+#error "Not implemented"
+#endif /* __linux__ */
+#include <pthread.h>
+#endif /* WITH_THREAD */
+
+#ifndef __APPLE__
+#include <event2/event.h>
+#include <event2/thread.h>
+#endif /* __APPLE__ */
+
#include <getopt.h>
#include <limits.h>
+#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -27,20 +40,41 @@
#include <libconfig.h>
-#include "util/log.h"
-#include "util/policy.h"
-
#ifdef __APPLE__
#include <Dispatch/Dispatch.h>
#else
-// Note: we might want to use libevent on Apple too
#include <event2/event.h>
#endif
-#include "facemgr.h"
+#include <hicn/facemgr.h>
+#include <hicn/policy.h>
+
+#include <hicn/util/ip_address.h>
+#include <hicn/util/log.h>
+
+#include <hicn/facemgr/cfg.h>
#define FACEMGR_TIMEOUT 3
+static struct event_base * loop;
+
+void facemgr_signal_handler(int signal) {
+ fprintf(stderr, "Received ^C... quitting !\n");
+ exit(0);
+#if 0
+ return;
+
+ // FIXME
+
+ /* should be atomic */
+ // FIXME Don't use loop in a static variable as we should not need it if all
+ // events are properly unregistered...
+#endif
+#ifdef __linux__
+ event_base_loopbreak(loop);
+#endif /* __linux__ */
+ loop = NULL;
+}
static struct option long_options[] =
{
@@ -101,106 +135,305 @@ int parse_cmdline(int argc, char ** argv, facemgr_options_t * opts)
return 0;
}
-int parse_config_file(const char * cfgpath, facemgr_t * facemgr)
+int
+parse_config_global(facemgr_cfg_t * cfg, config_setting_t * setting)
{
- /* Reading configuration file */
- config_t cfg;
- config_setting_t *setting;
+ /* - face_type */
+
+ const char *face_type_str;
+ facemgr_face_type_t face_type;
+ if (config_setting_lookup_string(setting, "face_type", &face_type_str)) {
+ if (strcasecmp(face_type_str, "auto") == 0) {
+ face_type = FACEMGR_FACE_TYPE_DEFAULT;
+ } else
+ if (strcasecmp(face_type_str, "native-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_UDP;
+ } else
+ if (strcasecmp(face_type_str, "native-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+ } else
+ if (strcasecmp(face_type_str, "overlay-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+ } else
+ if (strcasecmp(face_type_str, "overlay-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
+ } else {
+ ERROR("Invalid face type in section 'global'");
+ return -1;
+ }
- config_init(&cfg);
+ int rc = facemgr_cfg_set_face_type(cfg, &face_type);
+ if (rc < 0)
+ goto ERR;
+ }
- /* Read the file. If there is an error, report it and exit. */
- if(!config_read_file(&cfg, cfgpath))
- goto ERR_FILE;
+ /* - disable_discovery */
- setting = config_lookup(&cfg, "log");
- if (setting) {
- const char *log_level_str;
- if (config_setting_lookup_string(setting, "log_level", &log_level_str)) {
- if (strcmp(log_level_str, "FATAL") == 0) {
- log_conf.log_level = LOG_FATAL;
- } else
- if (strcmp(log_level_str, "ERROR") == 0) {
- log_conf.log_level = LOG_ERROR;
- } else
- if (strcmp(log_level_str, "WARN") == 0) {
- log_conf.log_level = LOG_WARN;
- } else
- if (strcmp(log_level_str, "INFO") == 0) {
- log_conf.log_level = LOG_INFO;
- } else
- if (strcmp(log_level_str, "DEBUG") == 0) {
- log_conf.log_level = LOG_DEBUG;
- } else
- if (strcmp(log_level_str, "TRACE") == 0) {
- log_conf.log_level = LOG_TRACE;
- } else {
- printf("Ignored unknown log level\n");
- }
- }
+ int disable_discovery;
+ if (config_setting_lookup_bool(setting, "disable_discovery",
+ &disable_discovery)) {
+ int rc = facemgr_cfg_set_discovery(cfg, !disable_discovery);
+ if (rc < 0)
+ goto ERR;
}
- setting = config_lookup(&cfg, "faces.overlay.ipv4");
- if (setting) {
- const char * ip_address;
- int local_port, remote_port;
- if (config_setting_lookup_int(setting, "local_port", &local_port)) {
- if ((local_port < 0) || (local_port > MAX_PORT))
+ /* - disable_ipv4 */
+
+ int disable_ipv4;
+ if (config_setting_lookup_bool(setting, "disable_ipv4",
+ &disable_ipv4)) {
+ INFO("Ignored setting 'disable_ipv4' in section 'global' (not implemented).");
+#if 0
+ int rc = facemgr_cfg_set_ipv4(cfg, !disable_ipv4);
+ if (rc < 0)
+ goto ERR;
+#endif
+ }
+
+ /* - disable ipv6 */
+
+ int disable_ipv6;
+ if (config_setting_lookup_bool(setting, "disable_ipv6",
+ &disable_ipv6)) {
+ INFO("Ignored setting 'disable_ipv6' in section 'global': (not implemented).");
+#if 0
+ int rc = facemgr_cfg_set_ipv6(cfg, !disable_ipv6);
+ if (rc < 0)
+ goto ERR;
+#endif
+ }
+
+ /* - overlay */
+ config_setting_t *overlay = config_setting_get_member(setting, "overlay");
+ if (overlay) {
+
+ /* ipv4 */
+ config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4");
+ if (overlay_v4) {
+ const char * local_addr_str, * remote_addr_str;
+ ip_address_t local_addr, remote_addr;
+ ip_address_t * local_addr_p = NULL;
+ ip_address_t * remote_addr_p = NULL;
+ int local_port = 0;
+ int remote_port = 0;
+
+ if (config_setting_lookup_string(overlay_v4, "local_addr", &local_addr_str)) {
+ ip_address_pton(local_addr_str, &local_addr);
+ local_addr_p = &local_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) {
+ if (!IS_VALID_PORT(local_port))
+ goto ERR;
+ }
+
+ if (config_setting_lookup_string(overlay_v4, "remote_addr", &remote_addr_str)) {
+ ip_address_pton(remote_addr_str, &remote_addr);
+ remote_addr_p = &remote_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v4, "remote_port", &remote_port)) {
+ if (!IS_VALID_PORT(remote_port))
+ goto ERR;
+ }
+ int rc = facemgr_cfg_set_overlay(cfg, AF_INET,
+ local_addr_p, local_port,
+ remote_addr_p, remote_port);
+ if (rc < 0)
goto ERR;
- facemgr->overlay_v4_local_port = (uint16_t)local_port;
}
- if (config_setting_lookup_int(setting, "remote_port", &remote_port)) {
- if ((remote_port < 0) || (remote_port > MAX_PORT))
+ /* ipv6 */
+ config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6");
+ if (overlay_v6) {
+ const char * local_addr_str, * remote_addr_str;
+ ip_address_t local_addr, remote_addr;
+ ip_address_t * local_addr_p = NULL;
+ ip_address_t * remote_addr_p = NULL;
+ int local_port = 0;
+ int remote_port = 0;
+
+ if (config_setting_lookup_string(overlay_v6, "local_addr", &local_addr_str)) {
+ ip_address_pton(local_addr_str, &local_addr);
+ local_addr_p = &local_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) {
+ if (!IS_VALID_PORT(local_port))
+ goto ERR;
+ }
+
+ if (config_setting_lookup_string(overlay_v6, "remote_addr", &remote_addr_str)) {
+ ip_address_pton(remote_addr_str, &remote_addr);
+ remote_addr_p = &remote_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v6, "remote_port", &remote_port)) {
+ if (!IS_VALID_PORT(remote_port))
+ goto ERR;
+ }
+ int rc = facemgr_cfg_set_overlay(cfg, AF_INET6,
+ local_addr_p, local_port,
+ remote_addr_p, remote_port);
+ if (rc < 0)
goto ERR;
- facemgr->overlay_v4_remote_port = (uint16_t)remote_port;
}
- if (config_setting_lookup_string(setting, "remote_addr", &ip_address)) {
- ip_address_pton(ip_address, &facemgr->overlay_v4_remote_addr);
- printf("got v4 remote addr\n");
+ } /* overlay */
+
+ return 0;
+
+ERR:
+ return -1;
+}
+
+int
+parse_config_rules(facemgr_cfg_t * cfg, config_setting_t * setting)
+{
+ /* List of match-override tuples */
+ facemgr_cfg_rule_t * rule;
+
+ int count = config_setting_length(setting);
+ for (unsigned i = 0; i < count; ++i) {
+ config_setting_t * rule_setting = config_setting_get_elem(setting, i);
+
+ /* Sanity check */
+
+ config_setting_t * match_setting = config_setting_get_member(rule_setting, "match");
+ if (!match_setting) {
+ ERROR("Missing match section in rule #%d", i);
+ goto ERR_CHECK;
}
- }
- setting = config_lookup(&cfg, "faces.overlay.ipv6");
- if (setting) {
- const char * ip_address;
- int local_port, remote_port;
- if (config_setting_lookup_int(setting, "local_port", &local_port)) {
- if ((local_port < 0) || (local_port > MAX_PORT))
+ config_setting_t * override_setting = config_setting_get_member(rule_setting, "override");
+ if (!override_setting) {
+ ERROR("Missing override section in rule #%d", i);
+ goto ERR_CHECK;
+ }
+
+ rule = facemgr_cfg_rule_create();
+ if (!rule)
+ goto ERR_RULE;
+
+ /* Parse match */
+
+ const char * interface_name = NULL;
+ config_setting_lookup_string(match_setting, "interface_name", &interface_name);
+
+ const char * interface_type_str;
+ netdevice_type_t interface_type = NETDEVICE_TYPE_UNDEFINED;
+ if (config_setting_lookup_string(match_setting, "interface_type", &interface_type_str)) {
+ if (strcasecmp(interface_type_str, "wired") == 0) {
+ interface_type = NETDEVICE_TYPE_WIRED;
+ } else
+ if (strcasecmp(interface_type_str, "wifi") == 0) {
+ interface_type = NETDEVICE_TYPE_WIFI;
+ } else
+ if (strcasecmp(interface_type_str, "cellular") == 0) {
+ interface_type = NETDEVICE_TYPE_CELLULAR;
+ } else {
+ ERROR("Unknown interface type in rule #%d", i);
goto ERR;
- facemgr->overlay_v6_local_port = (uint16_t)local_port;
+ }
}
- if (config_setting_lookup_int(setting, "remote_port", &remote_port)) {
- if ((remote_port < 0) || (remote_port > MAX_PORT))
+ if ((!interface_name) && (interface_type == NETDEVICE_TYPE_UNDEFINED)) {
+ ERROR("Empty match section in rule #%d", i);
+ goto ERR;
+ }
+
+ /* Associate match to rule */
+
+ int rc = facemgr_cfg_rule_set_match(rule, interface_name, interface_type);
+ if (rc < 0)
+ goto ERR;
+
+ /* Parse override */
+
+ /* - face_type */
+
+ const char *face_type_str;
+ facemgr_face_type_t face_type;
+ if (config_setting_lookup_string(override_setting, "face_type", &face_type_str)) {
+ if (strcasecmp(face_type_str, "auto")) {
+ /* We currently hardcode different behaviours based on the OS */
+#ifdef __ANDROID__
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+#else
+ face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+#endif
+ } else
+ if (strcasecmp(face_type_str, "native-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_UDP;
+ } else
+ if (strcasecmp(face_type_str, "native-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+ } else
+ if (strcasecmp(face_type_str, "overlay-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+ } else
+ if (strcasecmp(face_type_str, "overlay-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
+ } else {
+ ERROR("Invalid face type in section 'global'");
+ return -1;
+ }
+
+ int rc = facemgr_cfg_rule_set_face_type(rule, &face_type);
+ if (rc < 0)
goto ERR;
- facemgr->overlay_v6_remote_port = (uint16_t)remote_port;
}
- if (config_setting_lookup_string(setting, "remote_addr", &ip_address))
- ip_address_pton(ip_address, &facemgr->overlay_v6_remote_addr);
- }
+ /* - disable_discovery */
- setting = config_lookup(&cfg, "faces.rules");
- if (setting) {
- int count = config_setting_length(setting);
- for(unsigned i = 0; i < count; ++i) {
- const char *interface_name;
- policy_tags_t tags = POLICY_TAGS_EMPTY;
+ int disable_discovery;
+ if (config_setting_lookup_bool(override_setting, "disable_discovery",
+ &disable_discovery)) {
+ int rc = facemgr_cfg_rule_set_discovery(rule, !disable_discovery);
+ if (rc < 0)
+ goto ERR;
+ }
- config_setting_t *rule = config_setting_get_elem(setting, i);
+ /* - disable_ipv4 */
- /* Interface name */
- if(!(config_setting_lookup_string(rule, "name", &interface_name)))
- continue;
+ int disable_ipv4;
+ if (config_setting_lookup_bool(override_setting, "disable_ipv4",
+ &disable_ipv4)) {
+ INFO("Ignored setting 'disable_ipv4' in rule #%d (not implemented).", i);
+#if 0
+ int rc = facemgr_cfg_rule_set_ipv4(rule, !disable_ipv4);
+ if (rc < 0)
+ goto ERR;
+#endif
+ }
- /* Associated tags */
- config_setting_t *tag_settings = config_setting_get_member(rule, "tags");
- if (!tag_settings)
+ /* - disable ipv6 */
+
+ int disable_ipv6;
+ if (config_setting_lookup_bool(override_setting, "disable_ipv6",
+ &disable_ipv6)) {
+ INFO("Ignored setting 'disable_ipv6' in rule #%d (not implemented).", i);
+#if 0
+ int rc = facemgr_cfg_rule_set_ipv6(rule, !disable_ipv6);
+ if (rc < 0)
goto ERR;
+#endif
+ }
+ /* - ignore */
+ int ignore;
+ if (config_setting_lookup_bool(override_setting, "ignore", &ignore)) {
+ int rc = facemgr_cfg_rule_set_ignore(rule, !!ignore);
+ if (rc < 0)
+ goto ERR;
+ }
+ /* - tags */
+ config_setting_t *tag_settings = config_setting_get_member(override_setting, "tags");
+ if (tag_settings) {
+ INFO("Ignored setting 'tags' in rule #%d (not implemented).", i);
+#if 0
+ policy_tags_t tags = POLICY_TAGS_EMPTY;
for (unsigned j = 0; j < config_setting_length(tag_settings); j++) {
const char * tag_str = config_setting_get_string_elem(tag_settings, j);
policy_tag_t tag = policy_tag_from_str(tag_str);
@@ -209,41 +442,267 @@ int parse_config_file(const char * cfgpath, facemgr_t * facemgr)
policy_tags_add(&tags, tag);
}
- /* debug */
+ int rc = facemgr_cfg_rule_set_tags(rule, tags);
+ if (rc < 0)
+ goto ERR;
+
+#if 0
char tags_str[MAXSZ_POLICY_TAGS];
policy_tags_snprintf(tags_str, MAXSZ_POLICY_TAGS, tags);
- printf("Rule #%d interface_name=%s, tags=%s\n", i, interface_name, tags_str);
- face_rules_add(&facemgr->rules, strdup(interface_name), tags);
+ DEBUG("Added tags tags=%s", tags_str);
+#endif
+#endif
}
+
+ /* - overlay */
+ config_setting_t *overlay = config_setting_get_member(override_setting, "overlay");
+ if (overlay) {
+
+ /* ipv4 */
+ config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4");
+ if (overlay_v4) {
+ const char * local_addr_str, * remote_addr_str;
+ ip_address_t local_addr, remote_addr;
+ ip_address_t * local_addr_p = NULL;
+ ip_address_t * remote_addr_p = NULL;
+ int local_port = 0;
+ int remote_port = 0;
+
+ if (config_setting_lookup_string(overlay_v4, "local_addr", &local_addr_str)) {
+ ip_address_pton(local_addr_str, &local_addr);
+ local_addr_p = &local_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) {
+ if (!IS_VALID_PORT(local_port))
+ goto ERR;
+ }
+
+ if (config_setting_lookup_string(overlay_v4, "remote_addr", &remote_addr_str)) {
+ ip_address_pton(remote_addr_str, &remote_addr);
+ remote_addr_p = &remote_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v4, "remote_port", &remote_port)) {
+ if (!IS_VALID_PORT(remote_port))
+ goto ERR;
+ }
+ int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET,
+ local_addr_p, local_port,
+ remote_addr_p, remote_port);
+ if (rc < 0)
+ goto ERR;
+ }
+
+ /* ipv6 */
+ config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6");
+ if (overlay_v6) {
+ const char * local_addr_str, * remote_addr_str;
+ ip_address_t local_addr, remote_addr;
+ ip_address_t * local_addr_p = NULL;
+ ip_address_t * remote_addr_p = NULL;
+ int local_port = 0;
+ int remote_port = 0;
+
+ if (config_setting_lookup_string(overlay_v6, "local_addr", &local_addr_str)) {
+ ip_address_pton(local_addr_str, &local_addr);
+ local_addr_p = &local_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) {
+ if (!IS_VALID_PORT(local_port))
+ goto ERR;
+ }
+
+ if (config_setting_lookup_string(overlay_v6, "remote_addr", &remote_addr_str)) {
+ ip_address_pton(remote_addr_str, &remote_addr);
+ remote_addr_p = &remote_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v6, "remote_port", &remote_port)) {
+ if (!IS_VALID_PORT(remote_port))
+ goto ERR;
+ }
+ int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET6,
+ local_addr_p, local_port,
+ remote_addr_p, remote_port);
+ if (rc < 0)
+ goto ERR;
+ }
+
+ } /* overlay */
+
+ /* Add newly created rule */
+
+ rc = facemgr_cfg_add_rule(cfg, rule);
+ if (rc < 0)
+ goto ERR;
}
+ return 0;
+
+ERR:
+ facemgr_cfg_rule_free(rule);
+ERR_RULE:
+ERR_CHECK:
+ return -1;
+}
- config_destroy(&cfg);
+/* Currently not using facemgr_cfg_t */
+int
+parse_config_log(facemgr_cfg_t * cfg, config_setting_t * setting)
+{
+ const char *log_level_str;
+ if (config_setting_lookup_string(setting, "log_level", &log_level_str)) {
+ if (strcasecmp(log_level_str, "FATAL") == 0) {
+ log_conf.log_level = LOG_FATAL;
+ } else
+ if (strcasecmp(log_level_str, "ERROR") == 0) {
+ log_conf.log_level = LOG_ERROR;
+ } else
+ if (strcasecmp(log_level_str, "WARN") == 0) {
+ log_conf.log_level = LOG_WARN;
+ } else
+ if (strcasecmp(log_level_str, "INFO") == 0) {
+ log_conf.log_level = LOG_INFO;
+ } else
+ if (strcasecmp(log_level_str, "DEBUG") == 0) {
+ log_conf.log_level = LOG_DEBUG;
+ } else
+ if (strcasecmp(log_level_str, "TRACE") == 0) {
+ log_conf.log_level = LOG_TRACE;
+ } else {
+ ERROR("Invalid log level in section 'log'");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+parse_config_file(const char * cfgpath, facemgr_cfg_t * cfg)
+{
+ /* Reading configuration file */
+ config_t cfgfile;
+ config_setting_t *setting;
+
+ config_init(&cfgfile);
+
+ /* Read the file. If there is an error, report it and exit. */
+ if(!config_read_file(&cfgfile, cfgpath))
+ goto ERR_FILE;
+
+ setting = config_lookup(&cfgfile, "global");
+ if (setting) {
+ int rc = parse_config_global(cfg, setting);
+ if (rc < 0)
+ goto ERR_PARSE;
+ }
+
+ setting = config_lookup(&cfgfile, "rules");
+ if (setting) {
+ int rc = parse_config_rules(cfg, setting);
+ if (rc < 0)
+ goto ERR_PARSE;
+ }
+
+ setting = config_lookup(&cfgfile, "log");
+ if (setting) {
+ int rc = parse_config_log(cfg, setting);
+ if (rc < 0)
+ goto ERR_PARSE;
+ }
+
+ config_destroy(&cfgfile);
return 0;
ERR_FILE:
- printf("Could not read configuration file %s\n", cfgpath);
- fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
- config_error_line(&cfg), config_error_text(&cfg));
- config_destroy(&cfg);
+ ERROR("Could not read configuration file %s", cfgpath);
+ fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile),
+ config_error_line(&cfgfile), config_error_text(&cfgfile));
+ config_destroy(&cfgfile);
exit(EXIT_FAILURE);
return -1;
-ERR:
- fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
- config_error_line(&cfg), config_error_text(&cfg));
- config_destroy(&cfg);
+ERR_PARSE:
+ fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile),
+ config_error_line(&cfgfile), config_error_text(&cfgfile));
+ config_destroy(&cfgfile);
return -1;
}
-#ifndef APPLE
-void dummy_handler(int fd, short event, void *arg) { }
-#endif /* APPLE */
+#ifdef __linux__
+typedef struct {
+ void (*cb)(void *, ...);
+ void * args;
+} cb_wrapper_args_t;
+
+void cb_wrapper(evutil_socket_t fd, short what, void * arg) {
+ cb_wrapper_args_t * cb_wrapper_args = arg;
+ cb_wrapper_args->cb(cb_wrapper_args->args);
+}
-int main(int argc, char **argv)
+struct event *
+loop_register_fd(struct event_base * loop, int fd, void * cb, void * cb_args)
{
- facemgr_t * facemgr = facemgr_create();
- if (!facemgr)
- goto ERR_FACEMGR;
+ // TODO: not freed
+ cb_wrapper_args_t * cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t));
+ *cb_wrapper_args = (cb_wrapper_args_t) {
+ .cb = cb,
+ .args = cb_args,
+ };
+
+ evutil_make_socket_nonblocking(fd);
+ struct event * event = event_new(loop, fd, EV_READ | EV_PERSIST, cb_wrapper, cb_wrapper_args);
+ if (!event)
+ goto ERR_EVENT_NEW;
+
+ if (event_add(event, NULL) < 0)
+ goto ERR_EVENT_ADD;
+
+ return event;
+
+ERR_EVENT_ADD:
+ event_free(event);
+ERR_EVENT_NEW:
+ return NULL;
+}
+
+int
+loop_unregister_event(struct event_base * loop, struct event * event)
+{
+ if (!event)
+ return 0;
+
+ event_del(event);
+ event_free(event);
+
+ return 0;
+}
+
+
+void * start_dispatch(void * loop_ptr)
+{
+ struct event_base * loop = (struct event_base *) loop_ptr;
+ event_base_dispatch(loop);
+
+ return NULL;
+}
+
+#endif /* __linux__ */
+
+int main(int argc, char ** argv)
+{
+ facemgr_cfg_t * cfg = NULL;
+ facemgr_t * facemgr;
+#ifdef WITH_THREAD
+ pthread_t facemgr_thread;
+#endif /* WITH_THREAD */
+
+ struct sigaction sigIntHandler;
+ sigIntHandler.sa_handler = facemgr_signal_handler;
+ sigemptyset(&sigIntHandler.sa_mask);
+ sigIntHandler.sa_flags = 0;
+ sigaction(SIGINT, &sigIntHandler, NULL);
char cfgfile[PATH_MAX];
@@ -252,7 +711,7 @@ int main(int argc, char **argv)
/* Commandline */
facemgr_options_t cmdline_opts = {0};
if (parse_cmdline(argc, argv, &cmdline_opts) < 0) {
- ERROR("Error parsing commandline\n");
+ ERROR("Error parsing commandline");
goto ERR_CMDLINE;
}
@@ -260,7 +719,7 @@ int main(int argc, char **argv)
//facemgr_options_t cfgfile_opts;
if (cmdline_opts.cfgfile) {
- if (strcmp(cmdline_opts.cfgfile, "none") == 0)
+ if (strcasecmp(cmdline_opts.cfgfile, "none") == 0)
goto NO_CFGFILE;
if (!realpath(cmdline_opts.cfgfile, (char*)&cfgfile))
@@ -274,76 +733,118 @@ int main(int argc, char **argv)
if (probe_cfgfile(cfgfile) < 0)
goto NO_CFGFILE;
- printf("Using configuration file %s\n", cfgfile);
-
PARSE_CFGFILE:
- if (parse_config_file(cfgfile, facemgr) < 0) {
- ERROR("Error parsing configuration file %s\n", cfgfile);
+ DEBUG("Using configuration file %s", cfgfile);
+ cfg = facemgr_cfg_create();
+ if (!cfg)
+ goto ERR_FACEMGR_CFG;
+
+ if (parse_config_file(cfgfile, cfg) < 0) {
+ ERROR("Error parsing configuration file %s", cfgfile);
goto ERR_PARSE;
}
+ facemgr = facemgr_create_with_config(cfg);
+ if (!facemgr)
+ goto ERR_FACEMGR_CONFIG;
+
+ goto MAIN_LOOP;
+
NO_CFGFILE:
+ facemgr = facemgr_create();
+ if (!facemgr)
+ goto ERR_FACEMGR;
+
+MAIN_LOOP:
+
+ /* Main loop */
+
+
+#ifdef WITH_THREAD
+ evthread_use_pthreads();
+#endif /* WITH_THREAD */
+
#ifdef __linux__
- facemgr->loop = event_base_new();
- if (!facemgr->loop)
- fatal("Could not create an event base");
-
- /* Main loop
- *
- * To avoid the loop to exit when empty, we might either rely on an option
- * introduced from versions 2.1.x:
- * event_base_loop(loop->base, EVLOOP_NO_EXIT_ON_EMPTY);
- * or use this workaround:
- * http://archives.seul.org/libevent/users/Sep-2012/msg00056.html
- *
- * TODO:
- * - HUP should interrupt the main loop
- */
- {
- struct event *ev;
- struct timeval tv;
- tv.tv_sec = FACEMGR_TIMEOUT;
- tv.tv_usec = 0;
-
- ev = event_new(facemgr->loop, fileno(stdin), EV_TIMEOUT | EV_PERSIST, dummy_handler, NULL);
- event_add(ev, &tv);
- }
+ /* Event loop */
+ loop = event_base_new();
+ if (!loop)
+ goto ERR_EVENT;
+
+ facemgr_set_event_loop_handler(facemgr, loop, loop_register_fd, loop_unregister_event);
#endif /* __linux__ */
- DEBUG("Bootstrap...\n");
+#ifdef __ANDROID__
+ facemgr_set_jvm(facemgr, NULL, NULL); // FIXME
+#endif /* __ ANDROID__ */
+
+ DEBUG("Bootstrap...");
+
if (facemgr_bootstrap(facemgr) < 0 )
goto ERR_BOOTSTRAP;
#ifdef __linux__
event_set_log_callback(NULL);
- event_base_dispatch(facemgr->loop);
- event_base_free(facemgr->loop);
+#ifdef WITH_THREAD
+ if (pthread_create(&facemgr_thread, NULL, start_dispatch, loop)) {
+ fprintf(stderr, "Error creating thread\n");
+ return EXIT_FAILURE;
+ }
+#else
+ event_base_dispatch(loop);
+#endif /* WITH_THREAD */
+
#endif /* __linux__ */
#ifdef __APPLE__
/* Main loop */
- facemgr->loop = NULL;
dispatch_main();
#endif /* __APPLE__ */
- /* Clean up */
- //interface_delete_all();
+#ifdef __linux__
+#ifdef WITH_THREAD
+ for(;;) {
+ facemgr_list_faces(facemgr, NULL, NULL);
+ sleep(5);
+ }
+#endif /* WITH_THREAD */
+#endif /* __linux__ */
+
+ facemgr_stop(facemgr);
+#ifdef __linux__
+#ifdef WITH_THREAD
+ DEBUG("Waiting for loop to terminate...");
+ if(pthread_join(facemgr_thread, NULL)) {
+ fprintf(stderr, "Error joining thread\n");
+ return EXIT_FAILURE;
+ }
+ DEBUG("Loop terminated !");
+#endif /* WITH_THREAD */
+#endif /* __linux__ */
facemgr_free(facemgr);
return EXIT_SUCCESS;
ERR_BOOTSTRAP:
+#ifdef __linux__
+ERR_EVENT:
+#endif /* __linux__ */
+
+ facemgr_free(facemgr);
+ERR_FACEMGR_CONFIG:
+ if (cfg)
+ facemgr_cfg_free(cfg);
+ERR_FACEMGR:
+ERR_FACEMGR_CFG:
+
ERR_PARSE:
ERR_PATH:
ERR_CMDLINE:
- facemgr_free(facemgr);
-ERR_FACEMGR:
return EXIT_FAILURE;
-}
+}
diff --git a/ctrl/facemgr/src/netdevice.h b/ctrl/facemgr/src/netdevice.h
deleted file mode 100644
index b64ad0f9a..000000000
--- a/ctrl/facemgr/src/netdevice.h
+++ /dev/null
@@ -1,52 +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 netdevice.h
- * \brief Netdevice abstraction
- */
-#ifndef FACEMGR_NETDEVICE_H
-#define FACEMGR_NETDEVICE_H
-
-#include <net/if.h> // IFNAMSIZ
-
-#include "common.h"
-
-#define foreach_netdevice_type \
- _(UNDEFINED) \
- _(WIRED) \
- _(WIFI) \
- _(CELLULAR) \
- _(VPN) \
- _(N)
-
-#define MAXSZ_NETDEVICE_TYPE 9
-#define MAXSZ_NETDEVICE_TYPE_ MAXSZ_NETDEVICE_TYPE
-
-typedef enum {
-#define _(x) x,
-foreach_netdevice_type
-#undef _
-} netdevice_type_t;
-
-extern const char * netdevice_type_str[];
-
-
-typedef struct {
- u32 index;
- char name[IFNAMSIZ];
-} netdevice_t;
-
-#endif /* FACEMGR_NETDEVICE_H */
diff --git a/ctrl/facemgr/src/util/log.c b/ctrl/facemgr/src/util/log.c
index 54943cf45..c1fc999ad 100644
--- a/ctrl/facemgr/src/util/log.c
+++ b/ctrl/facemgr/src/util/log.c
@@ -13,12 +13,16 @@
* limitations under the License.
*/
-#include "log.h"
+#include <hicn/util/log.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
log_conf_t log_conf = DEFAULT_LOG_CONF;
#define FMT_DATETIME "%02d-%02d-%04d %02d:%02d:%02d"
@@ -43,48 +47,96 @@ static char *timestamp(void)
}
void _log_va(int level, const char *fmt, va_list ap)
-{
- char *prefix;
- FILE *f = log_conf.log_file ? log_conf.log_file : stdout;
+{
#if 0
if (!conf.log_system)
return;
#endif
+ 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);
+ }
+
+#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");
#ifdef DEBUG
fflush(f);
#endif
+#endif
}
void _log(int level, const char *fmt, ...)
diff --git a/ctrl/facemgr/src/util/map.h b/ctrl/facemgr/src/util/map.h
index 2694de2a7..b6773f209 100644
--- a/ctrl/facemgr/src/util/map.h
+++ b/ctrl/facemgr/src/util/map.h
@@ -31,6 +31,10 @@ typedef struct {
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 *) \
@@ -47,7 +51,7 @@ NAME ## _t * NAME ## _create();
\
void NAME ## _free(NAME ## _t * map); \
\
-int NAME ## _add(NAME ## _t * map, KEY_T key, const VAL_T value); \
+int NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value); \
\
int NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value); \
\
@@ -60,6 +64,24 @@ void NAME ## _dump(NAME ## _t * map);
#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) \
{ \
@@ -72,7 +94,7 @@ NAME ## _pair_snprintf(char * buf, size_t size, const NAME ## _pair_t * pair) {
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); \
+ rc = VALUE_SNPRINTF(buf+rc, BUFSIZE/2, (VAL_T)pair->value); \
return rc; \
} \
\
@@ -93,57 +115,98 @@ NAME ## _finalize(NAME ## _t * map)
AUTOGENERATE_CREATE_FREE(NAME) \
\
int \
-NAME ## _add(NAME ## _t * map, KEY_T key, const VAL_T value) \
+NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value) \
{ \
int rc; \
+ NAME ## _pair_t * found = NULL; \
\
- /* Create pair */ \
- NAME ## _pair_t * pair = malloc(sizeof(NAME ## _pair_t)); \
+ NAME ## _pair_t * pair = NAME ## _pair_create(key, value); \
if (!pair) \
- return FACEMGR_FAILURE; \
- \
- pair->key = key; \
- pair->value = (VAL_T)value; \
+ return -1; \
\
- rc = NAME ## _pair_set_get(&map->pair_set, pair, NULL); \
- if (!FACEMGR_IS_ERROR(rc)) { \
- free(pair); \
+ 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 (FACEMGR_IS_ERROR(rc)) { \
- free(pair); \
- return FACEMGR_FAILURE; \
+ if (rc < 0) { \
+ NAME ## _pair_free(pair); \
+ return -1; \
} \
- return FACEMGR_SUCCESS; \
+ return 0; \
} \
\
int \
NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value) \
{ \
- NAME ## _pair_t * found, search = { .key = key }; \
+ NAME ## _pair_t * found = NULL; \
+ NAME ## _pair_t search = { .key = key }; \
int rc = NAME ## _pair_set_remove(&map->pair_set, &search, &found); \
- if (FACEMGR_IS_ERROR(rc)) \
+ if (rc < 0) \
return ERR_MAP_NOT_FOUND; \
- *value = found->value; \
- return FACEMGR_SUCCESS; \
+ 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, search = { .key = key }; \
+ NAME ## _pair_t * found = NULL, search = { .key = key }; \
int rc = NAME ## _pair_set_get(&map->pair_set, &search, &found); \
- if (FACEMGR_IS_ERROR(rc)) \
- return ERR_MAP_NOT_FOUND; \
- *value = found->value; \
- return FACEMGR_SUCCESS; \
+ 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; \
+ /* 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); \
+ return 0; \
+} \
+ \
+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; \
+ /* 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); \
+ return 0; \
}
#endif /* UTIL_MAP_H */
diff --git a/ctrl/facemgr/src/util/policy.c b/ctrl/facemgr/src/util/policy.c
deleted file mode 100644
index 6c8651ee3..000000000
--- a/ctrl/facemgr/src/util/policy.c
+++ /dev/null
@@ -1,59 +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 policy.h
- * \brief Implementation of policy description
- */
-
-#include <stdio.h>
-#include "policy.h"
-
-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 _
-};
-
-const char * policy_state_str[] = {
- #define _(x) [POLICY_STATE_ ## x] = STRINGIZE(x),
- foreach_policy_state
- #undef _
-};
-
-int
-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 < 0)
- return rc;
- cur += rc;
- if (size != 0 && cur >= s + size)
- return cur - s;
-
- return cur - s;
-}
diff --git a/ctrl/facemgr/src/util/set.h b/ctrl/facemgr/src/util/set.h
index 47a6eeaff..61df209ab 100644
--- a/ctrl/facemgr/src/util/set.h
+++ b/ctrl/facemgr/src/util/set.h
@@ -16,15 +16,27 @@
#ifndef UTIL_SET_H
#define UTIL_SET_H
+#include <hicn/util/log.h>
#include <search.h>
#include <string.h>
-#include "token.h"
+//#if !defined(__ANDROID__) && !defined(__APPLE__)
+//#include <threads.h>
+//#else
+#define thread_local _Thread_local
+//#endif /* ! __ANDROID__ */
#include "../common.h"
#define ERR_SET_EXISTS -2
#define ERR_SET_NOT_FOUND -3
-#define BUFSIZE 80
+/* FIXME: buffer overflow when this is too small... investigate */
+#define BUFSIZE 1024
+
+static inline
+int
+int_snprintf(char * buf, size_t size, int value) {
+ return snprintf(buf, size, "%d", value);
+}
static inline
int
@@ -34,7 +46,7 @@ string_snprintf(char * buf, size_t size, const char * s) {
static inline
int
-generic_snprintf(char * buf, size_t size, void * value) {
+generic_snprintf(char * buf, size_t size, const void * value) {
return snprintf(buf, BUFSIZE, "%p", value);
}
@@ -57,7 +69,9 @@ int NAME ## _add(NAME ## _t * set, const T element); \
\
int NAME ## _remove(NAME ## _t * set, const T search, T * element); \
\
-int NAME ## _get(NAME ## _t * set, const T search, T * element); \
+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);
@@ -70,7 +84,7 @@ NAME ## _initialize(NAME ## _t * set) \
{ \
set->root = NULL; \
set->size = 0; \
- return FACEMGR_SUCCESS; \
+ return 0; \
} \
\
NO_FINALIZE(NAME); \
@@ -79,49 +93,88 @@ AUTOGENERATE_CREATE_FREE(NAME); \
int \
NAME ## _add(NAME ## _t * set, const T element) \
{ \
- return tsearch(element, &set->root, (cmp_t)CMP) \
- ? FACEMGR_SUCCESS : FACEMGR_FAILURE; \
+ void * ptr = tsearch(element, &set->root, (cmp_t)CMP); \
+ if (!ptr) \
+ return -1; \
+ set->size++; \
+ return 0; \
} \
\
int \
NAME ## _remove(NAME ## _t * set, const T search, T * element) \
{ \
- T * found = tdelete(search, &set->root, (cmp_t)CMP); \
- if (found && element) \
+ T * found = tfind(search, &set->root, (cmp_t)CMP); \
+ if (!found) \
+ return ERR_SET_NOT_FOUND; \
+ if (element) \
*element = *found; \
- return found ? FACEMGR_SUCCESS : ERR_SET_NOT_FOUND; \
+ tdelete(search, &set->root, (cmp_t)CMP); \
+ set->size--; \
+ return 0; \
} \
\
int \
-NAME ## _get(NAME ## _t * set, const T search, T * element) \
+NAME ## _get(const NAME ## _t * set, const T search, T * element) \
{ \
T * found = tfind(search, &set->root, (cmp_t)CMP); \
- if (found && element) \
- *element = *found; \
- return found ? FACEMGR_SUCCESS : ERR_SET_NOT_FOUND; \
+ if (element) \
+ *element = found ? *found : NULL; \
+ return 0; \
} \
\
-void \
-__ ## NAME ## _dump_node(const void *nodep, const VISIT which, const int depth) \
+static void \
+NAME ## _dump_node(const void *nodep, const VISIT which, \
+ const int depth) \
{ \
char buf[BUFSIZE]; \
switch (which) { \
case preorder: \
- break; \
- case postorder: \
- break; \
case endorder: \
break; \
+ case postorder: \
case leaf: \
SNPRINTF(buf, BUFSIZE, *(T*)nodep); \
- printf("%s\n", buf); \
+ INFO("%s", buf); \
break; \
} \
} \
\
void \
NAME ## _dump(NAME ## _t * set) { \
- twalk(set->root, __ ## NAME ## _dump_node); \
+ 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) \
+{ \
+ *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; \
+ return set->size; \
+}
#endif /* UTIL_SET_H */
diff --git a/ctrl/libhicnctrl/CMakeLists.txt b/ctrl/libhicnctrl/CMakeLists.txt
index cb1bd722c..6b67544ee 100644
--- a/ctrl/libhicnctrl/CMakeLists.txt
+++ b/ctrl/libhicnctrl/CMakeLists.txt
@@ -26,21 +26,38 @@ set(CMAKE_MODULE_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
)
+include(BuildMacros)
+
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_MACOSX_RPATH ON)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- set(HICN_CTRL hicn-ctrl)
- set(LIBHICN_CTRL hicn-ctrl)
- set(LIBHICN_CTRL_SHARED ${LIBHICNCTRL}.shared)
- set(LIBHICN_CTRL_STATIC ${LIBHICNCTRL}.static)
-endif()
-set(LIBHICNCTRL_COMPONENT lib${LIBHICN_CTRL})
+ find_package_wrapper(Libhicn REQUIRED)
+
+ set(HICNCTRL hicnctrl)
+ set(LIBHICNCTRL hicnctrl)
+ set(LIBHICNCTRL_SHARED ${LIBHICNCTRL}.shared)
+ set(LIBHICNCTRL_STATIC ${LIBHICNCTRL}.static)
+
+else()
+ if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
+ set(HICN_LIBRARIES ${LIBHICN_STATIC})
+ list(APPEND DEPENDENCIES
+ ${LIBHICN_STATIC}
+ )
+ else ()
+ set(HICN_LIBRARIES ${LIBHICN_SHARED})
+ list(APPEND DEPENDENCIES
+ ${LIBHICN_SHARED}
+ )
+ endif ()
+
+endif()
-set(TO_INSTALL_HEADER_FILES)
+set(LIBHICNCTRL_COMPONENT lib${LIBHICNCTRL})
add_subdirectory(includes)
add_subdirectory(src)
diff --git a/ctrl/libhicnctrl/includes/ctrl.h b/ctrl/libhicnctrl/includes/ctrl.h
index 646630968..e61b7a482 120000..100644
--- a/ctrl/libhicnctrl/includes/ctrl.h
+++ b/ctrl/libhicnctrl/includes/ctrl.h
@@ -1 +1,25 @@
-hicn/ctrl.h \ No newline at end of file
+/*
+ * 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 ctrl.h
+ * \brief Main interface for hICN control library
+ */
+#ifndef HICNCTRL_H
+#define HICNCTRL_H
+
+#include <hicn/ctrl/api.h>
+
+#endif /* HICNCTRL_H */
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
index 45efb39f9..a0ee828b9 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -68,42 +68,19 @@
#include <stdbool.h>
#include <stdint.h>
+#include <hicn/util/ip_address.h>
#include "face.h"
-#include "util/types.h"
+
+#define HICN_DEFAULT_PORT 9695
#define LIBHICNCTRL_SUCCESS 0
#define LIBHICNCTRL_FAILURE -1
#define LIBHICNCTRL_NOT_IMPLEMENTED -99
#define LIBHICNCTRL_IS_ERROR(x) (x < 0)
-
-/**
- * This allows to selectively define convenience types to avoid any collision
- * when using the library in conjunction with other frameworks including similar
- * defines
- */
-#ifdef _HICNTRL_NO_DEFS
-#define _HICNTRL_NO_DEF_TYPES
-#define _HICNTRL_NO_DEF_IPADDR
-#define _HICNTRL_NO_DEF_UNIONCAST
-#endif
-
-#ifndef _HICNTRL_NO_DEF_TYPES
-typedef uint8_t u8;
-typedef uint16_t u16;
-typedef uint32_t u32;
-typedef uint64_t u64;
-#endif /* _HICNTRL_NO_DEF_TYPES */
-
-#ifndef _HICNTRL_NO_DEF_IPADDR
-#include "util/ip_address.h"
-#endif /* _HICNTRL_NO_DEF_IPADDR */
-
-#ifndef _HICNTRL_NO_DEF_UNIONCAST
/* Helper for avoiding warnings about type-punning */
#define UNION_CAST(x, destType) \
(((union {__typeof__(x) a; destType b;})x).b)
-#endif /* _HICNTRL_NO_DEF_UNIONCAST */
/******************************************************************************
* Message helper types and aliases
@@ -419,27 +396,13 @@ hc_sock_reset(hc_sock_t * s);
#endif
#define NAME_LEN 16 /* NULL-terminated right ? */
-#ifdef __linux__
#define INTERFACE_LEN 16
-#endif
#define MAXSZ_HC_NAME_ NAME_LEN
#define MAXSZ_HC_NAME MAXSZ_HC_NAME_ + NULLTERM
#define MAXSZ_HC_ID_ 10 /* Number of digits for MAX_INT */
#define MAXSZ_HC_ID MAXSZ_HC_ID_ + NULLTERM
-#define MAXSZ_HC_PROTO_ 8 /* inetX:// */
-#define MAXSZ_HC_PROTO MAXSZ_HC_PROTO_ + NULLTERM
-
-#define MAXSZ_HC_URL4_ MAXSZ_HC_PROTO_ + MAXSZ_IP4_ADDRESS_ + MAXSZ_PORT_
-#define MAXSZ_HC_URL6_ MAXSZ_HC_PROTO_ + MAXSZ_IP6_ADDRESS_ + MAXSZ_PORT_
-#define MAXSZ_HC_URL_ MAXSZ_HC_URL6_
-#define MAXSZ_HC_URL4 MAXSZ_HC_URL4_ + NULLTERM
-#define MAXSZ_HC_URL6 MAXSZ_HC_URL6_ + NULLTERM
-#define MAXSZ_HC_URL MAXSZ_HC_URL_ + NULLTERM
-
-int hc_url_snprintf(char * s, size_t size, int family,
- const ip_address_t * ip_address, u16 port);
#define foreach_type(TYPE, VAR, data) \
for (TYPE * VAR = (TYPE*)data->buffer; \
@@ -498,9 +461,7 @@ typedef int (*HC_PARSE)(const u8 *, u8 *);
// FIXME the listener should not require any port for hICN...
typedef struct {
char name[NAME_LEN]; /* K.w */ // XXX clarify what used for
-#ifdef __linux__
char interface_name[INTERFACE_LEN]; /* Kr. */
-#endif
u32 id;
hc_connection_type_t type; /* .rw */
int family; /* .rw */
@@ -509,6 +470,7 @@ typedef struct {
} hc_listener_t;
int hc_listener_create(hc_sock_t * s, hc_listener_t * listener);
+/* listener_found might eventually be allocated, and needs to be freed */
int hc_listener_get(hc_sock_t *s, hc_listener_t * listener,
hc_listener_t ** listener_found);
int hc_listener_delete(hc_sock_t * s, hc_listener_t * listener);
@@ -520,7 +482,7 @@ int hc_listener_parse(void * in, hc_listener_t * listener);
#define foreach_listener(VAR, data) foreach_type(hc_listener_t, VAR, data)
-#define MAXSZ_HC_LISTENER_ MAXSZ_HC_URL_ + SPACE + MAXSZ_HC_CONNECTION_TYPE_
+#define MAXSZ_HC_LISTENER_ INTERFACE_LEN + SPACE + MAXSZ_URL_ + SPACE + MAXSZ_HC_CONNECTION_TYPE_
#define MAXSZ_HC_LISTENER MAXSZ_HC_LISTENER_ + NULLTERM
GENERATE_FIND_HEADER(listener);
@@ -531,9 +493,15 @@ int hc_listener_snprintf(char * s, size_t size, hc_listener_t * listener);
* Connections
*----------------------------------------------------------------------------*/
+/*
+ * NOTE :
+ * - interface_name is mainly used to derive listeners from connections, but is
+ * not itself used to create connections.
+ */
typedef struct {
u32 id; /* Kr. */
char name[NAME_LEN]; /* K.w */
+ char interface_name[INTERFACE_LEN]; /* Kr. */
hc_connection_type_t type; /* .rw */
int family; /* .rw */
ip_address_t local_addr; /* .rw */
@@ -549,6 +517,7 @@ typedef struct {
int hc_connection_create(hc_sock_t * s, hc_connection_t * connection);
+/* connection_found will be allocated, and must be freed */
int hc_connection_get(hc_sock_t *s, hc_connection_t * connection,
hc_connection_t ** connection_found);
int hc_connection_update_by_id(hc_sock_t * s, int hc_connection_id,
@@ -567,13 +536,14 @@ int hc_connection_cmp(const hc_connection_t * c1, const hc_connection_t * c2);
int hc_connection_parse(void * in, hc_connection_t * connection);
#ifdef WITH_POLICY
-int hc_connection_set_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+int hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
#endif /* WITH_POLICY */
#define foreach_connection(VAR, data) foreach_type(hc_connection_t, VAR, data)
-#define MAXSZ_HC_CONNECTION_ MAXSZ_HC_CONNECTION_STATE_ + \
- 2 * MAXSZ_HC_URL_ + MAXSZ_HC_CONNECTION_TYPE_ + SPACES(3)
+#define MAXSZ_HC_CONNECTION_ MAXSZ_HC_CONNECTION_STATE_ + \
+ INTERFACE_LEN + SPACE + \
+ 2 * MAXSZ_URL_ + MAXSZ_HC_CONNECTION_TYPE_ + SPACES(3)
#define MAXSZ_HC_CONNECTION MAXSZ_HC_CONNECTION_ + NULLTERM
GENERATE_FIND_HEADER(connection);
@@ -581,38 +551,6 @@ GENERATE_FIND_HEADER(connection);
int hc_connection_snprintf(char * s, size_t size, const hc_connection_t * connection);
/*----------------------------------------------------------------------------*
- * Routes
- *----------------------------------------------------------------------------*/
-
-typedef struct {
- u8 face_id; /* Kr. */
- int family; /* Krw */
- ip_address_t remote_addr; /* krw */
- u8 len; /* krw */
- u16 cost; /* .rw */
-} hc_route_t;
-
-int hc_route_parse(void * in, hc_route_t * route);
-
-int hc_route_create(hc_sock_t * s, hc_route_t * route);
-int hc_route_delete(hc_sock_t * s, hc_route_t * route);
-int hc_route_list(hc_sock_t * s, hc_data_t ** pdata);
-
-#define foreach_route(VAR, data) foreach_type(hc_route_t, VAR, data)
-
-#define MAX_FACE_ID 255
-#define MAXSZ_FACE_ID 3
-#define MAX_COST 65535
-#define MAXSZ_COST 5
-#define MAX_LEN 255
-#define MAXSZ_LEN 3
-
-#define MAXSZ_HC_ROUTE_ MAXSZ_FACE_ID + 1 + MAXSZ_COST + 1 + MAXSZ_IP_ADDRESS + 1 + MAXSZ_LEN
-#define MAXSZ_HC_ROUTE MAXSZ_HC_ROUTE_ + NULLTERM
-
-int hc_route_snprintf(char * s, size_t size, hc_route_t * route);
-
-/*----------------------------------------------------------------------------*
* Faces
*
* A face is an abstraction introduced by the control library to abstract the
@@ -623,7 +561,7 @@ int hc_route_snprintf(char * s, size_t size, hc_route_t * route);
*----------------------------------------------------------------------------*/
typedef struct {
- u32 id;
+ u8 id;
char name[NAME_LEN];
face_t face; // or embed ?
//face_id_t parent; /* Pointer from connection to listener */
@@ -644,12 +582,47 @@ int hc_face_list(hc_sock_t * s, hc_data_t ** pdata);
#define foreach_face(VAR, data) foreach_type(hc_face_t, VAR, data)
-#define MAXSZ_HC_FACE_ 0
+#define MAX_FACE_ID 255
+#define MAXSZ_FACE_ID_ 3
+#define MAXSZ_FACE_ID MAXSZ_FACE_ID_ + NULLTERM
+#define MAXSZ_FACE_NAME_ NAMELEN
+#define MAXSZ_FACE_NAME MAXSZ_FACE_NAME_ + NULLTERM
+
+#define MAXSZ_HC_FACE_ MAXSZ_FACE_ID_ + MAXSZ_FACE_NAME_ + MAXSZ_FACE_ + 5
#define MAXSZ_HC_FACE MAXSZ_HC_FACE_ + NULLTERM
int hc_face_snprintf(char * s, size_t size, hc_face_t * face);
-/////// XXX XXX XXX XXX missing face api functions, cf punting now...
+/*----------------------------------------------------------------------------*
+ * Routes
+ *----------------------------------------------------------------------------*/
+
+typedef struct {
+ u8 face_id; /* Kr. */
+ int family; /* Krw */
+ ip_address_t remote_addr; /* krw */
+ u8 len; /* krw */
+ u16 cost; /* .rw */
+} hc_route_t;
+
+int hc_route_parse(void * in, hc_route_t * route);
+
+int hc_route_create(hc_sock_t * s, hc_route_t * route);
+int hc_route_delete(hc_sock_t * s, hc_route_t * route);
+int hc_route_list(hc_sock_t * s, hc_data_t ** pdata);
+
+#define foreach_route(VAR, data) foreach_type(hc_route_t, VAR, data)
+
+#define MAX_COST 65535
+#define MAXSZ_COST 5
+#define MAX_LEN 255
+#define MAXSZ_LEN 3
+
+#define MAXSZ_HC_ROUTE_ MAXSZ_FACE_ID + 1 + MAXSZ_COST + 1 + MAXSZ_IP_ADDRESS + 1 + MAXSZ_LEN
+#define MAXSZ_HC_ROUTE MAXSZ_HC_ROUTE_ + NULLTERM
+
+int hc_route_snprintf(char * s, size_t size, hc_route_t * route);
+
/*----------------------------------------------------------------------------*
* Punting
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
index 1d07c9b72..4209c6eb6 100755
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
@@ -32,7 +32,7 @@
#include <stdlib.h>
#ifdef WITH_POLICY
-#include "util/policy.h"
+#include <hicn/policy.h>
#endif /* WITH_POLICY */
typedef struct in6_addr ipv6_addr_t;
@@ -131,6 +131,7 @@ typedef struct {
typedef struct {
char symbolic[16];
+ //char interfaceName[16];
union commandAddr remoteIp;
union commandAddr localIp;
uint16_t remotePort;
@@ -166,9 +167,9 @@ typedef struct {
add_connection_command connectionData;
uint32_t connid;
uint8_t state;
-#ifdef WITH_UPDATE
+ uint8_t admin_state;
char connectionName[16];
-#endif /* WITH_UPDATE */
+ char interfaceName[16];
} list_connections_command;
// SIZE=64
@@ -282,10 +283,8 @@ typedef struct {
typedef struct {
union commandAddr address;
-#ifdef WITH_UPDATE
char listenerName[16];
char interfaceName[16];
-#endif /* WITH_UPDATE */
uint32_t connid;
uint16_t port;
uint8_t addressType;
@@ -310,11 +309,10 @@ typedef struct {
// SIZE=1
-//========== NEW COMMANDS ==========
-
typedef struct {
char symbolicOrConnid[16];
uint8_t admin_state;
+ uint8_t pad8[3];
} connection_set_admin_state_command;
#ifdef WITH_POLICY
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h
index 2856ce89b..5c1fecd55 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h
@@ -30,12 +30,11 @@
#define NULLTERM 1
#endif
-#ifndef _HICNTRL_NO_DEF_IPADDR
-#include "util/ip_address.h"
-#endif /* _HICNTRL_NO_DEF_IPADDR */
-#include "util/policy.h"
-#include "util/types.h"
+#include <hicn/policy.h>
+#include <hicn/util/ip_address.h>
+
+typedef unsigned int hash_t;
/* Netdevice type */
@@ -43,6 +42,7 @@
#define foreach_netdevice_type \
_(UNDEFINED) \
+ _(LOOPBACK) \
_(WIRED) \
_(WIFI) \
_(CELLULAR) \
@@ -63,25 +63,48 @@ extern const char * netdevice_type_str[];
/* 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);
+
#define NETDEVICE_UNDEFINED_INDEX 0
/* Face state */
#define foreach_face_state \
_(UNDEFINED) \
- _(PENDING_UP) \
- _(UP) \
- _(PENDING_DOWN) \
_(DOWN) \
- _(ERROR) \
+ _(UP) \
_(N)
-#define MAXSZ_FACE_STATE_ 12
+
+#define MAXSZ_FACE_STATE_ 9
#define MAXSZ_FACE_STATE MAXSZ_FACE_STATE_ + 1
typedef enum {
@@ -116,49 +139,49 @@ foreach_face_type
extern const char * face_type_str[];
-#define MAXSZ_FACE_ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_IP_ADDRESS + 2 * MAXSZ_PORT + 9
+#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 union {
- int family; /* To access family independently of face type */
- struct {
- int family;
- netdevice_t netdevice;
- ip_address_t local_addr;
- ip_address_t remote_addr;
- } hicn;
- struct {
- int family;
- ip_address_t local_addr;
- u16 local_port;
- ip_address_t remote_addr;
- u16 remote_port;
- } tunnel;
-} face_params_t;
-
typedef struct {
face_type_t type;
- face_params_t params;
face_state_t admin_state;
face_state_t state;
#ifdef WITH_POLICY
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 */
+ ip_address_t local_addr;
+ 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 ip_address_t * local_addr,
- u16 local_port, const ip_address_t * remote_addr, u16 remote_port,
+int face_initialize_udp(face_t * face, const char * interface_name,
+ const ip_address_t * local_addr, u16 local_port,
+ const 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 ip_address_t * local_addr, u16 local_port,
+face_t * face_create_udp(const char * interface_name,
+ const ip_address_t * local_addr, u16 local_port,
const ip_address_t * remote_addr, u16 remote_port, int family);
-face_t * face_create_udp_sa(const struct sockaddr * local_addr,
+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);
@@ -173,6 +196,7 @@ hash_t face_hash(const face_t * face);
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);
#endif /* HICN_FACE_H */
diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt
index 204311c39..7b4413d55 100644
--- a/ctrl/libhicnctrl/src/CMakeLists.txt
+++ b/ctrl/libhicnctrl/src/CMakeLists.txt
@@ -11,11 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-include(BuildMacros)
-
list(APPEND COMPILER_DEFINITIONS
"-DWITH_POLICY"
-# "-DWITH_UPDATE"
)
set(HEADER_FILES
@@ -26,34 +23,34 @@ set(HEADER_FILES
set(UTIL_HEADER_FILES
face.h
- util/ip_address.h
util/log.h
- util/policy.h
- util/token.h
- util/types.h
)
set(SOURCE_FILES
api.c
- util/policy.c
+ face.c
util/log.c
)
set(LIBRARIES
m
+ ${HICN_LIBRARIES}
)
set(INCLUDE_DIRS
./
../includes/
+ ${HICN_INCLUDE_DIRS}
)
-if (ANDROID_API)
- build_library(${LIBHICN_CTRL}
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
+ set(HICN_LIBRARIES ${LIBHICN_STATIC})
+ build_library(${LIBHICNCTRL}
STATIC
SOURCES ${SOURCE_FILES}
INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
LINK_LIBRARIES ${LIBRARIES}
+ DEPENDS ${LIBHICN_STATIC}
COMPONENT ${LIBHICNCTRL_COMPONENT}
DEPENDS ${LIBHICN_STATIC}
INCLUDE_DIRS ${INCLUDE_DIRS}
@@ -61,11 +58,12 @@ if (ANDROID_API)
DEFINITIONS ${COMPILER_DEFINITIONS}
)
else ()
- build_library(${LIBHICN_CTRL}
+ build_library(${LIBHICNCTRL}
SHARED STATIC
SOURCES ${SOURCE_FILES}
INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
LINK_LIBRARIES ${LIBRARIES}
+ DEPENDS ${LIBHICN_SHARED}
COMPONENT ${LIBHICNCTRL_COMPONENT}
DEPENDS ${LIBHICN_SHARED}
INCLUDE_DIRS ${INCLUDE_DIRS}
@@ -74,14 +72,14 @@ else ()
)
endif ()
-if(NOT ANDROID_API AND NOT COMPILE_FOR_IOS)
+if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Android" AND NOT COMPILE_FOR_IOS)
list(APPEND DAEMON_SRC
cli.c
)
- build_executable(${HICN_CTRL}
+ build_executable(${HICNCTRL}
SOURCES ${DAEMON_SRC}
- LINK_LIBRARIES ${LIBHICN_CTRL_SHARED}
- DEPENDS ${LIBHICN_CTRL_SHARED}
+ LINK_LIBRARIES ${LIBHICNCTRL_SHARED} ${LIBHICN_SHARED}
+ DEPENDS ${LIBHICNCTRL_SHARED} ${LIBHICN_SHARED}
COMPONENT ${LIBHICNCTRL_COMPONENT}
INCLUDE_DIRS ${INCLUDE_DIRS}
DEFINITIONS ${COMPILER_DEFINITIONS}
diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c
index 3d8a2c166..769c96076 100644
--- a/ctrl/libhicnctrl/src/api.c
+++ b/ctrl/libhicnctrl/src/api.c
@@ -28,12 +28,21 @@
#include <hicn/ctrl/api.h>
#include <hicn/ctrl/commands.h>
+#include <hicn/util/token.h>
#include "util/log.h"
-#include "util/token.h"
#include <strings.h>
#define PORT 9695
+#if 0
+#ifdef __APPLE__
+#define RANDBYTE() (u8)(arc4random() & 0xFF)
+#else
+#define RANDBYTE() (u8)(random() & 0xFF)
+#endif
+#endif
+#define RANDBYTE() (u8)(rand() & 0xFF)
+
/*
* list was working with all seq set to 0, but it seems hicnLightControl uses
* 1, and replies with the same seqno
@@ -159,8 +168,8 @@ static const hc_connection_state_t map_from_list_connections_state[] = {
};
-#define connection_state_to_face_state(x) ((face_state_t)x)
-#define face_state_to_connection_state(x) ((hc_connection_state_t)x)
+#define connection_state_to_face_state(x) ((face_state_t)(x))
+#define face_state_to_connection_state(x) ((hc_connection_state_t)(x))
#define IS_VALID_ADDR_TYPE(x) ((x >= ADDR_INET) && (x <= ADDR_UNIX))
@@ -342,6 +351,8 @@ hc_sock_parse_url(const char * url, struct sockaddr * sa)
/* FIXME URL parsing is currently not implemented */
assert(!url);
+ srand(time(NULL));
+
/*
* A temporary solution is to inspect the sa_family fields of the passed in
* sockaddr, which defaults to AF_UNSPEC (0) and thus creates an IPv4/TCP
@@ -443,7 +454,13 @@ ERR_PARSE:
int
hc_sock_send(hc_sock_t * s, hc_msg_t * msg, size_t msglen)
{
- return send(s->fd, msg, msglen, 0);
+ int rc;
+ rc = send(s->fd, msg, msglen, 0);
+ if (rc < 0) {
+ perror("hc_sock_send");
+ return -1;
+ }
+ return 0;
}
int
@@ -473,6 +490,7 @@ hc_sock_recv(hc_sock_t * s, hc_data_t * data)
// XXX
}
if (rc < 0) {
+ perror("hc_sock_recv");
/* Error occurred */
// XXX check for EWOULDBLOCK;
// XXX
@@ -647,7 +665,8 @@ hc_execute_command(hc_sock_t * s, hc_msg_t * msg, size_t msg_len,
if (!data)
goto ERR_DATA;
- hc_sock_send(s, msg, msg_len);
+ if (hc_sock_send(s, msg, msg_len) < 0)
+ goto ERR_PROCESS;
while(!data->complete) {
if (hc_sock_recv(s, data) < 0)
break;
@@ -667,52 +686,6 @@ ERR_DATA:
return LIBHICNCTRL_FAILURE;
}
-/* /!\ Please update constants in header file upon changes */
-int
-hc_url_snprintf(char * s, size_t size, int family,
- const ip_address_t * ip_address, u16 port)
-{
- char * cur = s;
- int rc;
-
- /* Other address are currently not supported */
- if (!IS_VALID_FAMILY(family)) {
- ERROR("Invalid family %d for IP address", family);
- return -1;
- }
-
- rc = snprintf(cur, s + size - cur, "inet%c://",
- (family == AF_INET) ? '4' : '6');
- if (rc < 0)
- return rc;
- cur += rc;
- if (size != 0 && cur >= s + size)
- return cur - s;
-
- rc = ip_address_snprintf(cur, s + size - cur, ip_address, family);
- if (rc < 0)
- return rc;
- cur += rc;
- if (size != 0 && cur >= s + size)
- return cur - s;
-
- rc = snprintf(cur, s + size - cur, ":");
- if (rc < 0)
- return rc;
- cur += rc;
- if (size != 0 && cur >= s + size)
- return cur - s;
-
- rc = snprintf(cur, s + size - cur, "%d", port);
- if (rc < 0)
- return rc;
- cur += rc;
- if (size != 0 && cur >= s + size)
- return cur - s;
-
- return cur - s;
-}
-
/*----------------------------------------------------------------------------*
* Listeners
*----------------------------------------------------------------------------*/
@@ -750,9 +723,7 @@ hc_listener_create(hc_sock_t * s, hc_listener_t * listener)
};
snprintf(msg.payload.symbolic, NAME_LEN, "%s", listener->name);
-#ifdef __linux__
snprintf(msg.payload.interfaceName, INTERFACE_LEN, "%s", listener->interface_name);
-#endif
hc_command_params_t params = {
.cmd = ACTION_CREATE,
@@ -772,13 +743,25 @@ hc_listener_get(hc_sock_t *s, hc_listener_t * listener,
hc_listener_t ** listener_found)
{
hc_data_t * listeners;
+ hc_listener_t * found;
if (hc_listener_list(s, &listeners) < 0)
return LIBHICNCTRL_FAILURE;
/* Test */
- if (hc_listener_find(listeners, listener, listener_found) < 0)
+ if (hc_listener_find(listeners, listener, &found) < 0) {
+ hc_data_free(listeners);
return LIBHICNCTRL_FAILURE;
+ }
+
+ if (found) {
+ *listener_found = malloc(sizeof(hc_listener_t));
+ if (!*listener_found)
+ return LIBHICNCTRL_FAILURE;
+ **listener_found = *found;
+ } else {
+ *listener_found = NULL;
+ }
hc_data_free(listeners);
@@ -818,6 +801,7 @@ hc_listener_delete(hc_sock_t * s, hc_listener_t * listener)
return LIBHICNCTRL_FAILURE;
printf("Delete listener ID=%d\n", listener_found->id);
snprintf(msg.payload.symbolicOrListenerid, NAME_LEN, "%d", listener_found->id);
+ free(listener_found);
}
hc_command_params_t params = {
@@ -879,6 +863,7 @@ hc_listener_cmp(const hc_listener_t * l1, const hc_listener_t * l2)
{
return ((l1->type == l2->type) &&
(l1->family == l2->family) &&
+ (strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN) == 0) &&
(ip_address_cmp(&l1->local_addr, &l2->local_addr, l1->family) == 0) &&
(l1->local_port == l2->local_port))
? LIBHICNCTRL_SUCCESS
@@ -913,7 +898,8 @@ hc_listener_parse(void * in, hc_listener_t * listener)
.local_addr = UNION_CAST(cmd->address, ip_address_t),
.local_port = ntohs(cmd->port),
};
- memset(listener->name, 0, NAME_LEN);
+ snprintf(listener->name, NAME_LEN, "%s", cmd->listenerName);
+ snprintf(listener->interface_name, INTERFACE_LEN, "%s", cmd->interfaceName);
return LIBHICNCTRL_SUCCESS;
}
@@ -925,14 +911,15 @@ GENERATE_FIND(listener)
int
hc_listener_snprintf(char * s, size_t size, hc_listener_t * listener)
{
- char local[MAXSZ_HC_URL];
+ char local[MAXSZ_URL];
int rc;
- rc = hc_url_snprintf(local, MAXSZ_HC_URL,
+ rc = url_snprintf(local, MAXSZ_URL,
listener->family, &listener->local_addr, listener->local_port);
if (rc < 0)
return rc;
- return snprintf(s, size+17, "%s %s",
+ return snprintf(s, size+17, "%s %s %s",
+ listener->interface_name,
local,
connection_type_str[listener->type]);
}
@@ -993,13 +980,25 @@ hc_connection_get(hc_sock_t *s, hc_connection_t * connection,
hc_connection_t ** connection_found)
{
hc_data_t * connections;
+ hc_connection_t * found;
if (hc_connection_list(s, &connections) < 0)
return LIBHICNCTRL_FAILURE;
/* Test */
- if (hc_connection_find(connections, connection, connection_found) < 0)
+ if (hc_connection_find(connections, connection, &found) < 0) {
+ hc_data_free(connections);
return LIBHICNCTRL_FAILURE;
+ }
+
+ if (found) {
+ *connection_found = malloc(sizeof(hc_connection_t));
+ if (!*connection_found)
+ return LIBHICNCTRL_FAILURE;
+ **connection_found = *found;
+ } else {
+ *connection_found = NULL;
+ }
hc_data_free(connections);
@@ -1039,6 +1038,7 @@ hc_connection_delete(hc_sock_t * s, hc_connection_t * connection)
return LIBHICNCTRL_FAILURE;
printf("Delete connection ID=%d\n", connection_found->id);
snprintf(msg.payload.symbolicOrConnid, NAME_LEN, "%d", connection_found->id);
+ free(connection_found);
}
hc_command_params_t params = {
@@ -1158,6 +1158,7 @@ hc_connection_parse(void * in, hc_connection_t * connection)
.state = state,
};
snprintf(connection->name, NAME_LEN, "%s", cmd->connectionData.symbolic);
+ snprintf(connection->interface_name, INTERFACE_LEN, "%s", cmd->interfaceName);
return LIBHICNCTRL_SUCCESS;
}
@@ -1169,23 +1170,24 @@ GENERATE_FIND(connection)
int
hc_connection_snprintf(char * s, size_t size, const hc_connection_t * connection)
{
- char local[MAXSZ_HC_URL];
- char remote[MAXSZ_HC_URL];
+ char local[MAXSZ_URL];
+ char remote[MAXSZ_URL];
int rc;
// assert(connection->connection_state)
- rc = hc_url_snprintf(local, MAXSZ_HC_URL, connection->family,
+ rc = url_snprintf(local, MAXSZ_URL, connection->family,
&connection->local_addr, connection->local_port);
if (rc < 0)
return rc;
- rc = hc_url_snprintf(remote, MAXSZ_HC_URL, connection->family,
+ rc = url_snprintf(remote, MAXSZ_URL, connection->family,
&connection->remote_addr, connection->remote_port);
if (rc < 0)
return rc;
- return snprintf(s, size, "%s %s %s %s",
+ return snprintf(s, size, "%s %s %s %s %s",
connection_state_str[connection->state],
+ connection->interface_name,
local,
remote,
connection_type_str[connection->type]);
@@ -1195,7 +1197,7 @@ hc_connection_snprintf(char * s, size_t size, const hc_connection_t * connection
int
hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
- hc_connection_state_t admin_state)
+ face_state_t state)
{
struct {
header_control_message hdr;
@@ -1208,7 +1210,7 @@ hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
.seqNum = s->send_seq,
},
.payload = {
- .admin_state = admin_state,
+ .admin_state = state,
},
};
snprintf(msg.payload.symbolicOrConnid, NAME_LEN, "%s", conn_id_or_name);
@@ -1436,13 +1438,12 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool
switch(f->type) {
case FACE_TYPE_HICN:
- /* FIXME truncations, collisions, ... */
*connection = (hc_connection_t) {
.type = CONNECTION_TYPE_HICN,
- .family = f->params.hicn.family,
- .local_addr = f->params.hicn.local_addr,
+ .family = f->family,
+ .local_addr = f->local_addr,
.local_port = 0,
- .remote_addr = f->params.hicn.remote_addr,
+ .remote_addr = f->remote_addr,
.remote_port = 0,
.admin_state = face_state_to_connection_state(f->admin_state),
.state = face_state_to_connection_state(f->state),
@@ -1451,16 +1452,18 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool
#endif /* WITH_POLICY */
};
snprintf(connection->name, NAME_LEN, "%s",
- f->params.hicn.netdevice.name);
+ f->netdevice.name);
+ snprintf(connection->interface_name, INTERFACE_LEN, "%s",
+ f->netdevice.name);
break;
case FACE_TYPE_TCP:
*connection = (hc_connection_t) {
.type = CONNECTION_TYPE_TCP,
- .family = f->params.hicn.family,
- .local_addr = f->params.tunnel.local_addr,
- .local_port = f->params.tunnel.local_port,
- .remote_addr = f->params.tunnel.remote_addr,
- .remote_port = f->params.tunnel.remote_port,
+ .family = f->family,
+ .local_addr = f->local_addr,
+ .local_port = f->local_port,
+ .remote_addr = f->remote_addr,
+ .remote_port = f->remote_port,
.admin_state = face_state_to_connection_state(f->admin_state),
.state = face_state_to_connection_state(f->state),
#ifdef WITH_POLICY
@@ -1468,23 +1471,21 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool
#endif /* WITH_POLICY */
};
if (generate_name) {
-#ifdef __APPLE__
- snprintf(connection->name, NAME_LEN, "tcp%d", arc4random() & 0xFF);
-#else
- snprintf(connection->name, NAME_LEN, "tcp%ld", random() & 0xFF);
-#endif
+ snprintf(connection->name, NAME_LEN, "tcp%u", RANDBYTE());
} else {
memset(connection->name, 0, NAME_LEN);
}
+ snprintf(connection->interface_name, INTERFACE_LEN, "%s",
+ f->netdevice.name);
break;
case FACE_TYPE_UDP:
*connection = (hc_connection_t) {
.type = CONNECTION_TYPE_UDP,
.family = AF_INET,
- .local_addr = f->params.tunnel.local_addr,
- .local_port = f->params.tunnel.local_port,
- .remote_addr = f->params.tunnel.remote_addr,
- .remote_port = f->params.tunnel.remote_port,
+ .local_addr = f->local_addr,
+ .local_port = f->local_port,
+ .remote_addr = f->remote_addr,
+ .remote_port = f->remote_port,
.admin_state = face_state_to_connection_state(f->admin_state),
.state = face_state_to_connection_state(f->state),
#ifdef WITH_POLICY
@@ -1492,20 +1493,21 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool
#endif /* WITH_POLICY */
};
if (generate_name) {
-#ifdef __APPLE__
- snprintf(connection->name, NAME_LEN, "udp%d", arc4random() & 0xFF);
-#else
- snprintf(connection->name, NAME_LEN, "udp%ld", random() & 0xFF);
-#endif
+ snprintf(connection->name, NAME_LEN, "udp%u", RANDBYTE());
} else {
memset(connection->name, 0, NAME_LEN);
}
+ snprintf(connection->interface_name, INTERFACE_LEN, "%s",
+ f->netdevice.name);
break;
default:
return LIBHICNCTRL_FAILURE;
}
- return LIBHICNCTRL_SUCCESS;
+ snprintf(connection->interface_name, INTERFACE_LEN, "%s",
+ f->netdevice.name);
+
+ return LIBHICNCTRL_SUCCESS;
}
/* CONNECTION -> FACE */
@@ -1519,13 +1521,11 @@ hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face)
.id = connection->id,
.face = {
.type = FACE_TYPE_TCP,
- .params.tunnel = {
- .family = connection->family,
- .local_addr = connection->local_addr,
- .local_port = connection->local_port,
- .remote_addr = connection->remote_addr,
- .remote_port = connection->remote_port,
- },
+ .family = connection->family,
+ .local_addr = connection->local_addr,
+ .local_port = connection->local_port,
+ .remote_addr = connection->remote_addr,
+ .remote_port = connection->remote_port,
.admin_state = connection_state_to_face_state(connection->admin_state),
.state = connection_state_to_face_state(connection->state),
#ifdef WITH_POLICY
@@ -1539,13 +1539,11 @@ hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face)
.id = connection->id,
.face = {
.type = FACE_TYPE_UDP,
- .params.tunnel = {
- .family = connection->family,
- .local_addr = connection->local_addr,
- .local_port = connection->local_port,
- .remote_addr = connection->remote_addr,
- .remote_port = connection->remote_port,
- },
+ .family = connection->family,
+ .local_addr = connection->local_addr,
+ .local_port = connection->local_port,
+ .remote_addr = connection->remote_addr,
+ .remote_port = connection->remote_port,
.admin_state = connection_state_to_face_state(connection->admin_state),
.state = connection_state_to_face_state(connection->state),
#ifdef WITH_POLICY
@@ -1559,12 +1557,10 @@ hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face)
.id = connection->id,
.face = {
.type = FACE_TYPE_HICN,
- .params.hicn = {
- .family = connection->family,
- .netdevice.index = NETDEVICE_UNDEFINED_INDEX, // XXX
- .local_addr = connection->local_addr,
- .remote_addr = connection->remote_addr,
- },
+ .family = connection->family,
+ .netdevice.index = NETDEVICE_UNDEFINED_INDEX, // XXX
+ .local_addr = connection->local_addr,
+ .remote_addr = connection->remote_addr,
.admin_state = connection_state_to_face_state(connection->admin_state),
.state = connection_state_to_face_state(connection->state),
#ifdef WITH_POLICY
@@ -1576,7 +1572,11 @@ hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face)
default:
return LIBHICNCTRL_FAILURE;
}
+ face->face.netdevice.name[0] = '\0';
+ face->face.netdevice.index = 0;
snprintf(face->name, NAME_LEN, "%s", connection->name);
+ snprintf(face->face.netdevice.name, INTERFACE_LEN, "%s", connection->interface_name);
+ netdevice_update_index(&face->face.netdevice);
return LIBHICNCTRL_SUCCESS;
}
@@ -1592,6 +1592,8 @@ hc_connection_to_local_listener(const hc_connection_t * connection, hc_listener_
.local_addr = connection->local_addr,
.local_port = connection->local_port,
};
+ snprintf(listener->name, NAME_LEN, "lst%u", RANDBYTE()); // generate name
+ snprintf(listener->interface_name, INTERFACE_LEN, "%s", connection->interface_name);
return LIBHICNCTRL_SUCCESS;
}
@@ -1631,8 +1633,11 @@ hc_face_create(hc_sock_t * s, hc_face_t * face)
/* We need to create the listener if it does not exist */
if (hc_listener_create(s, &listener) < 0) {
ERROR("[hc_face_create] Could not create listener.");
+ free(listener_found);
return LIBHICNCTRL_FAILURE;
}
+ } else {
+ free(listener_found);
}
/* Create corresponding connection */
@@ -1656,6 +1661,7 @@ hc_face_create(hc_sock_t * s, hc_face_t * face)
}
face->id = connection_found->id;
+ free(connection_found);
break;
@@ -1674,6 +1680,7 @@ hc_face_create(hc_sock_t * s, hc_face_t * face)
break;
default:
ERROR("[hc_face_create] Unknwon face type.");
+
return LIBHICNCTRL_FAILURE;
};
@@ -1702,7 +1709,9 @@ hc_face_get(hc_sock_t * s, hc_face_t * face, hc_face_t ** face_found)
*face_found = NULL;
return LIBHICNCTRL_SUCCESS;
}
+ *face_found = malloc(sizeof(face_t));
hc_connection_to_face(connection_found, *face_found);
+ free(connection_found);
break;
case FACE_TYPE_HICN_LISTENER:
@@ -1716,7 +1725,9 @@ hc_face_get(hc_sock_t * s, hc_face_t * face, hc_face_t ** face_found)
*face_found = NULL;
return LIBHICNCTRL_SUCCESS;
}
+ *face_found = malloc(sizeof(face_t));
hc_listener_to_face(listener_found, *face_found);
+ free(listener_found);
break;
default:
@@ -1776,6 +1787,71 @@ ERR:
int
hc_face_snprintf(char * s, size_t size, hc_face_t * face)
{
+ /* URLs are also big enough to contain IP addresses in the hICN case */
+ char local[MAXSZ_URL];
+ char remote[MAXSZ_URL];
+#ifdef WITH_POLICY
+ char tags[MAXSZ_POLICY_TAGS];
+#endif /* WITH_POLICY */
+ int rc;
+
+ switch(face->face.type) {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_HICN_LISTENER:
+ rc = ip_address_snprintf(local, MAXSZ_URL,
+ &face->face.local_addr,
+ face->face.family);
+ if (rc < 0)
+ return rc;
+ rc = ip_address_snprintf(remote, MAXSZ_URL,
+ &face->face.remote_addr,
+ face->face.family);
+ if (rc < 0)
+ return rc;
+ break;
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_UDP_LISTENER:
+ rc = url_snprintf(local, MAXSZ_URL, face->face.family,
+ &face->face.local_addr,
+ face->face.local_port); if (rc < 0)
+ return rc;
+ rc = url_snprintf(remote, MAXSZ_URL, face->face.family,
+ &face->face.remote_addr,
+ face->face.remote_port); if (rc < 0)
+ if (rc < 0)
+ return rc;
+ break;
+ default:
+ return LIBHICNCTRL_FAILURE;
+ }
+
+ // [#ID NAME] TYPE LOCAL_URL REMOTE_URL STATE/ADMIN_STATE (TAGS)
+#ifdef WITH_POLICY
+ rc = policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->face.tags);
+ if (rc < 0)
+ return rc;
+
+ return snprintf(s, size, "[#%d %s] %s %s %s %s/%s (%s)",
+ face->id,
+ face->name,
+ face_type_str[face->face.type],
+ local,
+ remote,
+ face_state_str[face->face.state],
+ face_state_str[face->face.admin_state],
+ tags);
+#else
+ return snprintf(s, size, "[#%d %s] %s %s %s %s/%s",
+ face->id,
+ face->name,
+ face_type_str[face->face.type],
+ local,
+ remote,
+ face_state_str[face->face.state],
+ face_state_str[face->face.admin_state]);
+#endif /* WITH_POLICY */
return LIBHICNCTRL_SUCCESS;
}
@@ -1783,7 +1859,7 @@ int
hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, // XXX wrong identifier
face_state_t admin_state)
{
- return hc_connection_set_admin_state(s, conn_id_or_name, (hc_connection_state_t)admin_state);
+ return hc_connection_set_admin_state(s, conn_id_or_name, admin_state);
}
/*----------------------------------------------------------------------------*
diff --git a/ctrl/libhicnctrl/src/cli.c b/ctrl/libhicnctrl/src/cli.c
index 70620a84f..6798b5aec 100644
--- a/ctrl/libhicnctrl/src/cli.c
+++ b/ctrl/libhicnctrl/src/cli.c
@@ -22,9 +22,8 @@
#include <unistd.h> // getopt
#include <hicn/ctrl.h>
-
-#include "util/ip_address.h"
-#include "util/token.h"
+#include <hicn/util/ip_address.h>
+#include <hicn/util/token.h>
#define die(LABEL, MESSAGE) do { \
diff --git a/ctrl/libhicnctrl/src/face.c b/ctrl/libhicnctrl/src/face.c
index 9e0fbb597..41ff58f81 100644
--- a/ctrl/libhicnctrl/src/face.c
+++ b/ctrl/libhicnctrl/src/face.c
@@ -21,10 +21,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <hicn/util/token.h>
-#include "face.h"
+#include <hicn/ctrl/face.h>
#include "util/hash.h"
-#include "util/token.h"
#define member_size(type, member) sizeof(((type *)0)->member)
@@ -37,6 +37,112 @@ 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)
+{
+ 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);
+}
+
/* Face state */
@@ -61,33 +167,42 @@ foreach_face_type
int
face_initialize(face_t * face)
{
- bzero(face, sizeof(face_t)); /* 0'ed for hash */
+ memset(face, 0, sizeof(face_t)); /* 0'ed for hash */
return 1;
}
int
-face_initialize_udp(face_t * face, const ip_address_t * local_addr,
- u16 local_port, const ip_address_t * remote_addr, u16 remote_port,
+face_initialize_udp(face_t * face, const char * interface_name, const
+ ip_address_t * local_addr, u16 local_port,
+ const ip_address_t * remote_addr, u16 remote_port,
int family)
{
+ if (!local_addr)
+ return -1;
+
*face = (face_t) {
.type = FACE_TYPE_UDP,
- .params.tunnel = {
- .family = family,
- .local_addr = *local_addr,
- .local_port = local_port,
- .remote_addr = *remote_addr,
- .remote_port = remote_port,
- },
+ .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 struct sockaddr * local_addr,
+face_initialize_udp_sa(face_t * face, const char * interface_name,
+ const struct sockaddr * local_addr,
const struct sockaddr * remote_addr)
{
- if (local_addr->sa_family != remote_addr->sa_family)
+ if (!local_addr)
+ return -1;
+
+ if (remote_addr && (local_addr->sa_family != remote_addr->sa_family))
return -1;
switch (local_addr->sa_family) {
@@ -97,14 +212,14 @@ face_initialize_udp_sa(face_t * face, const struct sockaddr * local_addr,
struct sockaddr_in *rsai = (struct sockaddr_in *)remote_addr;
*face = (face_t) {
.type = FACE_TYPE_UDP,
- .params.tunnel = {
- .family = AF_INET,
- .local_addr.v4.as_inaddr = lsai->sin_addr,
- .local_port = ntohs(lsai->sin_port),
- .remote_addr.v4.as_inaddr = rsai->sin_addr,
- .remote_port = ntohs(rsai->sin_port),
- },
+ .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:
@@ -113,19 +228,22 @@ face_initialize_udp_sa(face_t * face, const struct sockaddr * local_addr,
struct sockaddr_in6 *rsai = (struct sockaddr_in6 *)remote_addr;
*face = (face_t) {
.type = FACE_TYPE_UDP,
- .params.tunnel = {
- .family = AF_INET6,
- .local_addr.v6.as_in6addr = lsai->sin6_addr,
- .local_port = ntohs(lsai->sin6_port),
- .remote_addr.v6.as_in6addr = rsai->sin6_addr,
- .remote_port = ntohs(rsai->sin6_port),
- },
+ .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;
}
@@ -135,11 +253,12 @@ face_t * face_create()
return face;
}
-face_t * face_create_udp(const ip_address_t * local_addr, u16 local_port,
+face_t * face_create_udp(const char * interface_name,
+ const ip_address_t * local_addr, u16 local_port,
const ip_address_t * remote_addr, u16 remote_port, int family)
{
face_t * face = face_create();
- if (face_initialize_udp(face, local_addr, local_port, remote_addr, remote_port, family) < 0)
+ if (face_initialize_udp(face, interface_name, local_addr, local_port, remote_addr, remote_port, family) < 0)
goto ERR_INIT;
return face;
@@ -148,11 +267,12 @@ ERR_INIT:
return NULL;
}
-face_t * face_create_udp_sa(const struct sockaddr * local_addr,
+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, local_addr, remote_addr) < 0)
+ if (face_initialize_udp_sa(face, interface_name, local_addr, remote_addr) < 0)
goto ERR_INIT;
return face;
@@ -166,10 +286,6 @@ void face_free(face_t * face)
free(face);
}
-#define face_param_cmp(f1, f2, face_param_type) \
- memcmp(&f1->type, &f2->type, \
- member_size(face_params_t, face_param_type));
-
/**
* \brief Compare two faces
* \param [in] f1 - First face
@@ -182,18 +298,61 @@ void face_free(face_t * face)
int
face_cmp(const face_t * f1, const face_t * f2)
{
- if (f1->type != f2->type)
- return false;
+
+ 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:
- return face_param_cmp(f1, f2, hicn);
+ ret = ip_address_cmp(&f1->local_addr, &f2->local_addr, f1->family);
+ if (ret != 0)
+ return ret;
+
+ ret = ip_address_cmp(&f1->remote_addr, &f2->remote_addr, f1->family);
+ if (ret != 0)
+ return ret;
+
+ break;
+
case FACE_TYPE_TCP:
case FACE_TYPE_UDP:
- return face_param_cmp(f1, f2, tunnel);
+ ret = ip_address_cmp(&f1->local_addr, &f2->local_addr, f1->family);
+ if (ret != 0)
+ return ret;
+
+ ret = f1->local_port - f2->local_port;
+ if (ret != 0)
+ return ret;
+
+ ret = ip_address_cmp(&f1->remote_addr, &f2->remote_addr, f1->family);
+ if (ret != 0)
+ return ret;
+
+ ret = f1->remote_port - f2->remote_port;
+ if (ret != 0)
+ return ret;
+
+ break;
default:
- return false;
+ break;
}
+
+ return 0;
}
hash_t
@@ -209,34 +368,59 @@ face_snprintf(char * s, size_t size, const face_t * face)
{
switch(face->type) {
case FACE_TYPE_HICN:
- return 0; // XXX Not implemented
+ {
+ char local[MAXSZ_IP_ADDRESS];
+ char remote[MAXSZ_IP_ADDRESS];
+ char tags[MAXSZ_POLICY_TAGS];
+
+ ip_address_snprintf(local, MAXSZ_IP_ADDRESS,
+ &face->local_addr,
+ face->family);
+ ip_address_snprintf(remote, MAXSZ_IP_ADDRESS,
+ &face->remote_addr,
+ face->family);
+ policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->tags);
+ 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:
- {
- char local[MAXSZ_IP_ADDRESS];
- char remote[MAXSZ_IP_ADDRESS];
-
- ip_address_snprintf(local, MAXSZ_IP_ADDRESS,
- &face->params.tunnel.local_addr,
- face->params.tunnel.family);
- ip_address_snprintf(remote, MAXSZ_IP_ADDRESS,
- &face->params.tunnel.remote_addr,
- face->params.tunnel.family);
-
- return snprintf(s, size, "%s [%s:%d -> %s:%d]",
- face_type_str[face->type],
- local,
- face->params.tunnel.local_port,
- remote,
- face->params.tunnel.remote_port);
- }
- break;
+ {
+ char local[MAXSZ_IP_ADDRESS];
+ char remote[MAXSZ_IP_ADDRESS];
+ char tags[MAXSZ_POLICY_TAGS];
+
+ ip_address_snprintf(local, MAXSZ_IP_ADDRESS,
+ &face->local_addr,
+ face->family);
+ ip_address_snprintf(remote, MAXSZ_IP_ADDRESS,
+ &face->remote_addr,
+ face->family);
+ policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->tags);
+
+ 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 0;
+ 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)
{
diff --git a/ctrl/libhicnctrl/src/util/ip_address.h b/ctrl/libhicnctrl/src/util/ip_address.h
deleted file mode 100644
index 472cceeea..000000000
--- a/ctrl/libhicnctrl/src/util/ip_address.h
+++ /dev/null
@@ -1,316 +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 ip_address.h
- * \brief IP address type support
- */
-#ifndef UTIL_IP_ADDRESS_H
-#define UTIL_IP_ADDRESS_H
-
-#include <arpa/inet.h> // inet_ntop
-#ifdef __APPLE__
-#include <libkern/OSByteOrder.h>
-#define __bswap_constant_32(x) OSSwapInt32(x)
-#include <machine/endian.h>
-#else
-#ifdef __ANDROID__
-#include <byteswap.h>
-#endif
-#include <endian.h>
-#endif
-#include <errno.h>
-#include <netdb.h> // struct addrinfo
-#include <netinet/in.h> // INET*_ADDRSTRLEN, IN*ADDR_LOOPBACK
-#include <stdlib.h>
-#include <string.h> // memset
-
-#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 IP_MAX_ADDR_LEN IPV6_ADDR_LEN
-
-#define DUMMY_PORT 1234
-
-typedef union {
- union {
- struct in_addr as_inaddr;
- u8 as_u8[4];
- u16 as_u16[2];
- u32 as_u32;
- } v4;
- union {
- struct in6_addr as_in6addr;
- u8 as_u8[16];
- u16 as_u16[8];
- u32 as_u32[4];
- u64 as_u64[2];
- } v6;
- u8 buffer[IP_MAX_ADDR_LEN];
- u8 as_u8[IP_MAX_ADDR_LEN];
- u16 as_u16[IP_MAX_ADDR_LEN >> 1];
- u32 as_u32[IP_MAX_ADDR_LEN >> 2];
- u64 as_u64[IP_MAX_ADDR_LEN >> 3];
-} ip_address_t;
-
-#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
-
-
-typedef struct {
- int family;
- ip_address_t address;
- u8 len;
-} ip_prefix_t;
-
-#define MAXSZ_PREFIX_ MAXSZ_IP_ADDRESS_ + 1 + 3
-#define MAXSZ_PREFIX MAXSZ_PREFIX_ + 1
-
-/* No htonl() with const */
-static const ip_address_t IPV4_LOOPBACK = {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#ifdef __ANDROID__
- .v4.as_inaddr.s_addr = bswap_32(INADDR_LOOPBACK),
-#else
- .v4.as_inaddr.s_addr = __bswap_constant_32(INADDR_LOOPBACK),
-#endif
-#else
- .v4.as_inaddr.s_addr = INADDR_LOOPBACK,
-#endif
-};
-
-static const ip_address_t IPV6_LOOPBACK = {
- .v6.as_in6addr = IN6ADDR_LOOPBACK_INIT,
-};
-
-static const ip_address_t IPV4_ANY = {
- .v4.as_inaddr.s_addr = INADDR_ANY,
-};
-
-static const ip_address_t IPV6_ANY = {
- .v6.as_in6addr = IN6ADDR_ANY_INIT,
-};
-
-#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) && (x < MAX_PORT))
-
-#define MAXSZ_PORT_ 5
-#define MAXSZ_PORT MAXSZ_PORT_ + 1
-
-#define IS_VALID_FAMILY(x) ((x == AF_INET) || (x == AF_INET6))
-
-static inline
-int
-ip_address_get_family (const char * ip_address)
-{
- struct addrinfo hint, *res = NULL;
- int rc;
-
- memset (&hint, '\0', sizeof hint);
-
- hint.ai_family = PF_UNSPEC;
- hint.ai_flags = AI_NUMERICHOST;
-
- rc = getaddrinfo (ip_address, NULL, &hint, &res);
- if (rc)
- {
- return -1;
- }
- rc = res->ai_family;
- freeaddrinfo (res);
- return rc;
-}
-
-static inline
-int
-ip_address_len (const ip_address_t * ip_address, int family)
-{
- return (family == AF_INET6) ? IPV6_ADDR_LEN :
- (family == AF_INET) ? IPV4_ADDR_LEN : 0;
-}
-
-static inline
-int
-ip_address_ntop (const ip_address_t * ip_address, char *dst, const size_t len,
- int family)
-{
- const char * s = inet_ntop (family, ip_address->buffer, dst, len);
- return (s ? 1 : -1);
-}
-
-/*
- * Parse ip addresses in presentation format
- */
-static inline
-int
-ip_address_pton (const char *ip_address_str, ip_address_t * ip_address)
-{
- int pton_fd;
- char *addr = strdup (ip_address_str);
- int family;
-
-
- family = ip_address_get_family (addr);
-
- switch (family)
- {
- case AF_INET6:
- pton_fd = inet_pton (AF_INET6, addr, &ip_address->buffer);
- break;
- case AF_INET:
- pton_fd = inet_pton (AF_INET, addr, &ip_address->buffer);
- break;
- default:
- goto ERR;
- }
-
- // 0 = not in presentation format
- // < 0 = other error (use perror)
- if (pton_fd <= 0)
- {
- goto ERR;
- }
-
- return 1;
-ERR:
- free (addr);
- return -1;
-}
-
-
-
-static inline
-int
-ip_address_snprintf(char * s, size_t size, const ip_address_t * ip_address, int family)
-{
- size_t len = family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN;
- const char * rc = inet_ntop (family, ip_address->buffer, s, len);
- return rc ? strlen(rc) : -1;
-}
-
-
-static inline
-int
-ip_address_to_sockaddr(const ip_address_t * ip_address,
- struct sockaddr *sockaddr_address, int family)
-{
- struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) sockaddr_address;
- struct sockaddr_in *tmp4 = (struct sockaddr_in *) sockaddr_address;
-
- switch (family)
- {
- case AF_INET6:
- tmp6->sin6_family = AF_INET6;
- tmp6->sin6_port = DUMMY_PORT;
- tmp6->sin6_scope_id = 0;
- memcpy (&tmp6->sin6_addr, ip_address->buffer, IPV6_ADDR_LEN);
- break;
- case AF_INET:
- tmp4->sin_family = AF_INET;
- tmp4->sin_port = DUMMY_PORT;
- memcpy (&tmp4->sin_addr, ip_address->buffer, IPV4_ADDR_LEN);
- break;
- default:
- return -1;
- }
-
- return 1;
-}
-
-static inline
-int
-ip_address_cmp(const ip_address_t * ip1, const ip_address_t * ip2, int family)
-{
- return memcmp(ip1, ip2, ip_address_len(ip1, family));
-}
-
-/* Parse IP Prefixes in presentation format (in bits, separated by a slash) */
-static inline
-int
-ip_prefix_pton (const char *ip_address_str, ip_prefix_t * ip_prefix)
-{
- int pton_fd;
- char *p;
- char *eptr;
- char *addr = strdup (ip_address_str);
-
- p = strchr (addr, '/');
- if (!p)
- {
- ip_prefix->len = 0; // until we get the ip address family
- }
- else
- {
- ip_prefix->len = strtoul (p + 1, &eptr, 10);
- *p = 0;
- }
-
- ip_prefix->family = ip_address_get_family (addr);
-
- switch (ip_prefix->family)
- {
- case AF_INET6:
- if (ip_prefix->len > IPV6_ADDR_LEN_BITS)
- goto ERR;
- pton_fd = inet_pton (AF_INET6, addr, &ip_prefix->address.buffer);
- break;
- case AF_INET:
- if (ip_prefix->len > IPV4_ADDR_LEN_BITS)
- goto ERR;
- pton_fd = inet_pton (AF_INET, addr, &ip_prefix->address.buffer);
- break;
- default:
- goto ERR;
- }
-
- // 0 = not in presentation format
- // < 0 = other error (use perror)
- if (pton_fd <= 0)
- {
- goto ERR;
- }
-
- return 1;
-ERR:
- free (addr);
- return -1;
-}
-
-static inline
-int
-ip_prefix_ntop (const ip_prefix_t * ip_prefix, char *dst, size_t size)
-{
- char ip_s[MAXSZ_IP_ADDRESS];
- const char * s = inet_ntop (ip_prefix->family, ip_prefix->address.buffer, ip_s, MAXSZ_IP_ADDRESS);
- if (!s)
- return -1;
- size_t n = snprintf(dst, size, "%s/%d", ip_s, ip_prefix->len);
-
- return (n > 0 ? 1 : -1);
-}
-
-#endif /* UTIL_IP_ADDRESS_H */
diff --git a/ctrl/libhicnctrl/src/util/policy.c b/ctrl/libhicnctrl/src/util/policy.c
deleted file mode 100644
index 90dbc72cd..000000000
--- a/ctrl/libhicnctrl/src/util/policy.c
+++ /dev/null
@@ -1,53 +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 policy.h
- * \brief Implementation of policy description
- */
-
-#include <stdio.h>
-#include "policy.h"
-
-const char * policy_tag_str[] = {
- #define _(x) [POLICY_TAG_ ## x] = STRINGIZE(x),
- foreach_policy_tag
- #undef _
-};
-
-const char * policy_state_str[] = {
- #define _(x) [POLICY_STATE_ ## x] = STRINGIZE(x),
- foreach_policy_state
- #undef _
-};
-
-int
-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 < 0)
- return rc;
- cur += rc;
- if (size != 0 && cur >= s + size)
- return cur - s;
-
- return cur - s;
-}
diff --git a/ctrl/libhicnctrl/src/util/policy.h b/ctrl/libhicnctrl/src/util/policy.h
deleted file mode 100644
index 231e53f73..000000000
--- a/ctrl/libhicnctrl/src/util/policy.h
+++ /dev/null
@@ -1,266 +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 policy.h
- * \brief Policy description
- */
-#ifndef HICN_POLICY_H
-#define HICN_POLICY_H
-
-#include <netinet/in.h> // INET*_ADDRSTRLEN
-#include "token.h"
-
-/* POLICY TAG */
-
-#define foreach_policy_tag \
- /* Interface type */ \
- _(WIRED) \
- _(WIFI) \
- _(CELLULAR) \
- /* QoS */ \
- _(BEST_EFFORT) \
- _(REALTIME) \
- _(MULTIPATH) \
- /* Security */ \
- _(TRUSTED)
-
-typedef enum {
-#define _(x) POLICY_TAG_ ## x,
-foreach_policy_tag
-#undef _
- POLICY_TAG_N
-} policy_tag_t;
-
-#define MAXSZ_POLICY_TAG_ 11
-#define MAXSZ_POLICY_TAG MAXSZ_POLICY_TAG_ + 1
-
-extern const char * policy_tag_str[];
-
-
-/* POLICY_TAGS */
-
-typedef int policy_tags_t;
-
-static inline
-void policy_tags_add(policy_tags_t * tags, policy_tag_t tag)
-{
- *tags |= (1 << tag);
-}
-
-static inline
-void policy_tags_remove(policy_tags_t * tags, policy_tag_t tag)
-{
- *tags &= ~(1 << tag);
-}
-
-static inline
-int policy_tags_has(policy_tags_t tags, policy_tag_t tag)
-{
- return tags & (1 << tag);
-}
-
-#define POLICY_TAGS_EMPTY 0
-
-
-/* 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
-#undef _
-} policy_state_t;
-
-#define MAXSZ_POLICY_STATE_ 8
-#define MAXSZ_POLICY_STATE MAXSZ_POLICY_STATE_ + 1
-
-extern const char * policy_state_str[];
-
-
-/* POLICY TAG STATE */
-
-typedef struct {
- 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);
-
-
-/* INTERFACE STATS */
-
-typedef struct {
- float throughput;
- float latency;
- float loss_rate;
-} interface_stats_t;
-
-#define INTERFACE_STATS_NONE { \
- .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;
-} policy_stats_t;
-
-#define POLICY_STATS_NONE { \
- .wired = INTERFACE_STATS_NONE, \
- .wifi = INTERFACE_STATS_NONE, \
- .cellular = INTERFACE_STATS_NONE, \
- .all = INTERFACE_STATS_NONE, \
-}
-
-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, \
-}
-
-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, \
-}
-
-/* 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;
-} policy_t;
-
-static const policy_t POLICY_NONE = {
- .app_name = { 0 },
- .tags = {
-#define _(x) [POLICY_TAG_ ## x] = { POLICY_STATE_NEUTRAL, 0 },
-foreach_policy_tag
-#undef _
- },
- .stats = POLICY_STATS_NONE,
-};
-
-
-/* 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];
- };
- policy_t policy;
-} policy_description_t;
-
-/* DEFAULT POLICY */
-
-static const policy_description_t default_policy[] = {
- {
- .family = AF_INET6,
- .ipv6_prefix = "a001::/16",
- .policy = {
- .app_name = "Webex",
- .tags = {
- [POLICY_TAG_WIRED] = { POLICY_STATE_PREFER, 0 },
- [POLICY_TAG_WIFI] = { POLICY_STATE_NEUTRAL, 0 },
- [POLICY_TAG_CELLULAR] = { POLICY_STATE_AVOID, 1 },
- [POLICY_TAG_BEST_EFFORT] = { POLICY_STATE_PROHIBIT, 0 },
- [POLICY_TAG_REALTIME] = { POLICY_STATE_REQUIRE, 1 },
- [POLICY_TAG_MULTIPATH] = { POLICY_STATE_AVOID, 0 },
- [POLICY_TAG_TRUSTED] = { POLICY_STATE_REQUIRE, 1 },
- },
- .stats = POLICY_STATS_NONE,
- },
- },
- {
- .family = AF_INET6,
- .ipv6_prefix = "b001::/16",
- .policy = {
- .app_name = "Video Streaming",
- .tags = {
- [POLICY_TAG_WIRED] = { POLICY_STATE_PREFER, 0 },
- [POLICY_TAG_WIFI] = { POLICY_STATE_NEUTRAL, 0 },
- [POLICY_TAG_CELLULAR] = { POLICY_STATE_NEUTRAL, 0 },
- [POLICY_TAG_BEST_EFFORT] = { POLICY_STATE_PROHIBIT, 0 },
- [POLICY_TAG_REALTIME] = { POLICY_STATE_REQUIRE, 0 },
- [POLICY_TAG_MULTIPATH] = { POLICY_STATE_AVOID, 0 },
- [POLICY_TAG_TRUSTED] = { POLICY_STATE_PREFER, 0 },
- },
- .stats = POLICY_STATS_NONE,
- },
- },
- {
- .family = AF_INET6,
- .ipv6_prefix = "c001::/16",
- .policy = {
- .app_name = "*",
- .tags = {
- [POLICY_TAG_WIRED] = { POLICY_STATE_PREFER, 0 },
- [POLICY_TAG_WIFI] = { POLICY_STATE_NEUTRAL, 0 },
- [POLICY_TAG_CELLULAR] = { POLICY_STATE_NEUTRAL, 0 },
- [POLICY_TAG_BEST_EFFORT] = { POLICY_STATE_PROHIBIT, 0 },
- [POLICY_TAG_REALTIME] = { POLICY_STATE_REQUIRE, 0 },
- [POLICY_TAG_MULTIPATH] = { POLICY_STATE_AVOID, 0 },
- [POLICY_TAG_TRUSTED] = { POLICY_STATE_PROHIBIT, 1 },
- },
- .stats = POLICY_STATS_NONE,
- },
- },
-};
-
-#endif /* HICN_POLICY_H */
diff --git a/ctrl/libhicnctrl/src/util/token.h b/ctrl/libhicnctrl/src/util/token.h
deleted file mode 100644
index 43e0a77b2..000000000
--- a/ctrl/libhicnctrl/src/util/token.h
+++ /dev/null
@@ -1,40 +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.
- */
-
-/* Token concatenation */
-
-/*
- * 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
-
-/*
- * Concatenate preprocessor tokens A and B after macro-expanding them.
- */
-#define PPCAT(A, B) PPCAT_NX(A, B)
-
-/* Token stringification */
-
-/*
- * Turn A into a string literal without expanding macro definitions
- * (however, if invoked from a macro, macro arguments are expanded).
- */
-#define STRINGIZE_NX(A) #A
-
-/*
- * Turn A into a string literal after macro-expanding it.
- */
-#define STRINGIZE(A) STRINGIZE_NX(A)
diff --git a/ctrl/libhicnctrl/src/util/types.h b/ctrl/libhicnctrl/src/util/types.h
deleted file mode 100644
index 10a0bdca0..000000000
--- a/ctrl/libhicnctrl/src/util/types.h
+++ /dev/null
@@ -1,36 +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.
- */
-
-#ifndef UTIL_TYPES
-#define UTIL_TYPES
-
-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 unsigned int hash_t;
-
-typedef int (*cmp_t)(const void *, const void *);
-
-/* Enums */
-
-#define IS_VALID_ENUM_TYPE(NAME, x) ((x > NAME ## _UNDEFINED) && (x < NAME ## _N))
-
-#endif /* UTIL_TYPES */
diff --git a/ctrl/sysrepo-plugins/README.md b/ctrl/sysrepo-plugins/README.md
index 3f0ed2e34..0940fff67 100644
--- a/ctrl/sysrepo-plugins/README.md
+++ b/ctrl/sysrepo-plugins/README.md
@@ -1,6 +1,8 @@
# Sysrepo plugin for hicn-plugin (2019)
-These plugins serve as a data management agent. They provide yang models via NETCONF to allow the management of hicn-light, and hicn-plugin which runs in VPP instance from out-of-box.
+These plugins serve as a data management agent. They provide yang models via
+NETCONF to allow the management of hicn-light, and hicn-plugin which runs in VPP
+instance from out-of-box.
## Software Requirement
@@ -15,7 +17,7 @@ These plugins serve as a data management agent. They provide yang models via NET
## hICN yang model
You can install the yang model using the following bash script:
-
+```
EXIT_CODE=0
command -v sysrepoctl > /dev/null
if [ $? != 0 ]; then
@@ -24,53 +26,21 @@ if [ $? != 0 ]; then
else
sysrepoctl --install --yang=path_to_hicn_yang_model
fi
-
-hicn.yang can be found in the yang-model. It consists of two container nodes: hicn-conf and hicn-state. One is used to hold the configuration data (i.e., hicn-conf) and one for providing the state data (i.e., hicn-state). The hicn-conf has one node, params, which contains the hICN configuration parameters. Controler can configure these parameters through the edit-config RPC call. This node can be used to enable and to initialize the hicn-plugin in VPP instance. Hicn-state container is used to provide the state data to the controler. It consists of state, strategy, strategies, route, and face-ip-params nodes with the coresponding leaves. In hicn model variety of RPCs are provided to allow controler to communicate with hicn-plugin as well as update the state data in hicn-state. Here you can find the schematic view of the described hicn model:
-
-
-module: hicn
- +--rw hicn-conf
- | +--rw params
- | +--rw enable_disable? boolean
- | +--rw pit_max_size? int32
- | +--rw cs_max_size? int32
- | +--rw cs_reserved_app? int32
- | +--rw pit_dflt_lifetime_sec? float
- | +--rw pit_max_lifetime_sec? float
- | +--rw pit_min_lifetime_sec? float
- +--ro hicn-state
- +--ro states
- | +--ro pkts_processed? uint64
- | +--ro pkts_interest_count? uint64
- | +--ro pkts_data_count? uint64
- | +--ro pkts_from_cache_count? uint64
- | +--ro pkts_no_pit_count? uint64
- | +--ro pit_expired_count? uint64
- | +--ro cs_expired_count? uint64
- | +--ro cs_lru_count? uint64
- | +--ro pkts_drop_no_buf? uint64
- | +--ro interests_aggregated? uint64
- | +--ro interests_retx? uint64
- | +--ro interests_hash_collision? uint64
- | +--ro pit_entries_count? uint64
- | +--ro cs_entries_count? uint64
- | +--ro cs_entries_ntw_count? uint64
- +--ro strategy
- | +--ro description? uint8
- +--ro route
- | +--ro faceids? uint16
- | +--ro strategy_id? uint32
- +--ro strategies
- | +--ro n_strategies? uint8
- | +--ro strategy_id? uint32
- +--ro face-ip-params
- +--ro nh_addr? uint64
- +--ro swif? uint32
- +--ro flags? uint32
-
+```
+hicn.yang can be found in the yang-model. It consists of two container nodes:
+hicn-conf and hicn-state. One is used to hold the configuration data (i.e.,
+hicn-conf) and one for providing the state data (i.e., hicn-state). The
+hicn-conf has one node, params, which contains the hICN configuration
+parameters. A controller can configure these parameters through the edit-config RPC
+call. This node can be used to enable and to initialize the hicn-plugin in VPP
+instance. Hicn-state container is used to provide the state data to the
+controller. It consists of state, strategy, strategies, route, and face-ip-params
+nodes with the corresponding leaves. In the hicn model a variety of RPCs are provided
+to allow controller to communicate with the hicn-plugin as well as update the state
+data in hicn-state.
To setup the startup configuration you can use the following script:
-
+```
EXIT_CODE=0
command -v sysrepocfg > /dev/null
if [ $? != 0 ]; then
@@ -79,10 +49,10 @@ if [ $? != 0 ]; then
else
sysrepocfg -d startup -i path_to_startup_xml -f xml hicn
fi
-
+```
startup.xml is placed in the yang-model. Here you can find the content:
-
+```
<hicn-conf xmlns="urn:sysrepo:hicn">
<params>
<enable_disable>false</enable_disable>
@@ -94,81 +64,17 @@ startup.xml is placed in the yang-model. Here you can find the content:
<pit_min_lifetime_sec>-1</pit_min_lifetime_sec>
</params>
</hicn-conf>
-
-As can be seen, it contains the leaves of the params in hicn-conf node which is used as the startup configuration. This configuration can be changed through the controler by subscribing which changes the target to the running state. hicn yang model provides a list of RPCs which allows controler to communicate directly with the hicn-plugin. This RPCs may also cause the modification in state data. Here you can find the list of RPCs:
-
- rpcs:
- +---x node-params-set
- | +---w input
- | +---w enable_disable? boolean
- | +---w pit_max_size? int32
- | +---w cs_max_size? int32
- | +---w cs_reserved_app? int32
- | +---w pit_dflt_lifetime_sec? float
- | +---w pit_max_lifetime_sec? float
- | +---w pit_min_lifetime_sec? float
- +---x node-params-get
- +---x node-stat-get
- +---x strategy-get
- | +---w input
- | +---w strategy_id? uint32
- +---x strategies-get
- +---x route-get
- | +---w input
- | +---w prefix0? uint64
- | +---w prefix1? uint64
- | +---w len? uint8
- +---x route-del
- | +---w input
- | +---w prefix0? uint64
- | +---w prefix1? uint64
- | +---w len? uint8
- +---x route-nhops-add
- | +---w input
- | +---w prefix0? uint64
- | +---w prefix1? uint64
- | +---w len? uint8
- | +---w face_ids0? uint32
- | +---w face_ids1? uint32
- | +---w face_ids2? uint32
- | +---w face_ids3? uint32
- | +---w face_ids4? uint32
- | +---w face_ids5? uint32
- | +---w face_ids6? uint32
- | +---w n_faces? uint8
- +---x route-nhops-del
- | +---w input
- | +---w prefix0? uint64
- | +---w prefix1? uint64
- | +---w len? uint8
- | +---w faceid? uint16
- +---x face-ip-params-get
- | +---w input
- | +---w faceid? uint16
- +---x face-ip-add
- | +---w input
- | +---w nh_addr0? uint64
- | +---w nh_addr1? uint64
- | +---w swif? uint32
- +---x face-ip-del
- | +---w input
- | +---w faceid? uint16
- +---x punting-add
- | +---w input
- | +---w prefix0? uint64
- | +---w prefix1? uint64
- | +---w len? uint8
- | +---w swif? uint32
- +---x punting-del
- +---w input
- +---w prefix0? uint64
- +---w prefix1? uint64
- +---w len? uint8
- +---w swif? uint32
-
-
-In order to run different RPCs from controler you can use the examples in the controler_rpcs_instances.xml in the yang-model. Here you can find the content:
-
+```
+As can be seen, it contains the leaves of the params in hicn-conf node which is
+used as the startup configuration. This configuration can be changed through the
+controller by subscribing which changes the target to the running state. hicn
+yang model provides a list of RPCs which allows controller to communicate
+directly with the hicn-plugin. This RPCs may also cause the modification in
+state data.
+
+In order to run different RPCs from controller you can use the examples in the
+controler_rpcs_instances.xml in the yang-model. Here you can find the content:
+```
<node-params-get xmlns="urn:sysrepo:hicn"/>
<node-stat-get xmlns="urn:sysrepo:hicn"/>
@@ -179,7 +85,6 @@ In order to run different RPCs from controler you can use the examples in the co
<strategies-get xmlns="urn:sysrepo:hicn"/>
-
<route-get xmlns="urn:sysrepo:hicn">
<prefix0>10</prefix0>
<prefix1>20</prefix1>
@@ -213,7 +118,6 @@ In order to run different RPCs from controler you can use the examples in the co
<faceid>40</faceid>
</route-nhops-del>
-
<face-ip-params-get xmlns="urn:sysrepo:hicn">
<faceid>10</faceid>
</face-ip-params-get>
@@ -235,27 +139,33 @@ In order to run different RPCs from controler you can use the examples in the co
<swif>40</swif>
</punting-add>
-
<punting-del xmlns="urn:sysrepo:hicn">
<prefix0>10</prefix0>
<prefix1>20</prefix1>
<len>30</len>
<swif>40</swif>
</punting-del>
-
+```
## Run the plugin
-Firstly, verify the plugin and binary libraries are located correctly, then run the vpp through (service vpp start). Next, run the sysrepo daemon (sysrepod), for debug mode: sysrepo -d -l 4 which runs with high verbosity. Then, run the sysrepo plugin (sysrepo-plugind), for debug mode: sysrep-plugind -d -l 4 which runs with high verbosity. Now, the hicn sysrepo plugin is loaded. Then, run the netopeer2-server which serves as NETCONF server.
+Firstly, verify the plugin and binary libraries are located correctly, then run
+the vpp through (service vpp start). Next, run the sysrepo daemon (sysrepod),
+for debug mode: sysrepo -d -l 4 which runs with high verbosity. Then, run the
+sysrepo plugin (sysrepo-plugind), for debug mode: sysrep-plugind -d -l 4 which
+runs with high verbosity. Now, the hicn sysrepo plugin is loaded. Then, run the
+netopeer2-server which serves as NETCONF server.
## Connect from netopeer2-cli
In order to connect through the netopeer client run the netopeer2-cli. Then, follow these steps:
-connect --host XXX --login XXX
---> get (you can get the configuration and operational data)
---> get-config (you can get the configuratoin data)
---> edit-config --target running --config (you can modify the configuration but it needs an xml configuration input. For example,
+- connect --host XXX --login XXX
+- get (you can get the configuration and operational data)
+- get-config (you can get the configuration data)
+- edit-config --target running --config
+ you can modify the configuration but it needs an xml configuration input
+```
<hicn-conf xmlns="urn:sysrepo:hicn">
<params>
<enable_disable>false</enable_disable>
@@ -267,15 +177,16 @@ connect --host XXX --login XXX
<pit_min_lifetime_sec>-1</pit_min_lifetime_sec>
</params>
</hicn-conf>
-)
---> user-rpc (you can call one of the rpc proposed by hicn model but it needs an xml input, you can pick one in controler_rpcs_instances.xml)
+```
+- user-rpc (you can call one of the rpc proposed by hicn model but it needs an xml input)
-## Connect from OpenDayligh (ODL) controller
+## Connect from OpenDaylight (ODL) controller
-In order to connect througt the OpenDaylight follow these procedure:
+In order to connect through the OpenDaylight follow these procedure:
- run karaf distribution (./opendayligh_installation_folder/bin/karaf)
-- install the required feature list in DOL (feature:install odl-netconf-server odl-netconf-connector odl-restconf-all odl-netconf-topology or
+- install the required feature list in DOL (feature:install odl-netconf-server
+ odl-netconf-connector odl-restconf-all odl-netconf-topology or
odl-netconf-clustered-topology)
- run a rest client program (e.g., postman or RESTClient)
- mount the remote netopeer2-server to the OpenDaylight by the following REST API:
@@ -283,7 +194,7 @@ In order to connect througt the OpenDaylight follow these procedure:
PUT http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/hicn-node
with the following body
-
+```
<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">
<node-id>hicn-node</node-id>
<host xmlns="urn:opendaylight:netconf-node-topology">Remote_NETCONF_SERVER_IP</host>
@@ -293,8 +204,8 @@ with the following body
<tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>
<keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">1</keepalive-delay>
</node>
-
-Note that the header files must be set to Content-Type: application/xml, Accept: application/xml. There are more options which can be set but for simplicity we keep a short configuration to mount the remote node.
+```
+Note that the header files must be set to Content-Type: application/xml, Accept: application/xml.
- send the operation through the following REST API:
@@ -304,7 +215,9 @@ The body can be used the same as edit-config in netopeer2-cli.
## Connect from Network Services Orchestrator (NSO)
-To connect NSO to the netopeer2-server, first, you need to write a NED package for your device. The procudeure to create NED for hicn is explaned in the following:
+To connect NSO to the netopeer2-server, first, you need to write a NED package
+for your device. The procedure to create NED for hicn is explained in the
+following:
Place hicn.yang model in a folder called hicn-yang-model, and follow these steps:
@@ -323,7 +236,6 @@ Place hicn.yang model in a folder called hicn-yang-model, and follow these steps
At this point, we are able to connect to the remote device.
-
## Release note
-The current version is compatible with the 19.01 VPP stable and sysrepo 0.7.7.
+The current version is compatible with the 19.01 VPP stable and sysrepo 0.7.7. \ No newline at end of file
diff --git a/hicn-light/CMakeLists.txt b/hicn-light/CMakeLists.txt
index 39fce8c1f..1e5805d68 100644
--- a/hicn-light/CMakeLists.txt
+++ b/hicn-light/CMakeLists.txt
@@ -39,8 +39,9 @@ if(NOT WIN32)
else ()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996")
endif ()
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
-if(ANDROID_API)
+if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
message("############ Detected cross compile for $ENV{CMAKE_SYSTEM_NAME}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ANDROID_C_FLAGS}")
endif()
@@ -58,7 +59,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
set(HICN_LIGHT_CONTROL ${HICN_LIGHT}-control)
set(HICN_LIGHT_DAEMON ${HICN_LIGHT}-daemon)
else()
- if (ANDROID_API)
+ if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
set(HICN_LIBRARIES ${LIBHICN_STATIC})
list(APPEND DEPENDENCIES
${LIBHICN_STATIC}
diff --git a/hicn-light/src/hicn/CMakeLists.txt b/hicn-light/src/hicn/CMakeLists.txt
index 9129cba17..64b0ff2a0 100644
--- a/hicn-light/src/hicn/CMakeLists.txt
+++ b/hicn-light/src/hicn/CMakeLists.txt
@@ -14,8 +14,7 @@ list(APPEND COMPILER_DEFINITIONS
"-DWITH_POLICY"
)
-
-if(NOT ANDROID_API AND NOT COMPILE_FOR_IOS)
+if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Android" AND NOT COMPILE_FOR_IOS)
add_subdirectory(command_line)
endif ()
@@ -43,7 +42,7 @@ list(APPEND TO_INSTALL_HEADER_FILES
${CMAKE_CURRENT_BINARY_DIR}/hicn-light/config.h
)
-if (ANDROID_API)
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
build_library(${LIBHICN_LIGHT}
STATIC
SOURCES ${SOURCE_FILES}
diff --git a/hicn-light/src/hicn/config/configuration.c b/hicn-light/src/hicn/config/configuration.c
index 182c2fdc1..b14ea551a 100644
--- a/hicn-light/src/hicn/config/configuration.c
+++ b/hicn-light/src/hicn/config/configuration.c
@@ -363,30 +363,32 @@ struct iovec *configuration_ProcessCreateTunnel(Configuration *config,
Address *source = NULL;
Address *destination = NULL;
- if (!symbolicNameTable_Exists(config->symbolicNameTable, symbolicName)) {
- if (control->ipType == ADDR_INET) {
- source =
- addressFromInaddr4Port(&control->localIp.ipv4, &control->localPort);
- destination =
- addressFromInaddr4Port(&control->remoteIp.ipv4, &control->remotePort);
- } else if (control->ipType == ADDR_INET6) {
- source =
- addressFromInaddr6Port(&control->localIp.ipv6, &control->localPort);
- destination =
- addressFromInaddr6Port(&control->remoteIp.ipv6, &control->remotePort);
- } else {
- printf("Invalid IP type.\n"); // will generate a Nack
- }
-
- AddressPair *pair = addressPair_Create(source, destination);
- conn = (Connection *)connectionTable_FindByAddressPair(
- forwarder_GetConnectionTable(config->forwarder), pair);
+ if (symbolicNameTable_Exists(config->symbolicNameTable, symbolicName)) {
+ logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
+ __func__, "Listener symbolic name already exists");
+ goto ERR;
+ }
- addressPair_Release(&pair);
+ if (control->ipType == ADDR_INET) {
+ source =
+ addressFromInaddr4Port(&control->localIp.ipv4, &control->localPort);
+ destination =
+ addressFromInaddr4Port(&control->remoteIp.ipv4, &control->remotePort);
+ } else if (control->ipType == ADDR_INET6) {
+ source =
+ addressFromInaddr6Port(&control->localIp.ipv6, &control->localPort);
+ destination =
+ addressFromInaddr6Port(&control->remoteIp.ipv6, &control->remotePort);
} else {
- conn = NULL;
+ printf("Invalid IP type.\n"); // will generate a Nack
}
+ AddressPair *pair = addressPair_Create(source, destination);
+ conn = (Connection *)connectionTable_FindByAddressPair(
+ forwarder_GetConnectionTable(config->forwarder), pair);
+
+ addressPair_Release(&pair);
+
if (!conn) {
IoOperations *ops = NULL;
switch (control->connectionType) {
@@ -460,11 +462,14 @@ struct iovec *configuration_ProcessCreateTunnel(Configuration *config,
if (destination)
addressDestroy(&destination);
- if (success) { // ACK
- return utils_CreateAck(header, control, sizeof(add_connection_command));
- } else { // NACK
+ if (!success)
+ goto ERR;
+
+ // ACK
+ return utils_CreateAck(header, control, sizeof(add_connection_command));
+
+ERR:
return utils_CreateNack(header, control, sizeof(add_connection_command));
- }
}
/**
@@ -577,6 +582,13 @@ struct iovec *configuration_ProcessRemoveTunnel(Configuration *config,
return response;
}
+void _strlwr(char *string) {
+ char *p = string;
+ while ((*p = tolower(*p))) {
+ p++;
+ }
+}
+
struct iovec *configuration_ProcessConnectionList(Configuration *config,
struct iovec *request) {
ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder);
@@ -603,8 +615,17 @@ struct iovec *configuration_ProcessConnectionList(Configuration *config,
// set structure fields
listConnectionsCommand->connid = connection_GetConnectionId(original);
+
+ const char *connectionName = symbolicNameTable_GetNameByIndex(config->symbolicNameTable, connection_GetConnectionId(original));
+ snprintf(listConnectionsCommand->connectionName, 16, "%s", connectionName);
+ _strlwr(listConnectionsCommand->connectionName);
+
+ snprintf(listConnectionsCommand->interfaceName, 16, "%s", ioOperations_GetInterfaceName(connection_GetIoOperations(original)));
+
listConnectionsCommand->state =
connection_IsUp(original) ? IFACE_UP : IFACE_DOWN;
+ listConnectionsCommand->admin_state =
+ (connection_GetAdminState(original) == CONNECTION_STATE_UP) ? IFACE_UP : IFACE_DOWN;
listConnectionsCommand->connectionData.connectionType =
ioOperations_GetConnectionType(connection_GetIoOperations(original));
@@ -707,6 +728,14 @@ struct iovec *configuration_ProcessListenersList(Configuration *config,
listListenersCommand->address.ipv6 = tmpAddr6.sin6_addr;
listListenersCommand->port = tmpAddr6.sin6_port;
}
+
+ const char * listenerName = listenerEntry->getListenerName(listenerEntry);
+ snprintf(listListenersCommand->listenerName, 16, "%s", listenerName);
+ if (listenerEntry->getEncapType(listenerEntry) == ENCAP_TCP ||
+ listenerEntry->getEncapType(listenerEntry) == ENCAP_UDP) {
+ const char * interfaceName = listenerEntry->getInterfaceName(listenerEntry);
+ snprintf(listListenersCommand->interfaceName, 16, "%s", interfaceName);
+ }
}
// send response
diff --git a/hicn-light/src/hicn/config/configurationListeners.c b/hicn-light/src/hicn/config/configurationListeners.c
index 97e7dbb87..86d8a215a 100644
--- a/hicn-light/src/hicn/config/configurationListeners.c
+++ b/hicn-light/src/hicn/config/configurationListeners.c
@@ -211,32 +211,21 @@ static bool _addEther(Configuration *config, add_listener_command *control,
return false;
}
-#ifdef __linux__
/*
* Create a new IPV4/TCP listener.
*
* @param [in,out] forwarder The hicn-light forwarder instance
+ * @param [in] listenerName The name of the listener
* @param [in] addr4 The ipv4 address in network byte order
* @param [in] port The port number in network byte order
* @param [in] interfaceName The name of the interface to bind the socket
*
* return true if success, false otherwise
*/
-static bool _setupTcpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4,
- uint16_t *port, const char *interfaceName) {
-#else
-/*
- * Create a new IPV4/TCP listener.
- *
- * @param [in,out] forwarder The hicn-light forwarder instance
- * @param [in] addr4 The ipv4 address in network byte order
- * @param [in] port The port number in network byte order
- *
- * return true if success, false otherwise
- */
-static bool _setupTcpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4,
- uint16_t *port) {
-#endif
+static bool _setupTcpListenerOnInet(Forwarder *forwarder, char *listenerName, ipv4_addr_t *addr4,
+ uint16_t *port, char *interfaceName) {
+ parcAssertNotNull(listenerName, "Parameter listenerName must be non-null");
+
bool success = false;
struct sockaddr_in addr;
@@ -245,42 +234,31 @@ static bool _setupTcpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4,
addr.sin_port = *port;
addr.sin_addr.s_addr = *addr4;
- ListenerOps *ops = tcpListener_CreateInet(forwarder, addr);
+ ListenerOps *ops = tcpListener_CreateInet(forwarder, listenerName, addr, interfaceName);
if (ops) {
success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
+#if 0
parcAssertTrue(success, "Failed to add TCP listener on %s to ListenerSet",
addressToString(ops->getListenAddress(ops)));
+#endif
}
return success;
}
-#ifdef __linux__
/*
* Create a new IPV4/UDP listener.
*
* @param [in,out] forwarder The hicn-light forwarder instance
+ * @param [in] listenerName The name of the listener
* @param [in] addr4 The ipv4 address in network byte order
* @param [in] port The port number in network byte order
* @param [in] interfaceName The name of the interface to bind the socket
*
* return true if success, false otherwise
*/
-static bool _setupUdpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4,
+static bool _setupUdpListenerOnInet(Forwarder *forwarder, char *listenerName, ipv4_addr_t *addr4,
uint16_t *port, char *interfaceName) {
-#else
-/*
- * Create a new IPV4/UDP listener.
- *
- * @param [in,out] forwarder The hicn-light forwarder instance
- * @param [in] addr4 The ipv4 address in network byte order
- * @param [in] port The port number in network byte order
- *
- * return true if success, false otherwise
- */
-static bool _setupUdpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4,
- uint16_t *port) {
-#endif
bool success = false;
struct sockaddr_in addr;
@@ -289,21 +267,18 @@ static bool _setupUdpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4,
addr.sin_port = *port;
addr.sin_addr.s_addr = *addr4;
-#ifdef __linux__
- ListenerOps *ops = udpListener_CreateInet(forwarder, addr, interfaceName);
-#else
- ListenerOps *ops = udpListener_CreateInet(forwarder, addr);
-#endif
+ ListenerOps *ops = udpListener_CreateInet(forwarder, listenerName, addr, interfaceName);
if (ops) {
success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
+#if 0
parcAssertTrue(success, "Failed to add UDP listener on %s to ListenerSet",
addressToString(ops->getListenAddress(ops)));
+#endif
}
return success;
}
-#ifdef __linux__
/*
* Create a new IPV6/TCP listener.
*
@@ -314,23 +289,9 @@ static bool _setupUdpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4,
*
* return true if success, false otherwise
*/
-static bool _setupTcpListenerOnInet6Light(Forwarder *forwarder,
+static bool _setupTcpListenerOnInet6Light(Forwarder *forwarder, char *listenerName,
ipv6_addr_t *addr6, uint16_t *port, char *interfaceName,
uint32_t scopeId) {
-#else
-/*
- * Create a new IPV6/TCP listener.
- *
- * @param [in,out] forwarder The hicn-light forwarder instance
- * @param [in] addr6 The ipv6 address in network byte order
- * @param [in] port The port number in network byte order
- *
- * return true if success, false otherwise
- */
-static bool _setupTcpListenerOnInet6Light(Forwarder *forwarder,
- ipv6_addr_t *addr6, uint16_t *port,
- uint32_t scopeId) {
-#endif
bool success = false;
struct sockaddr_in6 addr;
@@ -340,17 +301,18 @@ static bool _setupTcpListenerOnInet6Light(Forwarder *forwarder,
addr.sin6_addr = *addr6;
addr.sin6_scope_id = scopeId;
- ListenerOps *ops = tcpListener_CreateInet6(forwarder, addr);
+ ListenerOps *ops = tcpListener_CreateInet6(forwarder, listenerName, addr, interfaceName);
if (ops) {
success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
+#if 0
parcAssertTrue(success, "Failed to add TCP6 listener on %s to ListenerSet",
addressToString(ops->getListenAddress(ops)));
+#endif
}
return success;
}
-#ifdef __linux__
/*
* Create a new IPV6/UDP listener.
*
@@ -361,21 +323,8 @@ static bool _setupTcpListenerOnInet6Light(Forwarder *forwarder,
*
* return true if success, false otherwise
*/
-static bool _setupUdpListenerOnInet6Light(Forwarder *forwarder,
+static bool _setupUdpListenerOnInet6Light(Forwarder *forwarder, char *listenerName,
ipv6_addr_t *addr6, uint16_t *port, char *interfaceName) {
-#else
-/*
- * Create a new IPV6/UDP listener.
- *
- * @param [in,out] forwarder The hicn-light forwarder instance
- * @param [in] addr6 The ipv6 address in network byte order
- * @param [in] port The port number in network byte order
- *
- * return true if success, false otherwise
- */
-static bool _setupUdpListenerOnInet6Light(Forwarder *forwarder,
- ipv6_addr_t *addr6, uint16_t *port) {
-#endif
bool success = false;
struct sockaddr_in6 addr;
@@ -385,15 +334,13 @@ static bool _setupUdpListenerOnInet6Light(Forwarder *forwarder,
addr.sin6_addr = *addr6;
addr.sin6_scope_id = 0;
-#ifdef __linux__
- ListenerOps *ops = udpListener_CreateInet6(forwarder, addr, interfaceName);
-#else
- ListenerOps *ops = udpListener_CreateInet6(forwarder, addr);
-#endif
+ ListenerOps *ops = udpListener_CreateInet6(forwarder, listenerName, addr, interfaceName);
if (ops) {
success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
+#if 0
parcAssertTrue(success, "Failed to add UDP6 listener on %s to ListenerSet",
addressToString(ops->getListenAddress(ops)));
+#endif
}
return success;
}
@@ -460,56 +407,33 @@ bool _addHicn(Configuration *config, add_listener_command *control,
bool _addIP(Configuration *config, add_listener_command *control,
unsigned ingressId) {
bool success = false;
+ char *symbolic = control->symbolic;
switch (control->addressType) {
case ADDR_INET: {
-#ifdef __linux__
if (control->connectionType == UDP_CONN) {
success =
- _setupUdpListenerOnInet(configuration_GetForwarder(config),
+ _setupUdpListenerOnInet(configuration_GetForwarder(config), symbolic,
&control->address.ipv4, &control->port, control->interfaceName);
} else if (control->connectionType == TCP_CONN) {
success =
- _setupTcpListenerOnInet(configuration_GetForwarder(config),
+ _setupTcpListenerOnInet(configuration_GetForwarder(config), symbolic,
&control->address.ipv4, &control->port, control->interfaceName);
}
-#else
- if (control->connectionType == UDP_CONN) {
- success =
- _setupUdpListenerOnInet(configuration_GetForwarder(config),
- &control->address.ipv4, &control->port);
- } else if (control->connectionType == TCP_CONN) {
- success =
- _setupTcpListenerOnInet(configuration_GetForwarder(config),
- &control->address.ipv4, &control->port);
- }
-#endif
break;
}
case ADDR_INET6: {
-#ifdef __linux__
if (control->connectionType == UDP_CONN) {
success = _setupUdpListenerOnInet6Light(
- configuration_GetForwarder(config), &control->address.ipv6,
+ configuration_GetForwarder(config), symbolic, &control->address.ipv6,
&control->port, control->interfaceName);
} else if (control->connectionType == TCP_CONN) {
success = _setupTcpListenerOnInet6Light(
- configuration_GetForwarder(config), &control->address.ipv6,
+ configuration_GetForwarder(config), symbolic, &control->address.ipv6,
&control->port, control->interfaceName, 0);
}
-#else
- if (control->connectionType == UDP_CONN) {
- success = _setupUdpListenerOnInet6Light(
- configuration_GetForwarder(config), &control->address.ipv6,
- &control->port);
- } else if (control->connectionType == TCP_CONN) {
- success = _setupTcpListenerOnInet6Light(
- configuration_GetForwarder(config), &control->address.ipv6,
- &control->port, 0);
- }
-#endif
break;
}
@@ -551,20 +475,25 @@ struct iovec *configurationListeners_Add(Configuration *config,
bool success = false;
- if (control->listenerMode == ETHER_MODE) {
- parcTrapNotImplemented("Add Ethernet Listener is not supported");
- success = _addEther(config, control, ingressId);
- // it is a failure
- } else if (control->listenerMode == IP_MODE) {
- success = _addIP(config, control, ingressId);
- } else if (control->listenerMode == HICN_MODE) {
- success = _addHicn(config, control, ingressId);
- } else {
- Logger *logger = configuration_GetLogger(config);
- if (logger_IsLoggable(logger, LoggerFacility_Config,
- PARCLogLevel_Warning)) {
- logger_Log(logger, LoggerFacility_Config, PARCLogLevel_Warning, __func__,
- "Unsupported encapsulation mode (ingress id %u)", ingressId);
+ ListenerSet *listenerSet = forwarder_GetListenerSet(configuration_GetForwarder(config));
+ int listenerId = listenerSet_FindIdByListenerName(listenerSet, control->symbolic);
+
+ if (listenerId < 0) {
+ if (control->listenerMode == ETHER_MODE) {
+ parcTrapNotImplemented("Add Ethernet Listener is not supported");
+ success = _addEther(config, control, ingressId);
+ // it is a failure
+ } else if (control->listenerMode == IP_MODE) {
+ success = _addIP(config, control, ingressId);
+ } else if (control->listenerMode == HICN_MODE) {
+ success = _addHicn(config, control, ingressId);
+ } else {
+ Logger *logger = configuration_GetLogger(config);
+ if (logger_IsLoggable(logger, LoggerFacility_Config,
+ PARCLogLevel_Warning)) {
+ logger_Log(logger, LoggerFacility_Config, PARCLogLevel_Warning, __func__,
+ "Unsupported encapsulation mode (ingress id %u)", ingressId);
+ }
}
}
@@ -619,7 +548,7 @@ struct iovec *configurationListeners_AddPunting(Configuration *config,
//=========================== INITIAL LISTENERS ====================
-static void _setupListenersOnAddress(Forwarder *forwarder,
+static void _setupListenersOnAddress(Forwarder *forwarder, char *listenerName,
const Address *address, uint16_t port,
char *interfaceName) {
address_type type = addressGetType(address);
@@ -627,24 +556,15 @@ static void _setupListenersOnAddress(Forwarder *forwarder,
case ADDR_INET: {
struct sockaddr_in tmp;
addressGetInet(address, &tmp);
-#ifdef __linux__
- _setupTcpListenerOnInet(forwarder, &tmp.sin_addr.s_addr, &port, interfaceName);
-#else
- _setupTcpListenerOnInet(forwarder, &tmp.sin_addr.s_addr, &port);
-#endif
+ _setupTcpListenerOnInet(forwarder, listenerName, &tmp.sin_addr.s_addr, &port, interfaceName);
break;
}
case ADDR_INET6: {
struct sockaddr_in6 tmp;
addressGetInet6(address, &tmp);
-#ifdef __linux__
- _setupTcpListenerOnInet6Light(forwarder, &tmp.sin6_addr, &port, interfaceName,
- tmp.sin6_scope_id);
-#else
- _setupTcpListenerOnInet6Light(forwarder, &tmp.sin6_addr, &port,
+ _setupTcpListenerOnInet6Light(forwarder, listenerName, &tmp.sin6_addr, &port, interfaceName,
tmp.sin6_scope_id);
-#endif
break;
}
@@ -674,8 +594,14 @@ void configurationListeners_SetupAll(const Configuration *config, uint16_t port,
const Address *address = addressListGetItem(addresses, j);
// Do not start on link address
+ char listenerName[16];
+#ifdef __ANDROID__
+ snprintf(listenerName, 16, "local_%zu", i);
+#else
+ snprintf(listenerName, 16, "local_%ld", i);
+#endif
if (addressGetType(address) != ADDR_LINK) {
- _setupListenersOnAddress(forwarder, address, port,
+ _setupListenersOnAddress(forwarder, listenerName, address, port,
(char *)interfaceGetName(iface));
}
}
@@ -689,16 +615,11 @@ void configurationListeners_SetutpLocalIPv4(const Configuration *config,
Forwarder *forwarder = configuration_GetForwarder(config);
in_addr_t addr = inet_addr("127.0.0.1");
uint16_t network_byte_order_port = htons(port);
-#ifdef __linux__
+ char listenerNameUdp[16] = "lo_udp";
+ char listenerNameTcp[16] = "lo_tcp";
char *loopback_interface = "lo";
- _setupUdpListenerOnInet(forwarder, (ipv4_addr_t *)&(addr),
+ _setupUdpListenerOnInet(forwarder, listenerNameUdp,(ipv4_addr_t *)&(addr),
&network_byte_order_port, loopback_interface);
- _setupTcpListenerOnInet(forwarder, (ipv4_addr_t *)&(addr),
+ _setupTcpListenerOnInet(forwarder, listenerNameTcp, (ipv4_addr_t *)&(addr),
&network_byte_order_port, loopback_interface);
-#else
- _setupUdpListenerOnInet(forwarder, (ipv4_addr_t *)&(addr),
- &network_byte_order_port);
- _setupTcpListenerOnInet(forwarder, (ipv4_addr_t *)&(addr),
- &network_byte_order_port);
-#endif
}
diff --git a/hicn-light/src/hicn/config/controlListConnections.c b/hicn-light/src/hicn/config/controlListConnections.c
index 0eb6392ea..dbd9707ca 100644
--- a/hicn-light/src/hicn/config/controlListConnections.c
+++ b/hicn-light/src/hicn/config/controlListConnections.c
@@ -83,7 +83,7 @@ static CommandReturn _controlListConnections_Execute(CommandParser *parser,
return CommandReturn_Failure;
}
#ifdef WITH_POLICY
- char flags_str[POLICY_TAG_N];
+ char flags_str[POLICY_TAG_N+1];
char *s;
#endif /* WITH_POLICY */
@@ -113,6 +113,12 @@ static CommandReturn _controlListConnections_Execute(CommandParser *parser,
}
}
+#ifdef WITH_POLICY
+ printf("%5s %10s %12s %6s %40s %40s %5s %s\n", "id", "name", "admin_state", "state", "source", "destination", "type", "flags");
+#else
+ printf("%5s %10s %12s %6s %40s %40s %5s\n", "id", "name", "admin_state", "state", "source", "destination", "type");
+#endif /* WITH_POLICY */
+
// Process/Print payload
for (int i = 0; i < receivedHeader->length; i++) {
list_connections_command *listConnectionsCommand =
@@ -140,7 +146,8 @@ foreach_policy_tag
*s = '\0';
parcBufferComposer_Format(
- composer, "%5d %4s %s %s %s [%s]", listConnectionsCommand->connid,
+ composer, "%5d %10s %12s %6s %40s %40s %5s [%s]", listConnectionsCommand->connid, listConnectionsCommand->connectionName,
+ stateString[listConnectionsCommand->admin_state],
stateString[listConnectionsCommand->state], sourceString,
destinationString,
connTypeString[listConnectionsCommand->connectionData.connectionType],
@@ -148,7 +155,8 @@ foreach_policy_tag
#else
parcBufferComposer_Format(
- composer, "%5d %4s %s %s %s", listConnectionsCommand->connid,
+ composer, "%5d %10s %12s %6s %40s %40s %5s", listConnectionsCommand->connid, listConnectionsCommand->connectionName,
+ stateString[listConnectionsCommand->admin_state],
stateString[listConnectionsCommand->state], sourceString,
destinationString,
connTypeString[listConnectionsCommand->connectionData.connectionType]);
diff --git a/hicn-light/src/hicn/config/controlListListeners.c b/hicn-light/src/hicn/config/controlListListeners.c
index 1f4ad7f2c..5be7b0a9b 100644
--- a/hicn-light/src/hicn/config/controlListListeners.c
+++ b/hicn-light/src/hicn/config/controlListListeners.c
@@ -95,7 +95,8 @@ static CommandReturn _controlListListeners_Execute(CommandParser *parser,
char *addrString = NULL;
if (receivedHeader->length > 0) {
- printf("%6.6s %50.70s %s\n", "iface", "address", "type");
+ printf("%6.6s %16s %50.70s %6s %10s\n", "iface", "name", "address", "type", "interface");
+
} else {
printf(" --- No entry in the list \n");
}
@@ -111,16 +112,26 @@ static CommandReturn _controlListListeners_Execute(CommandParser *parser,
PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_Format(composer, "%6u %50.70s %3s",
- listListenersCommand->connid, addrString,
- listenerType[listListenersCommand->encapType]);
+ if (strcmp(listenerType[listListenersCommand->encapType], "UDP") == 0 ||
+ strcmp(listenerType[listListenersCommand->encapType], "TCP") == 0) {
+ parcBufferComposer_Format(composer, "%6u %16s %50.70s %6s %10s",
+ listListenersCommand->connid,
+ listListenersCommand->listenerName,addrString,
+ listenerType[listListenersCommand->encapType],
+ listListenersCommand->interfaceName);
+ } else {
+ parcBufferComposer_Format(composer, "%6u %16s %50.70s %6s",
+ listListenersCommand->connid,
+ listListenersCommand->listenerName,addrString,
+ listenerType[listListenersCommand->encapType]);
+ }
PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
char *result = parcBuffer_ToString(tempBuffer);
parcBuffer_Release(&tempBuffer);
if (!controlState_IsInteractive(state)) {
- strcpy(commandOutputMain[i], result);
+ strncpy(commandOutputMain[i], result, 128);
}
puts(result);
diff --git a/hicn-light/src/hicn/config/controlUpdateConnection.c b/hicn-light/src/hicn/config/controlUpdateConnection.c
index 3e573d41d..ff834522e 100644
--- a/hicn-light/src/hicn/config/controlUpdateConnection.c
+++ b/hicn-light/src/hicn/config/controlUpdateConnection.c
@@ -31,9 +31,9 @@
#include <hicn/config/controlUpdateConnection.h>
+#include <hicn/policy.h>
#include <hicn/utils/commands.h>
#include <hicn/utils/utils.h>
-#include <hicn/utils/policy.h>
static CommandReturn _controlUpdateConnection_Execute(CommandParser *parser,
CommandOps *ops,
diff --git a/hicn-light/src/hicn/core/connection.c b/hicn-light/src/hicn/core/connection.c
index 2f50dbf7f..821da884d 100644
--- a/hicn-light/src/hicn/core/connection.c
+++ b/hicn-light/src/hicn/core/connection.c
@@ -28,7 +28,7 @@
#include <parc/algol/parc_Memory.h>
#include <parc/assert/parc_Assert.h>
#ifdef WITH_POLICY
-#include <hicn/utils/policy.h>
+#include <hicn/policy.h>
#endif /* WITH_POLICY */
struct connection {
@@ -329,6 +329,14 @@ void connection_SetAdminState(Connection *conn, connection_state_t admin_state)
ioOperations_SetAdminState(conn->ops, admin_state);
}
+const char * connection_GetInterfaceName(const Connection * conn)
+{
+ parcAssertNotNull(conn, "Parameter conn must be non-null");
+ if (!conn->ops)
+ return NULL;
+ return ioOperations_GetInterfaceName(conn->ops);
+}
+
#ifdef WITH_POLICY
void connection_AddTag(Connection *conn, policy_tag_t tag)
diff --git a/hicn-light/src/hicn/core/connection.h b/hicn-light/src/hicn/core/connection.h
index c007a1a26..b7b5e3c91 100644
--- a/hicn-light/src/hicn/core/connection.h
+++ b/hicn-light/src/hicn/core/connection.h
@@ -41,7 +41,7 @@ typedef enum {
#endif /* WITH_MAPME */
#ifdef WITH_POLICY
-#include <hicn/utils/policy.h>
+#include <hicn/policy.h>
#endif /* WITH_POLICY */
// packet types for probing
@@ -183,6 +183,8 @@ connection_state_t connection_GetAdminState(const Connection *conn);
void connection_SetAdminState(Connection *conn, connection_state_t admin_state);
+const char * connection_GetInterfaceName(const Connection * conn);
+
#ifdef WITH_POLICY
void connection_AddTag(Connection *conn, policy_tag_t tag);
void connection_RemoveTag(Connection *conn, policy_tag_t tag);
diff --git a/hicn-light/src/hicn/core/mapMe.c b/hicn-light/src/hicn/core/mapMe.c
index 0f86dfd7e..2b621387b 100644
--- a/hicn-light/src/hicn/core/mapMe.c
+++ b/hicn-light/src/hicn/core/mapMe.c
@@ -207,11 +207,11 @@ static PARCIterator *mapMeTFIB_CreateKeyIterator(const MapMeTFIB *tfib) {
int hicn_prefix_from_name(const Name *name, hicn_prefix_t *prefix) {
NameBitvector *bv = name_GetContentName(name);
- ip_address_t ip_address;
- nameBitvector_ToIPAddress(bv, &ip_address);
+ ip_prefix_t ip_prefix;
+ nameBitvector_ToIPAddress(bv, &ip_prefix);
/* The name length will be equal to ip address' prefix length */
- return hicn_prefix_create_from_ip_address(&ip_address, prefix);
+ return hicn_prefix_create_from_ip_prefix(&ip_prefix, prefix);
}
static Message *mapMe_createMessage(const MapMe *mapme, const Name *name,
diff --git a/hicn-light/src/hicn/core/nameBitvector.c b/hicn-light/src/hicn/core/nameBitvector.c
index ad6884d02..9a734359c 100644
--- a/hicn-light/src/hicn/core/nameBitvector.c
+++ b/hicn-light/src/hicn/core/nameBitvector.c
@@ -264,11 +264,11 @@ void nameBitvector_clear(NameBitvector *a, uint8_t start_from){
}
int nameBitvector_ToIPAddress(const NameBitvector *name,
- ip_address_t *ip_address) {
+ ip_prefix_t *prefix) {
if (name->IPversion == IPv4_TYPE) {
- struct in_addr *addr = (struct in_addr *)(&ip_address->buffer);
- ip_address->family = AF_INET;
- ip_address->prefix_len = IPV4_ADDR_LEN_BITS;
+ struct in_addr *addr = (struct in_addr *)(&prefix->address.buffer);
+ prefix->family = AF_INET;
+ prefix->len = IPV4_ADDR_LEN_BITS;
uint32_t tmp_addr = name->bits[0] >> 32ULL;
uint8_t addr_1 = (tmp_addr & 0xff000000) >> 24;
@@ -283,9 +283,9 @@ int nameBitvector_ToIPAddress(const NameBitvector *name,
addr->s_addr = (addr->s_addr | addr_1);
} else {
- struct in6_addr *addr = (struct in6_addr *)(&ip_address->buffer);
- ip_address->family = AF_INET6;
- ip_address->prefix_len = name->len; // IPV6_ADDR_LEN_BITS;
+ struct in6_addr *addr = (struct in6_addr *)(&prefix->address.buffer);
+ prefix->family = AF_INET6;
+ prefix->len = name->len; // IPV6_ADDR_LEN_BITS;
for (int i = 0; i < 8; i++) {
addr->s6_addr[i] = (uint8_t)((name->bits[0] >> 8 * (7 - i)) & 0xFF);
diff --git a/hicn-light/src/hicn/core/nameBitvector.h b/hicn-light/src/hicn/core/nameBitvector.h
index 44cc45662..19944778c 100644
--- a/hicn-light/src/hicn/core/nameBitvector.h
+++ b/hicn-light/src/hicn/core/nameBitvector.h
@@ -48,8 +48,7 @@ uint32_t nameBitvector_lpm(const NameBitvector *a, const NameBitvector *b);
void nameBitvector_clear(NameBitvector *a, uint8_t start_from);
-int nameBitvector_ToIPAddress(const NameBitvector *name,
- ip_address_t *ip_address);
+int nameBitvector_ToIPAddress(const NameBitvector *name, ip_prefix_t *prefix);
void nameBitvector_setLen(NameBitvector *name, uint8_t len);
Address *nameBitvector_ToAddress(const NameBitvector *name);
diff --git a/hicn-light/src/hicn/io/hicnConnection.c b/hicn-light/src/hicn/io/hicnConnection.c
index 124885b33..d56231c38 100644
--- a/hicn-light/src/hicn/io/hicnConnection.c
+++ b/hicn-light/src/hicn/io/hicnConnection.c
@@ -40,6 +40,7 @@
typedef struct hicn_state {
Forwarder *forwarder;
+ char * interfaceName;
Logger *logger;
// the hicn listener socket we receive packets on
@@ -96,6 +97,7 @@ static connection_state_t _getState(const IoOperations *ops);
static void _setState(IoOperations *ops, connection_state_t state);
static connection_state_t _getAdminState(const IoOperations *ops);
static void _setAdminState(IoOperations *ops, connection_state_t admin_state);
+static const char * _getInterfaceName(const IoOperations *ops);
/*
* This assigns a unique pointer to the void * which we use
@@ -127,6 +129,7 @@ static IoOperations _template = {
.setState = &_setState,
.getAdminState = &_getAdminState,
.setAdminState = &_setAdminState,
+ .getInterfaceName = &_getInterfaceName,
};
// =================================================================
@@ -136,7 +139,7 @@ static bool _saveSockaddr(_HicnState *hicnConnState, const AddressPair *pair);
static void _refreshProbeDestAddress(_HicnState *hicnConnState,
const uint8_t *message);
-IoOperations *hicnConnection_Create(Forwarder *forwarder, int fd,
+IoOperations *hicnConnection_Create(Forwarder *forwarder, const char * interfaceName, int fd,
const AddressPair *pair, bool isLocal) {
IoOperations *io_ops = NULL;
@@ -146,6 +149,7 @@ IoOperations *hicnConnection_Create(Forwarder *forwarder, int fd,
sizeof(_HicnState));
hicnConnState->forwarder = forwarder;
+ hicnConnState->interfaceName = strdup(interfaceName);
hicnConnState->logger = logger_Acquire(forwarder_GetLogger(forwarder));
bool saved = _saveSockaddr(hicnConnState, pair);
@@ -183,6 +187,7 @@ IoOperations *hicnConnection_Create(Forwarder *forwarder, int fd,
// _saveSockaddr will already log an error, no need for extra log message
// here
logger_Release(&hicnConnState->logger);
+ free(hicnConnState->interfaceName);
parcMemory_Deallocate((void **)&hicnConnState);
}
@@ -223,6 +228,7 @@ static void _destroy(IoOperations **opsPtr) {
// should I say something to libhicn?
logger_Release(&hicnConnState->logger);
+ free(hicnConnState->interfaceName);
parcMemory_Deallocate((void **)&hicnConnState);
parcMemory_Deallocate((void **)&ops);
@@ -585,3 +591,11 @@ static void _setAdminState(IoOperations *ops, connection_state_t admin_state) {
(_HicnState *)ioOperations_GetClosure(ops);
hicnConnState->admin_state = admin_state;
}
+
+static const char * _getInterfaceName(const IoOperations *ops)
+{
+ parcAssertNotNull(ops, "Parameter must be non-null");
+ _HicnState *hicnConnState =
+ (_HicnState *)ioOperations_GetClosure(ops);
+ return hicnConnState->interfaceName;
+}
diff --git a/hicn-light/src/hicn/io/hicnConnection.h b/hicn-light/src/hicn/io/hicnConnection.h
index a14024a4e..fec18e1bd 100644
--- a/hicn-light/src/hicn/io/hicnConnection.h
+++ b/hicn-light/src/hicn/io/hicnConnection.h
@@ -48,6 +48,6 @@
* <#example#>
* @endcode
*/
-IoOperations *hicnConnection_Create(Forwarder *forwarder, int fd,
+IoOperations *hicnConnection_Create(Forwarder *forwarder, const char * interfaceName, int fd,
const AddressPair *pair, bool isLocal);
#endif // hicnConnection_h
diff --git a/hicn-light/src/hicn/io/hicnListener.c b/hicn-light/src/hicn/io/hicnListener.c
index d13dc5b4d..995347d6a 100644
--- a/hicn-light/src/hicn/io/hicnListener.c
+++ b/hicn-light/src/hicn/io/hicnListener.c
@@ -42,6 +42,9 @@
#define MAX_HICN_RETRY 5
struct hicn_listener {
+
+ char *listenerName;
+
Forwarder *forwarder;
Logger *logger;
@@ -71,6 +74,8 @@ struct hicn_listener {
};
static void _destroy(ListenerOps **listenerOpsPtr);
+static const char *_getListenerName(const ListenerOps *ops);
+static const char *_getInterfaceName(const ListenerOps *ops);
static unsigned _getInterfaceIndex(const ListenerOps *ops);
static const Address *_getListenAddress(const ListenerOps *ops);
static EncapType _getEncapType(const ListenerOps *ops);
@@ -85,6 +90,8 @@ static ListenerOps _hicnTemplate = {
.getListenAddress = &_getListenAddress,
.getEncapType = &_getEncapType,
.getSocket = &_getSocket,
+ .getInterfaceName = &_getInterfaceName,
+ .getListenerName = &_getListenerName,
.createConnection = &_createNewConnection,
.lookupConnection = &_lookupConnection,
};
@@ -125,6 +132,9 @@ ListenerOps *hicnListener_CreateInet(Forwarder *forwarder, char *symbolic,
sizeof(HicnListener));
hicn->forwarder = forwarder;
+ hicn->listenerName = parcMemory_StringDuplicate(symbolic, strlen(symbolic));
+ hicn->logger = logger_Acquire(forwarder_GetLogger(forwarder));
+
hicn->logger = logger_Acquire(forwarder_GetLogger(forwarder));
hicn->conn_id = forwarder_GetNextConnectionId(forwarder);
@@ -164,6 +174,7 @@ ListenerOps *hicnListener_CreateInet(Forwarder *forwarder, char *symbolic,
}
logger_Release(&hicn->logger);
addressDestroy(&hicn->localAddress);
+ parcMemory_Deallocate((void **)&hicn->listenerName);
parcMemory_Deallocate((void **)&hicn);
return NULL;
}
@@ -206,6 +217,7 @@ ListenerOps *hicnListener_CreateInet6(Forwarder *forwarder, char *symbolic,
sizeof(HicnListener));
hicn->forwarder = forwarder;
+ hicn->listenerName = parcMemory_StringDuplicate(symbolic, strlen(symbolic));
hicn->logger = logger_Acquire(forwarder_GetLogger(forwarder));
hicn->conn_id = forwarder_GetNextConnectionId(forwarder);
@@ -255,6 +267,7 @@ ListenerOps *hicnListener_CreateInet6(Forwarder *forwarder, char *symbolic,
}
logger_Release(&hicn->logger);
addressDestroy(&hicn->localAddress);
+ parcMemory_Deallocate((void **)&hicn->listenerName);
parcMemory_Deallocate((void **)&hicn);
return NULL;
}
@@ -421,6 +434,15 @@ static void _destroy(ListenerOps **listenerOpsPtr) {
*listenerOpsPtr = NULL;
}
+static const char *_getListenerName(const ListenerOps *ops) {
+ HicnListener *hicn = (HicnListener *)ops->context;
+ return hicn->listenerName;
+}
+static const char *_getInterfaceName(const ListenerOps *ops) {
+ const char *interfaceName = "";
+ return interfaceName;
+}
+
static unsigned _getInterfaceIndex(const ListenerOps *ops) {
HicnListener *hicn = (HicnListener *)ops->context;
return hicn->conn_id;
@@ -468,7 +490,7 @@ static unsigned _createNewConnection(ListenerOps * listener, int fd,
bool isLocal = false;
// udpConnection_Create takes ownership of the pair
- IoOperations *ops = hicnConnection_Create(hicn->forwarder, fd, pair, isLocal);
+ IoOperations *ops = hicnConnection_Create(hicn->forwarder, listener->getInterfaceName(listener), fd, pair, isLocal);
Connection *conn = connection_Create(ops);
connectionTable_Add(forwarder_GetConnectionTable(hicn->forwarder), conn);
diff --git a/hicn-light/src/hicn/io/hicnTunnel.c b/hicn-light/src/hicn/io/hicnTunnel.c
index baf10c637..fd5acc680 100644
--- a/hicn-light/src/hicn/io/hicnTunnel.c
+++ b/hicn-light/src/hicn/io/hicnTunnel.c
@@ -56,7 +56,7 @@ IoOperations *hicnTunnel_CreateOnListener(Forwarder *forwarder,
AddressPair *pair = addressPair_Create(localAddress, remoteAddress);
bool isLocal = false;
int fd = localListener->getSocket(localListener);
- ops = hicnConnection_Create(forwarder, fd, pair, isLocal);
+ ops = hicnConnection_Create(forwarder, localListener->getInterfaceName(localListener), fd, pair, isLocal);
addressPair_Release(&pair);
} else {
diff --git a/hicn-light/src/hicn/io/ioOperations.c b/hicn-light/src/hicn/io/ioOperations.c
index bbcea41f8..31e37a461 100644
--- a/hicn-light/src/hicn/io/ioOperations.c
+++ b/hicn-light/src/hicn/io/ioOperations.c
@@ -83,3 +83,7 @@ connection_state_t ioOperations_GetAdminState(const IoOperations *ops) {
void ioOperations_SetAdminState(IoOperations *ops, connection_state_t admin_state) {
ops->setAdminState(ops, admin_state);
}
+
+const char * ioOperations_GetInterfaceName(const IoOperations *ops) {
+ return ops->getInterfaceName(ops);
+}
diff --git a/hicn-light/src/hicn/io/ioOperations.h b/hicn-light/src/hicn/io/ioOperations.h
index 7a48b7e3e..c8a107199 100644
--- a/hicn-light/src/hicn/io/ioOperations.h
+++ b/hicn-light/src/hicn/io/ioOperations.h
@@ -67,6 +67,8 @@ typedef struct io_ops IoOperations;
* state).
* @constant setAdminState Allows to set the administrative state of a
* connection.
+ * @constant getInterfaceName Returns the interface name associated to a
+ * connection.
* @discussion <#Discussion#>
*/
struct io_ops {
@@ -87,6 +89,7 @@ struct io_ops {
void (*setState)(IoOperations *ops, connection_state_t state);
connection_state_t (*getAdminState)(const IoOperations *ops);
void (*setAdminState)(IoOperations *ops, connection_state_t admin_state);
+ const char * (*getInterfaceName)(const IoOperations *ops);
};
/**
@@ -413,4 +416,12 @@ connection_state_t ioOperations_GetAdminState(const IoOperations *ops);
*/
void ioOperations_SetAdminState(IoOperations *ops, connection_state_t admin_state);
+/**
+ * Sets the interface name associated to the connection.
+ *
+ * @param [in] ops The connection implementation.
+ * @return the name associated to the connection (const char *)
+ */
+const char * ioOperations_GetInterfaceName(const IoOperations *ops);
+
#endif // io_h
diff --git a/hicn-light/src/hicn/io/listener.h b/hicn-light/src/hicn/io/listener.h
index ef1955b12..1b473be59 100644
--- a/hicn-light/src/hicn/io/listener.h
+++ b/hicn-light/src/hicn/io/listener.h
@@ -55,6 +55,15 @@ struct listener_ops {
void (*destroy)(ListenerOps **listenerOpsPtr);
/**
+ * Returns the listener name of the listener.
+ *
+ * @param [in] ops Pointer to this structure
+ *
+ * @return the listener name of the listener
+ */
+ const char *(*getListenerName)(const ListenerOps *ops);
+
+ /**
* Returns the interface index of the listener.
*
* @param [in] ops Pointer to this structure
@@ -82,6 +91,15 @@ struct listener_ops {
EncapType (*getEncapType)(const ListenerOps *ops);
/**
+ * Returns the interface name of the listener.
+ *
+ * @param [in] ops Pointer to this structure
+ *
+ * @return the interface name of the listener
+ */
+ const char *(*getInterfaceName)(const ListenerOps *ops);
+
+ /**
* Returns the underlying socket associated with the listener
*
* Not all listeners are capable of returning a useful socket. In those
diff --git a/hicn-light/src/hicn/io/listenerSet.c b/hicn-light/src/hicn/io/listenerSet.c
index 982373b63..3e44973d7 100644
--- a/hicn-light/src/hicn/io/listenerSet.c
+++ b/hicn-light/src/hicn/io/listenerSet.c
@@ -130,3 +130,39 @@ ListenerOps *listenerSet_Find(const ListenerSet *set, EncapType encapType,
return match;
}
+
+ListenerOps *listenerSet_FindById(const ListenerSet *set, unsigned id) {
+ parcAssertNotNull(set, "Parameter set must be non-null");
+
+ ListenerOps *match = NULL;
+
+ for (size_t i = 0; i < parcArrayList_Size(set->listOfListeners) && !match;
+ i++) {
+ ListenerOps *ops = parcArrayList_Get(set->listOfListeners, i);
+ parcAssertNotNull(ops, "Got null listener ops at index %zu", i);
+ if (ops->getInterfaceIndex(ops) == id) {
+ match = ops;
+ }
+ }
+
+ return match;
+}
+
+int listenerSet_FindIdByListenerName(const ListenerSet *set, const char *listenerName ) {
+ parcAssertNotNull(set, "Parameter set must be non-null");
+ parcAssertNotNull(listenerName, "Parameter listenerName must be non-null");
+
+ ListenerOps *match = NULL;
+ int index = -1;
+ for (size_t i = 0; i < parcArrayList_Size(set->listOfListeners) && !match;
+ i++) {
+ ListenerOps *ops = parcArrayList_Get(set->listOfListeners, i);
+ parcAssertNotNull(ops, "Got null listener ops at index %zu", i);
+ if (ops->getListenerName(ops) && strcmp(ops->getListenerName(ops), listenerName) == 0) {
+ index = ops->getInterfaceIndex(ops);
+ break;
+ }
+ }
+
+ return index;
+}
diff --git a/hicn-light/src/hicn/io/listenerSet.h b/hicn-light/src/hicn/io/listenerSet.h
index 8d15a2736..c8937fa02 100644
--- a/hicn-light/src/hicn/io/listenerSet.h
+++ b/hicn-light/src/hicn/io/listenerSet.h
@@ -134,4 +134,41 @@ ListenerOps *listenerSet_Get(const ListenerSet *set, size_t index);
*/
ListenerOps *listenerSet_Find(const ListenerSet *set, EncapType encapType,
const Address *localAddress);
+
+
+/**
+ * Looks up a listener by its id
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] set An allocated listener set
+ * @param [in] id of the listener
+ *
+ * @retval non-null The listener matching the query
+ * @retval null Does not exist
+ *
+ * Example:
+ * @code
+ *
+ * @endcode
+ */
+ListenerOps *listenerSet_FindById(const ListenerSet *set, unsigned id);
+/**
+ * Looks up a listener by its id
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] set An allocated listener set
+ * @param [in] name of the listener
+ *
+ * @retval greater or equal to 0 The listener matching the query
+ * @retval -1 Does not exist
+ *
+ * Example:
+ * @code
+ *
+ * @endcode
+ */
+int listenerSet_FindIdByListenerName(const ListenerSet *set, const char *listenerName);
+
#endif
diff --git a/hicn-light/src/hicn/io/streamConnection.c b/hicn-light/src/hicn/io/streamConnection.c
index ce2341cb8..224f129f7 100644
--- a/hicn-light/src/hicn/io/streamConnection.c
+++ b/hicn-light/src/hicn/io/streamConnection.c
@@ -47,6 +47,7 @@ static void _conn_eventcb(PARCEventQueue *bufferEventVector,
typedef struct stream_state {
Forwarder *forwarder;
+ char * interfaceName;
Logger *logger;
int fd;
@@ -90,6 +91,7 @@ static connection_state_t _streamConnection_getState(const IoOperations *ops);
static void _streamConnection_setState(IoOperations *ops, connection_state_t state);
static connection_state_t _streamConnection_getAdminState(const IoOperations *ops);
static void _streamConnection_setAdminState(IoOperations *ops, connection_state_t admin_state);
+static const char * _streamConnection_getInterfaceName(const IoOperations *ops);
/*
* This assigns a unique pointer to the void * which we use
@@ -121,6 +123,7 @@ static IoOperations _template = {
.setState = &_streamConnection_setState,
.getAdminState = &_streamConnection_getAdminState,
.setAdminState = &_streamConnection_setAdminState,
+ .getInterfaceName = &_streamConnection_getInterfaceName,
};
IoOperations *streamConnection_AcceptConnection(Forwarder *forwarder, int fd,
@@ -137,6 +140,7 @@ IoOperations *streamConnection_AcceptConnection(Forwarder *forwarder, int fd,
PARCEventQueueOption_CloseOnFree | PARCEventQueueOption_DeferCallbacks);
stream->forwarder = forwarder;
+ stream->interfaceName = NULL;
stream->logger = logger_Acquire(forwarder_GetLogger(forwarder));
stream->fd = fd;
stream->id = forwarder_GetNextConnectionId(forwarder);
@@ -191,6 +195,7 @@ IoOperations *streamConnection_OpenConnection(Forwarder *forwarder,
sizeof(_StreamState));
stream->forwarder = forwarder;
+ stream->interfaceName = NULL;
stream->logger = logger_Acquire(forwarder_GetLogger(forwarder));
stream->fd = parcEventQueue_GetFileDescriptor(bufferEventVector);
stream->bufferEventVector = bufferEventVector;
@@ -606,7 +611,7 @@ static void _conn_readcb(PARCEventQueue *event, PARCEventType type,
} else {
parcAssertTrue(false,
- "(Local stream connection) malformend packet received");
+ "(Local stream connection) malformed packet received");
}
}
@@ -728,3 +733,11 @@ static void _streamConnection_setAdminState(IoOperations *ops, connection_state_
(_StreamState *)ioOperations_GetClosure(ops);
stream->admin_state = admin_state;
}
+
+static const char * _streamConnection_getInterfaceName(const IoOperations *ops)
+{
+ parcAssertNotNull(ops, "Parameter must be non-null");
+ _StreamState *stream =
+ (_StreamState *)ioOperations_GetClosure(ops);
+ return stream->interfaceName;
+}
diff --git a/hicn-light/src/hicn/io/tcpListener.c b/hicn-light/src/hicn/io/tcpListener.c
index cc6fdbba8..4464edf28 100644
--- a/hicn-light/src/hicn/io/tcpListener.c
+++ b/hicn-light/src/hicn/io/tcpListener.c
@@ -30,6 +30,8 @@
#include <parc/assert/parc_Assert.h>
typedef struct tcp_listener {
+ char *listenerName;
+
Forwarder *forwarder;
Logger *logger;
@@ -38,6 +40,7 @@ typedef struct tcp_listener {
Address *localAddress;
unsigned id;
+ char *interfaceName;
// is the localAddress as 127.0.0.0 address?
bool isLocalAddressLocal;
@@ -46,30 +49,36 @@ typedef struct tcp_listener {
static void _tcpListener_Destroy(_TcpListener **listenerPtr);
static void _tcpListener_OpsDestroy(ListenerOps **listenerOpsPtr);
+static const char *_tcpListener_ListenerName(const ListenerOps *ops);
static unsigned _tcpListener_OpsGetInterfaceIndex(const ListenerOps *ops);
static const Address *_tcpListener_OpsGetListenAddress(const ListenerOps *ops);
+static const char *_tcpListener_InterfaceName(const ListenerOps *ops);
static EncapType _tcpListener_OpsGetEncapType(const ListenerOps *ops);
static ListenerOps _tcpTemplate = {
.context = NULL,
.destroy = &_tcpListener_OpsDestroy,
+ .getListenerName = &_tcpListener_ListenerName,
.getInterfaceIndex = &_tcpListener_OpsGetInterfaceIndex,
.getListenAddress = &_tcpListener_OpsGetListenAddress,
.getEncapType = &_tcpListener_OpsGetEncapType,
+ .getInterfaceName = &_tcpListener_InterfaceName,
.getSocket = NULL};
// STREAM daemon listener callback
static void _tcpListener_Listen(int, struct sockaddr *, int socklen,
void *tcpVoid);
-ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder,
- struct sockaddr_in6 sin6) {
+ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder, char *listenerName,
+ struct sockaddr_in6 sin6, char *interfaceName) {
_TcpListener *tcp = parcMemory_AllocateAndClear(sizeof(_TcpListener));
parcAssertNotNull(tcp, "parcMemory_AllocateAndClear(%zu) returned NULL",
sizeof(_TcpListener));
tcp->forwarder = forwarder;
+ tcp->listenerName = parcMemory_StringDuplicate(listenerName, strlen(listenerName));
tcp->logger = logger_Acquire(forwarder_GetLogger(forwarder));
+ tcp->interfaceName = parcMemory_StringDuplicate(interfaceName, strlen(interfaceName));
tcp->listener = dispatcher_CreateListener(
forwarder_GetDispatcher(forwarder), _tcpListener_Listen, (void *)tcp, -1,
@@ -107,8 +116,8 @@ ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder,
return ops;
}
-ListenerOps *tcpListener_CreateInet(Forwarder *forwarder,
- struct sockaddr_in sin) {
+ListenerOps *tcpListener_CreateInet(Forwarder *forwarder, char *listenerName,
+ struct sockaddr_in sin, char *interfaceName) {
_TcpListener *tcp = parcMemory_AllocateAndClear(sizeof(_TcpListener));
parcAssertNotNull(tcp, "parcMemory_AllocateAndClear(%zu) returned NULL",
sizeof(_TcpListener));
@@ -164,6 +173,9 @@ static void _tcpListener_Destroy(_TcpListener **listenerPtr) {
parcMemory_Deallocate((void **)&str);
}
+ parcMemory_Deallocate((void **)&tcp->listenerName);
+ parcMemory_Deallocate((void **)&tcp->interfaceName);
+
logger_Release(&tcp->logger);
dispatcher_DestroyListener(forwarder_GetDispatcher(tcp->forwarder),
&tcp->listener);
@@ -174,6 +186,16 @@ static void _tcpListener_Destroy(_TcpListener **listenerPtr) {
// ==================================================
+static const char *_tcpListener_ListenerName(const ListenerOps *ops) {
+ _TcpListener *tcp = (_TcpListener *)ops->context;
+ return tcp->listenerName;
+}
+
+static const char *_tcpListener_InterfaceName(const ListenerOps *ops) {
+ _TcpListener *tcp = (_TcpListener *)ops->context;
+ return tcp->interfaceName;
+}
+
static void _tcpListener_Listen(int fd, struct sockaddr *sa, int socklen,
void *tcpVoid) {
_TcpListener *tcp = (_TcpListener *)tcpVoid;
diff --git a/hicn-light/src/hicn/io/tcpListener.h b/hicn-light/src/hicn/io/tcpListener.h
index df0bbea1e..a841738e5 100644
--- a/hicn-light/src/hicn/io/tcpListener.h
+++ b/hicn-light/src/hicn/io/tcpListener.h
@@ -33,8 +33,8 @@
#include <hicn/io/listener.h>
#include <stdlib.h>
-ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder,
- struct sockaddr_in6 sin6);
-ListenerOps *tcpListener_CreateInet(Forwarder *forwarder,
- struct sockaddr_in sin);
+ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder, char *listenerName,
+ struct sockaddr_in6 sin6, char *interfaceName);
+ListenerOps *tcpListener_CreateInet(Forwarder *forwarder, char *listenerName,
+ struct sockaddr_in sin, char *interfaceName);
#endif // tcpListener_h
diff --git a/hicn-light/src/hicn/io/udpConnection.c b/hicn-light/src/hicn/io/udpConnection.c
index 78157f01f..9ad70403f 100644
--- a/hicn-light/src/hicn/io/udpConnection.c
+++ b/hicn-light/src/hicn/io/udpConnection.c
@@ -40,6 +40,7 @@
typedef struct udp_state {
Forwarder *forwarder;
+ char * interfaceName;
Logger *logger;
// the udp listener socket we receive packets on
@@ -81,6 +82,7 @@ static connection_state_t _getState(const IoOperations *ops);
static void _setState(IoOperations *ops, connection_state_t state);
static connection_state_t _getAdminState(const IoOperations *ops);
static void _setAdminState(IoOperations *ops, connection_state_t admin_state);
+static const char * _getInterfaceName(const IoOperations *ops);
/*
* This assigns a unique pointer to the void * which we use
@@ -112,6 +114,7 @@ static IoOperations _template = {
.setState = &_setState,
.getAdminState = &_getAdminState,
.setAdminState = &_setAdminState,
+ .getInterfaceName = &_getInterfaceName,
};
// =================================================================
@@ -119,7 +122,7 @@ static IoOperations _template = {
static void _setConnectionState(_UdpState *Udp, bool isUp);
static bool _saveSockaddr(_UdpState *udpConnState, const AddressPair *pair);
-IoOperations *udpConnection_Create(Forwarder *forwarder, int fd,
+IoOperations *udpConnection_Create(Forwarder *forwarder, const char * interfaceName, int fd,
const AddressPair *pair, bool isLocal) {
IoOperations *io_ops = NULL;
@@ -129,6 +132,7 @@ IoOperations *udpConnection_Create(Forwarder *forwarder, int fd,
sizeof(_UdpState));
udpConnState->forwarder = forwarder;
+ udpConnState->interfaceName = strdup(interfaceName);
udpConnState->logger = logger_Acquire(forwarder_GetLogger(forwarder));
bool saved = _saveSockaddr(udpConnState, pair);
@@ -166,6 +170,8 @@ IoOperations *udpConnection_Create(Forwarder *forwarder, int fd,
// _saveSockaddr will already log an error, no need for extra log message
// here
logger_Release(&udpConnState->logger);
+
+ free(udpConnState->interfaceName);
parcMemory_Deallocate((void **)&udpConnState);
}
@@ -202,6 +208,7 @@ static void _destroy(IoOperations **opsPtr) {
// that when its done
logger_Release(&udpConnState->logger);
+ free(udpConnState->interfaceName);
parcMemory_Deallocate((void **)&udpConnState);
parcMemory_Deallocate((void **)&ops);
@@ -435,3 +442,11 @@ static void _setAdminState(IoOperations *ops, connection_state_t admin_state) {
(_UdpState *)ioOperations_GetClosure(ops);
udpConnState->admin_state = admin_state;
}
+
+static const char * _getInterfaceName(const IoOperations *ops)
+{
+ parcAssertNotNull(ops, "Parameter must be non-null");
+ _UdpState *udpConnState =
+ (_UdpState *)ioOperations_GetClosure(ops);
+ return udpConnState->interfaceName;
+}
diff --git a/hicn-light/src/hicn/io/udpConnection.h b/hicn-light/src/hicn/io/udpConnection.h
index 07c4da9bd..9fbc5348b 100644
--- a/hicn-light/src/hicn/io/udpConnection.h
+++ b/hicn-light/src/hicn/io/udpConnection.h
@@ -48,6 +48,6 @@
* <#example#>
* @endcode
*/
-IoOperations *udpConnection_Create(Forwarder *forwarder, int fd,
+IoOperations *udpConnection_Create(Forwarder *forwarder, const char * interfaceName, int fd,
const AddressPair *pair, bool isLocal);
#endif // udpConnection_h
diff --git a/hicn-light/src/hicn/io/udpListener.c b/hicn-light/src/hicn/io/udpListener.c
index f6b434fed..050ca104c 100644
--- a/hicn-light/src/hicn/io/udpListener.c
+++ b/hicn-light/src/hicn/io/udpListener.c
@@ -41,6 +41,7 @@
struct udp_listener {
Forwarder *forwarder;
+ char *listenerName;
Logger *logger;
PARCEvent *udp_event;
@@ -48,13 +49,16 @@ struct udp_listener {
uint16_t port;
unsigned id;
+ char *interfaceName;
Address *localAddress;
};
static void _destroy(ListenerOps **listenerOpsPtr);
+static const char *_getListenerName(const ListenerOps *ops);
static unsigned _getInterfaceIndex(const ListenerOps *ops);
static const Address *_getListenAddress(const ListenerOps *ops);
static EncapType _getEncapType(const ListenerOps *ops);
+static const char *_getInterfaceName(const ListenerOps *ops);
static int _getSocket(const ListenerOps *ops);
static unsigned _createNewConnection(ListenerOps *listener, int fd, const AddressPair *pair);
static const Connection * _lookupConnection(ListenerOps * listener, const AddressPair *pair);
@@ -66,8 +70,10 @@ static ListenerOps udpTemplate = {
.getListenAddress = &_getListenAddress,
.getEncapType = &_getEncapType,
.getSocket = &_getSocket,
+ .getListenerName = &_getListenerName,
.createConnection = &_createNewConnection,
.lookupConnection = &_lookupConnection,
+ .getInterfaceName = &_getInterfaceName,
};
static void _readcb(int fd, PARCEventType what, void * listener_void);
@@ -76,19 +82,16 @@ static void _readcb(int fd, PARCEventType what, void * listener_void);
extern int bindSocket(int sock, const char* ifname);
#endif
-#ifdef __linux__
-ListenerOps *udpListener_CreateInet6(Forwarder *forwarder,
+ListenerOps *udpListener_CreateInet6(Forwarder *forwarder, char *listenerName,
struct sockaddr_in6 sin6, const char *interfaceName) {
-#else
-ListenerOps *udpListener_CreateInet6(Forwarder *forwarder,
- struct sockaddr_in6 sin6) {
-#endif
ListenerOps *ops = NULL;
UdpListener *udp = parcMemory_AllocateAndClear(sizeof(UdpListener));
parcAssertNotNull(udp, "parcMemory_AllocateAndClear(%zu) returned NULL",
sizeof(UdpListener));
udp->forwarder = forwarder;
+ udp->listenerName = parcMemory_StringDuplicate(listenerName, strlen(listenerName));
+ udp->interfaceName = parcMemory_StringDuplicate(interfaceName, strlen(interfaceName));
udp->logger = logger_Acquire(forwarder_GetLogger(forwarder));
udp->localAddress = addressCreateFromInet6(&sin6);
udp->id = forwarder_GetNextConnectionId(forwarder);
@@ -172,6 +175,8 @@ ListenerOps *udpListener_CreateInet6(Forwarder *forwarder,
myerrno, strerror(myerrno));
parcMemory_Deallocate((void **)&str);
}
+ parcMemory_Deallocate((void **)&udp->listenerName);
+ parcMemory_Deallocate((void **)&udp->interfaceName);
#ifndef _WIN32
close(udp->udp_socket);
#else
@@ -185,19 +190,16 @@ ListenerOps *udpListener_CreateInet6(Forwarder *forwarder,
return ops;
}
-#ifdef __linux__
-ListenerOps *udpListener_CreateInet(Forwarder *forwarder,
+ListenerOps *udpListener_CreateInet(Forwarder *forwarder, char *listenerName,
struct sockaddr_in sin, const char *interfaceName) {
-#else
-ListenerOps *udpListener_CreateInet(Forwarder *forwarder,
- struct sockaddr_in sin) {
-#endif
ListenerOps *ops = NULL;
UdpListener *udp = parcMemory_AllocateAndClear(sizeof(UdpListener));
parcAssertNotNull(udp, "parcMemory_AllocateAndClear(%zu) returned NULL",
sizeof(UdpListener));
udp->forwarder = forwarder;
+ udp->listenerName = parcMemory_StringDuplicate(listenerName, strlen(listenerName));
+ udp->interfaceName = parcMemory_StringDuplicate(interfaceName, strlen(interfaceName));
udp->logger = logger_Acquire(forwarder_GetLogger(forwarder));
udp->localAddress = addressCreateFromInet(&sin);
udp->id = forwarder_GetNextConnectionId(forwarder);
@@ -315,6 +317,16 @@ static void udpListener_Destroy(UdpListener **listenerPtr) {
*listenerPtr = NULL;
}
+static const char *_getListenerName(const ListenerOps *ops) {
+ UdpListener *udp = (UdpListener *)ops->context;
+ return udp->listenerName;
+}
+
+static const char *_getInterfaceName(const ListenerOps *ops) {
+ UdpListener *udp = (UdpListener *)ops->context;
+ return udp->interfaceName;
+}
+
static void _destroy(ListenerOps **listenerOpsPtr) {
ListenerOps *ops = *listenerOpsPtr;
UdpListener *udp = (UdpListener *)ops->context;
@@ -420,7 +432,7 @@ static unsigned _createNewConnection(ListenerOps * listener, int fd,
}
// metisUdpConnection_Create takes ownership of the pair
- IoOperations *ops = udpConnection_Create(udp->forwarder, fd, pair, isLocal);
+ IoOperations *ops = udpConnection_Create(udp->forwarder, udp->interfaceName, fd, pair, isLocal);
Connection *conn = connection_Create(ops);
// connection_AllowWldrAutoStart(conn);
diff --git a/hicn-light/src/hicn/io/udpListener.h b/hicn-light/src/hicn/io/udpListener.h
index 81d191eab..62c09e4db 100644
--- a/hicn-light/src/hicn/io/udpListener.h
+++ b/hicn-light/src/hicn/io/udpListener.h
@@ -27,16 +27,9 @@
struct udp_listener;
typedef struct udp_listener UdpListener;
-#ifdef __linux__
-ListenerOps *udpListener_CreateInet6(Forwarder *forwarder,
+ListenerOps *udpListener_CreateInet6(Forwarder *forwarder, char *listenerName,
struct sockaddr_in6 sin6, const char *if_bind);
-ListenerOps *udpListener_CreateInet(Forwarder *forwarder,
+ListenerOps *udpListener_CreateInet(Forwarder *forwarder, char *listenerName,
struct sockaddr_in sin, const char *if_bind);
-#else
-ListenerOps *udpListener_CreateInet6(Forwarder *forwarder,
- struct sockaddr_in6 sin6);
-ListenerOps *udpListener_CreateInet(Forwarder *forwarder,
- struct sockaddr_in sin);
-#endif
// void udpListener_SetPacketType(ListenerOps *ops, MessagePacketType type);
#endif // udpListener_h
diff --git a/hicn-light/src/hicn/io/udpTunnel.c b/hicn-light/src/hicn/io/udpTunnel.c
index 2f2f84105..9f5249e3c 100644
--- a/hicn-light/src/hicn/io/udpTunnel.c
+++ b/hicn-light/src/hicn/io/udpTunnel.c
@@ -60,7 +60,7 @@ IoOperations *udpTunnel_CreateOnListener(Forwarder *forwarder,
int fd = localListener->getSocket(localListener);
// udpListener_SetPacketType(localListener,
// MessagePacketType_ContentObject);
- ops = udpConnection_Create(forwarder, fd, pair, isLocal);
+ ops = udpConnection_Create(forwarder, localListener->getInterfaceName(localListener), fd, pair, isLocal);
addressPair_Release(&pair);
} else {
diff --git a/hicn-light/src/hicn/processor/fibEntry.c b/hicn-light/src/hicn/processor/fibEntry.c
index 9d82b086e..04e453ab9 100644
--- a/hicn-light/src/hicn/processor/fibEntry.c
+++ b/hicn-light/src/hicn/processor/fibEntry.c
@@ -39,7 +39,7 @@
#ifdef WITH_POLICY
#include <hicn/core/forwarder.h>
-#include <hicn/utils/policy.h>
+#include <hicn/policy.h>
#ifdef WITH_MAPME
#include <hicn/core/mapMe.h>
@@ -218,6 +218,8 @@ fibEntry_GetAvailableNextHops(const FibEntry *fibEntry, unsigned in_connection)
ConnectionList * list = connectionTable_GetEntries(table);
for (size_t i = 0; i < connectionList_Length(list); i++) {
Connection *conn = connectionList_Get(list, i);
+ if (connection_GetAdminState(conn) == CONNECTION_STATE_DOWN)
+ continue;
if (connection_GetState(conn) == CONNECTION_STATE_DOWN)
continue;
if (connection_IsLocal(conn))
@@ -236,6 +238,8 @@ fibEntry_GetAvailableNextHops(const FibEntry *fibEntry, unsigned in_connection)
const Connection * conn = connectionTable_FindById(table, conn_id);
if (!conn)
continue;
+ if (connection_GetAdminState(conn) == CONNECTION_STATE_DOWN)
+ continue;
if (connection_GetState(conn) == CONNECTION_STATE_DOWN)
continue;
if (!connection_IsLocal(conn))
@@ -259,6 +263,8 @@ fibEntry_GetAvailableNextHops(const FibEntry *fibEntry, unsigned in_connection)
conn = connectionTable_FindById(table, conn_id);
if (!conn)
continue;
+ if (connection_GetAdminState(conn) == CONNECTION_STATE_DOWN)
+ continue;
if (connection_GetState(conn) == CONNECTION_STATE_DOWN)
continue;
diff --git a/hicn-light/src/hicn/socket/api.c b/hicn-light/src/hicn/socket/api.c
index 213163675..a3d5a3cfe 100644
--- a/hicn-light/src/hicn/socket/api.c
+++ b/hicn-light/src/hicn/socket/api.c
@@ -39,7 +39,7 @@ static hicn_conf_t hicn_default_conf = {
struct ip_rule_state_ {
char tun_name[IF_NAMESIZE];
- ip_address_t ip_address;
+ ip_prefix_t prefix;
uint32_t table_id;
uint8_t priority;
uint8_t address_family;
@@ -160,7 +160,7 @@ void hicn_destroy() {
}
} else {
rc = ops.del_prio_rule(
- &rules_to_remove[i].ip_address, rules_to_remove[i].address_family,
+ &rules_to_remove[i].prefix, rules_to_remove[i].address_family,
rules_to_remove[i].priority, rules_to_remove[i].table_id);
if (rc < 0) {
goto ERR;
@@ -204,7 +204,7 @@ int hicn_socket_cmp(hicn_socket_t *a, hicn_socket_t *b) {
return b->fd - a->fd;
}
-ip_address_t *hicn_socket_get_src_ip(hicn_socket_t *socket) {
+ip_prefix_t *hicn_socket_get_src_ip(hicn_socket_t *socket) {
if (socket->type != HS_CONNECTION) {
return NULL;
}
@@ -252,7 +252,7 @@ int hicn_set_local_endpoint(hicn_socket_t *socket, const char *local_ip_address,
*/
/* Copy the local IP address inside the connection */
- rc = hicn_ip_pton(local_ip_address, &socket->connection.tun_ip_address);
+ rc = ip_prefix_pton(local_ip_address, &socket->connection.tun_ip_address);
if (rc < 0) {
rc = HICN_SOCKET_ERROR_SOCKET_LOCAL_REPR;
goto end;
@@ -262,13 +262,13 @@ end:
return rc;
}
-int hicn_get_local_address(const ip_address_t *remote_address,
- ip_address_t *local_address) {
+int hicn_get_local_address(const ip_prefix_t *remote_address,
+ ip_prefix_t *local_address) {
int rc = 0;
uint32_t interface_id;
- char remote_address_str[INET_MAX_ADDRSTRLEN];
+ char remote_address_str[INET_MAX_ADDRSTRLEN + 4 ];
- rc = hicn_ip_ntop(remote_address, remote_address_str,
+ rc = ip_prefix_ntop_short(remote_address, remote_address_str,
sizeof(remote_address_str));
if (rc < 0) {
rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR;
@@ -300,7 +300,7 @@ ERR:
int hicn_set_remote_endpoint(hicn_socket_t *socket,
const char *remote_ip_address) {
int af, rc = HICN_SOCKET_ERROR_NONE;
- ip_address_t addr;
+ ip_prefix_t addr;
af = get_addr_family(remote_ip_address);
if ((af != AF_INET6) && (af != AF_INET)) {
@@ -308,8 +308,8 @@ int hicn_set_remote_endpoint(hicn_socket_t *socket,
}
/* Bind local endpoint if not done yet */
- if (ip_address_empty(&socket->connection.tun_ip_address)) {
- char local_ip_address[INET_MAX_ADDRSTRLEN];
+ if (ip_prefix_empty(&socket->connection.tun_ip_address)) {
+ char local_ip_address[INET_MAX_ADDRSTRLEN + 4];
/* Local interface id */
// INFO("Getting interface_id from gateway IP address %s",
@@ -338,7 +338,7 @@ int hicn_set_remote_endpoint(hicn_socket_t *socket,
/////
/* Convert to representation format */
- rc = hicn_ip_ntop(&addr, local_ip_address, sizeof(local_ip_address));
+ rc = ip_prefix_ntop_short(&addr, local_ip_address, sizeof(local_ip_address));
if (rc < 0) {
rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR;
goto ERR;
@@ -455,8 +455,8 @@ int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) {
return rc;
}
- ip_address_t ip_address;
- rc = hicn_ip_pton(prefix, &ip_address);
+ ip_prefix_t ip_prefix;
+ rc = ip_prefix_pton(prefix, &ip_prefix);
if (rc < 0) {
return rc;
}
@@ -467,7 +467,7 @@ int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) {
if (punting_table_id == -1) punting_table_id = socket->connection.table_id;
- rc = ops.add_prio_rule(&ip_address, ip_address.family, 0,
+ rc = ops.add_prio_rule(&ip_prefix, ip_prefix.family, 0,
socket->connection.table_id);
if (rc < 0) {
return rc;
@@ -475,8 +475,8 @@ int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) {
strcpy(rules_to_remove[rules_counter].tun_name, "NONE");
- rules_to_remove[rules_counter].ip_address = ip_address;
- rules_to_remove[rules_counter].address_family = ip_address.family;
+ rules_to_remove[rules_counter].prefix = ip_prefix;
+ rules_to_remove[rules_counter].address_family = ip_prefix.family;
rules_to_remove[rules_counter].table_id = socket->connection.table_id;
rules_to_remove[rules_counter].priority = 0;
++rules_counter;
diff --git a/hicn-light/src/hicn/socket/api.h b/hicn-light/src/hicn/socket/api.h
index 283065fc7..1a7f5c700 100644
--- a/hicn-light/src/hicn/socket/api.h
+++ b/hicn-light/src/hicn/socket/api.h
@@ -84,7 +84,7 @@ typedef struct hicn_socket_s {
union {
struct {
- ip_address_t tun_ip_address;
+ ip_prefix_t tun_ip_address;
uint32_t interface_id;
/* ID of the corresponding table : avoid default values of 0, 32766 and
@@ -163,8 +163,8 @@ void hicn_free(hicn_socket_helper_t *hicn);
*
* @return 0 in case of success, -1 otherwise.
*/
-int hicn_get_local_address(const ip_address_t *remote_address,
- ip_address_t *local_address);
+int hicn_get_local_address(const ip_prefix_t *remote_address,
+ ip_prefix_t *local_address);
/* hICN socket */
diff --git a/hicn-light/src/hicn/socket/ops.h b/hicn-light/src/hicn/socket/ops.h
index 249caf87a..1bee7c6f6 100644
--- a/hicn-light/src/hicn/socket/ops.h
+++ b/hicn-light/src/hicn/socket/ops.h
@@ -17,10 +17,10 @@ typedef struct {
int (*get_output_ifid)(const char *ip_address, uint8_t address_family,
uint32_t *interface_id);
int (*get_ip_addr)(uint32_t interface_id, uint8_t address_family,
- ip_address_t *ip_address);
- int (*set_ip_addr)(uint32_t interface_id, ip_address_t *ip_address);
+ ip_prefix_t *ip_address);
+ int (*set_ip_addr)(uint32_t interface_id, ip_prefix_t *ip_address);
int (*up_if)(uint32_t interface_id);
- int (*add_in_route_table)(const ip_address_t *prefix,
+ int (*add_in_route_table)(const ip_prefix_t *prefix,
const uint32_t interface_id,
const uint8_t table_id);
int (*add_in_route_table_s)(const char *prefix, const uint32_t interface_id,
@@ -30,23 +30,23 @@ typedef struct {
const uint8_t table_id, int default_route);
int (*del_out_route)(const char *gateway, const uint8_t address_family,
const uint8_t table_id);
- int (*del_lo_route)(const ip_address_t *ip_address);
+ int (*del_lo_route)(const ip_prefix_t *ip_address);
int (*add_rule)(const char *interface_name, const uint8_t address_family,
const uint8_t table_id);
int (*del_rule)(const char *interface_name, const uint8_t address_family,
const uint8_t table_id);
- int (*add_neigh_proxy)(const ip_address_t *ip_address,
+ int (*add_neigh_proxy)(const ip_prefix_t *ip_address,
const uint32_t interface_id);
- int (*add_prio_rule)(const ip_address_t *ip_address,
+ int (*add_prio_rule)(const ip_prefix_t *ip_address,
const uint8_t address_family, const uint32_t priority,
const uint8_t table_id);
- int (*add_lo_prio_rule)(const ip_address_t *ip_address,
+ int (*add_lo_prio_rule)(const ip_prefix_t *ip_address,
const uint8_t address_family,
const uint32_t priority);
- int (*del_prio_rule)(const ip_address_t *ip_address,
+ int (*del_prio_rule)(const ip_prefix_t *ip_address,
const uint8_t address_family, const uint32_t priority,
const uint8_t table_id);
- int (*del_lo_prio_rule)(const ip_address_t *ip_address,
+ int (*del_lo_prio_rule)(const ip_prefix_t *ip_address,
const uint8_t address_family,
const uint32_t priority);
} hicn_socket_ops_t;
diff --git a/hicn-light/src/hicn/socket/ops_linux.c b/hicn-light/src/hicn/socket/ops_linux.c
index 0b1c6b817..f81ceff37 100644
--- a/hicn-light/src/hicn/socket/ops_linux.c
+++ b/hicn-light/src/hicn/socket/ops_linux.c
@@ -60,13 +60,13 @@ int _nl_get_output_ifid(const char *ip_address, uint8_t address_family,
* @see getifaddrs
*/
int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family,
- ip_address_t *ip_address);
+ ip_prefix_t *ip_address);
-int _nl_set_ip_addr(uint32_t interface_id, ip_address_t *ip_address);
+int _nl_set_ip_addr(uint32_t interface_id, ip_prefix_t *ip_address);
int _nl_up_if(uint32_t interface_id);
-int _nl_add_in_route_table(const ip_address_t *prefix,
+int _nl_add_in_route_table(const ip_prefix_t *prefix,
const uint32_t interface_id, const uint8_t table_id);
int _nl_add_in_route_table_s(const char *prefix, const uint32_t interface_id,
const uint8_t table_id);
@@ -77,25 +77,25 @@ int _nl_add_out_route(const char *gateway, const uint8_t address_family,
int _nl_del_out_route(const char *gateway, const uint8_t address_family,
const uint8_t table_id);
-int _nl_del_lo_route(const ip_address_t *ip_address);
+int _nl_del_lo_route(const ip_prefix_t *ip_address);
int _nl_add_rule(const char *interface_name, const uint8_t address_family,
const uint8_t table_id);
int _nl_del_rule(const char *interface_name, const uint8_t address_family,
const uint8_t table_id);
-int _nl_add_neigh_proxy(const ip_address_t *ip_address,
+int _nl_add_neigh_proxy(const ip_prefix_t *ip_address,
const uint32_t interface_id);
-int _nl_add_prio_rule(const ip_address_t *ip_address,
+int _nl_add_prio_rule(const ip_prefix_t *ip_address,
const uint8_t address_family, const uint32_t priority,
const uint8_t table_id);
-int _nl_add_lo_prio_rule(const ip_address_t *ip_address,
+int _nl_add_lo_prio_rule(const ip_prefix_t *ip_address,
const uint8_t address_family, const uint32_t priority);
-int _nl_del_prio_rule(const ip_address_t *ip_address,
+int _nl_del_prio_rule(const ip_prefix_t *ip_address,
const uint8_t address_family, const uint32_t priority,
const uint8_t table_id);
-int _nl_del_lo_prio_rule(const ip_address_t *ip_address,
+int _nl_del_lo_prio_rule(const ip_prefix_t *ip_address,
const uint8_t address_family, const uint32_t priority);
#endif /* HICN_NETLINK_H */
@@ -530,7 +530,7 @@ ERR:
}
int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family,
- ip_address_t *ip_address) {
+ ip_prefix_t *prefix) {
char buffer[BUFSIZE];
struct nlmsghdr *hdr = (struct nlmsghdr *)buffer;
size_t n;
@@ -575,9 +575,9 @@ int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family,
if ((payload->ifa_index == interface_id) &&
(payload->ifa_prefixlen < IPV6_ADDR_LEN * 8)) {
printf("got ip address\n");
- memcpy(ip_address->buffer, RTA_DATA(payload + 1), IPV6_ADDR_LEN);
- ip_address->family = AF_INET6;
- ip_address->prefix_len = IPV6_ADDR_LEN_BITS;
+ memcpy(prefix->address.buffer, RTA_DATA(payload + 1), IPV6_ADDR_LEN);
+ prefix->family = AF_INET6;
+ prefix->len = IPV6_ADDR_LEN_BITS;
printf("returning %d\n", HICN_SOCKET_ERROR_NONE);
return HICN_SOCKET_ERROR_NONE;
}
@@ -585,9 +585,9 @@ int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family,
if ((payload->ifa_index == interface_id) &&
(payload->ifa_prefixlen < IPV4_ADDR_LEN * 8)) {
printf("got ip address\n");
- memcpy(ip_address->buffer, RTA_DATA(payload + 1), IPV4_ADDR_LEN);
- ip_address->family = AF_INET;
- ip_address->prefix_len = IPV4_ADDR_LEN_BITS;
+ memcpy(prefix->address.buffer, RTA_DATA(payload + 1), IPV4_ADDR_LEN);
+ prefix->family = AF_INET;
+ prefix->len = IPV4_ADDR_LEN_BITS;
printf("returning %d\n", HICN_SOCKET_ERROR_NONE);
return HICN_SOCKET_ERROR_NONE;
}
@@ -604,7 +604,7 @@ ERR_SOCKET:
return HICN_SOCKET_ERROR_UNSPEC;
}
-int _nl_set_ip_addr(uint32_t interface_id, ip_address_t *ip_address) {
+int _nl_set_ip_addr(uint32_t interface_id, ip_prefix_t *prefix) {
char buffer[BUFSIZE];
struct nlmsghdr *hdr = (struct nlmsghdr *)buffer;
size_t n;
@@ -617,19 +617,19 @@ int _nl_set_ip_addr(uint32_t interface_id, ip_address_t *ip_address) {
.hdr.nlmsg_type = RTM_NEWADDR,
.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC,
.hdr.nlmsg_seq = seq++,
- .payload.ifa_family = ip_address->family,
- .payload.ifa_prefixlen = ip_address->prefix_len,
+ .payload.ifa_family = prefix->family,
+ .payload.ifa_prefixlen = prefix->len,
.payload.ifa_flags = 0,
.payload.ifa_scope = RT_SCOPE_UNIVERSE,
.payload.ifa_index = interface_id};
/* Set attributes = length/type/value */
- struct rtattr ifa_address = {RTA_LENGTH(ip_address_len(ip_address)),
+ struct rtattr ifa_address = {RTA_LENGTH(ip_prefix_len(prefix)),
IFA_ADDRESS};
struct iovec iov[] = {
{&msg, sizeof(msg)},
{&ifa_address, sizeof(ifa_address)},
- {(void *)&ip_address->buffer, sizeof(ip_address->buffer)},
+ {(void *)&prefix->address.buffer, sizeof(prefix->address.buffer)},
};
msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov));
@@ -966,7 +966,7 @@ ERR_SOCKET:
* ip route del 1:2::2 dev lo table local
*
*/
-int _nl_del_lo_route(const ip_address_t *ip_address) {
+int _nl_del_lo_route(const ip_prefix_t *prefix) {
char buffer[BUFSIZE];
struct nlmsghdr *hdr = (struct nlmsghdr *)buffer;
size_t n;
@@ -979,8 +979,8 @@ int _nl_del_lo_route(const ip_address_t *ip_address) {
.hdr.nlmsg_type = RTM_DELROUTE,
.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
.hdr.nlmsg_seq = seq++,
- .payload.rtm_family = ip_address->family,
- .payload.rtm_dst_len = ip_address->prefix_len,
+ .payload.rtm_family = prefix->family,
+ .payload.rtm_dst_len = prefix->len,
.payload.rtm_src_len = 0,
.payload.rtm_tos = 0,
.payload.rtm_table = RT_TABLE_LOCAL,
@@ -992,13 +992,13 @@ int _nl_del_lo_route(const ip_address_t *ip_address) {
/* Set attribute = length/type/value */
uint32_t one = 1;
- struct rtattr a_dst = {RTA_LENGTH(ip_address_len(ip_address)), RTA_DST};
+ struct rtattr a_dst = {RTA_LENGTH(ip_prefix_len(prefix)), RTA_DST};
struct rtattr a_ifid_lo = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF};
struct iovec iov[] = {
{&msg, sizeof(msg)},
/* Ip address */
{&a_dst, sizeof(a_dst)},
- {(void *)&ip_address->buffer, ip_address_len(ip_address)},
+ {(void *)&prefix->address.buffer, ip_prefix_len(prefix)},
/* Interface id */
{&a_ifid_lo, sizeof(a_ifid_lo)},
{&one, sizeof(one)}};
@@ -1129,7 +1129,7 @@ ERR_SOCKET:
* ip -6 neigh add proxy 1:2::2 dev hicnc-cons-eth0 2>&1 | grep nei
*
*/
-int _nl_add_neigh_proxy(const ip_address_t *ip_address,
+int _nl_add_neigh_proxy(const ip_prefix_t *prefix,
const uint32_t interface_id) {
/* Buffer for holding the response, with appropriate casting on the header */
char buffer[BUFSIZE];
@@ -1147,21 +1147,21 @@ int _nl_add_neigh_proxy(const ip_address_t *ip_address,
.hdr.nlmsg_type = RTM_NEWNEIGH,
.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL,
.hdr.nlmsg_seq = seq++,
- .payload.ndm_family = ip_address->family,
+ .payload.ndm_family = prefix->family,
.payload.ndm_ifindex = interface_id,
.payload.ndm_state = NUD_PERMANENT,
.payload.ndm_flags = NTF_PROXY,
};
/* Message attributes = length/type/value */
- struct rtattr a_dst = {RTA_LENGTH(ip_address_len(ip_address)), NDA_DST};
+ struct rtattr a_dst = {RTA_LENGTH(ip_prefix_len(prefix)), NDA_DST};
/* Iovec describing the packets */
struct iovec iov[] = {
{&msg, sizeof(msg)},
/* Ip address */
{&a_dst, sizeof(a_dst)},
- {(void *)&ip_address->buffer, sizeof(ip_address->buffer)},
+ {(void *)&prefix->address.buffer, sizeof(prefix->address.buffer)},
};
msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov));
@@ -1199,7 +1199,7 @@ ERR:
/* ip -6 route add 0:1::/64 dev hicn-if0 table 100 */
/* ip -6 route add 0:2::/64 dev hicn-if1 table 100 */
-int _nl_add_in_route_table(const ip_address_t *prefix,
+int _nl_add_in_route_table(const ip_prefix_t *prefix,
const uint32_t interface_id,
const uint8_t table_id) {
/* Buffer for holding the response, with appropriate casting on the header */
@@ -1219,7 +1219,7 @@ int _nl_add_in_route_table(const ip_address_t *prefix,
.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL,
.hdr.nlmsg_seq = seq++,
.payload.rtm_family = prefix->family,
- .payload.rtm_dst_len = prefix->prefix_len,
+ .payload.rtm_dst_len = prefix->len,
.payload.rtm_src_len = 0,
.payload.rtm_tos = 0,
.payload.rtm_table = table_id, /* RT_TABLE_MAIN, etc. */
@@ -1231,7 +1231,7 @@ int _nl_add_in_route_table(const ip_address_t *prefix,
};
/* Message attributes = length/type/value */
- struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix)), RTA_DST};
+ struct rtattr a_dst = {RTA_LENGTH(ip_prefix_len(prefix)), RTA_DST};
struct rtattr a_oif = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF};
/* Iovec describing the packets */
@@ -1239,7 +1239,7 @@ int _nl_add_in_route_table(const ip_address_t *prefix,
{&msg, sizeof(msg)},
/* Destination prefix / ip address */
{&a_dst, sizeof(a_dst)},
- {(void *)&prefix->buffer, ip_address_len(prefix)},
+ {(void *)&prefix->address.buffer, ip_prefix_len(prefix)},
/* Output interface */
{&a_oif, sizeof(a_oif)},
{(void *)&interface_id, sizeof(uint32_t)},
@@ -1283,9 +1283,9 @@ ERR:
int _nl_add_in_route_table_s(const char *prefix, const uint32_t interface_id,
const uint8_t table_id) {
int rc;
- ip_address_t ip_address;
+ ip_prefix_t ip_address;
- rc = hicn_ip_pton(prefix, &ip_address);
+ rc = ip_prefix_pton(prefix, &ip_address);
if (rc < 0) {
return rc;
}
@@ -1298,7 +1298,7 @@ int _nl_add_in_route_s(const char *prefix, const uint32_t interface_id) {
}
/* ip -6 rule add from b001::/16 prio 0 table 100 */
-int _nl_add_prio_rule(const ip_address_t *ip_address, uint8_t address_family,
+int _nl_add_prio_rule(const ip_prefix_t *prefix, uint8_t address_family,
const uint32_t priority, const uint8_t table_id) {
/* Buffer for holding the response, with appropriate casting on the header */
char buffer[BUFSIZE];
@@ -1318,7 +1318,7 @@ int _nl_add_prio_rule(const ip_address_t *ip_address, uint8_t address_family,
.hdr.nlmsg_seq = seq++,
.payload.family = address_family,
//.payload.dst_len = ,
- .payload.src_len = ip_address ? ip_address->prefix_len : 0,
+ .payload.src_len = prefix ? prefix->len : 0,
.payload.tos = 0,
.payload.table = table_id,
.payload.action = FR_ACT_TO_TBL,
@@ -1331,17 +1331,17 @@ int _nl_add_prio_rule(const ip_address_t *ip_address, uint8_t address_family,
goto ERR;
}
- if (ip_address) {
+ if (prefix) {
/* Message attributes = length/type/value */
- struct rtattr a_src = {RTA_LENGTH(ip_address_len(ip_address)), FRA_SRC};
+ struct rtattr a_src = {RTA_LENGTH(ip_prefix_len(prefix)), FRA_SRC};
struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY};
/* Iovec describing the packets */
struct iovec iov[] = {
{&msg, sizeof(msg)},
- /* Source prefix / ip_address */
+ /* Source prefix / prefix */
{&a_src, sizeof(a_src)},
- {(void *)&ip_address->buffer, ip_address_len(ip_address)},
+ {(void *)&prefix->address.buffer, ip_prefix_len(prefix)},
/* Priority */
{&a_prio, sizeof(a_prio)},
{(void *)&priority, sizeof(uint32_t)},
@@ -1392,14 +1392,14 @@ ERR:
return HICN_SOCKET_ERROR_UNSPEC;
}
-int _nl_add_lo_prio_rule(const ip_address_t *ip_address, uint8_t address_family,
+int _nl_add_lo_prio_rule(const ip_prefix_t *prefix, uint8_t address_family,
const uint32_t priority) {
- return _nl_add_prio_rule(ip_address, address_family, priority,
+ return _nl_add_prio_rule(prefix, address_family, priority,
RT_TABLE_LOCAL);
}
/* ip -6 rule del from all prio 0 table local */
-int _nl_del_prio_rule(const ip_address_t *ip_address, uint8_t address_family,
+int _nl_del_prio_rule(const ip_prefix_t *prefix, uint8_t address_family,
const uint32_t priority, const uint8_t table_id) {
/* Buffer for holding the response, with appropriate casting on the header */
char buffer[BUFSIZE];
@@ -1419,7 +1419,7 @@ int _nl_del_prio_rule(const ip_address_t *ip_address, uint8_t address_family,
.hdr.nlmsg_seq = seq++,
.payload.family = address_family,
//.payload.dst_len = ,
- .payload.src_len = ip_address ? ip_address->prefix_len : 0,
+ .payload.src_len = prefix ? prefix->len : 0,
.payload.tos = 0,
.payload.table = table_id,
.payload.action = FR_ACT_TO_TBL,
@@ -1433,16 +1433,16 @@ int _nl_del_prio_rule(const ip_address_t *ip_address, uint8_t address_family,
}
/* Message attributes = length/type/value */
- if (ip_address) {
- struct rtattr a_src = {RTA_LENGTH(ip_address_len(ip_address)), FRA_SRC};
+ if (prefix) {
+ struct rtattr a_src = {RTA_LENGTH(ip_prefix_len(prefix)), FRA_SRC};
struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY};
/* Iovec describing the packets */
struct iovec iov[] = {
{&msg, sizeof(msg)},
- /* Source prefix / ip_address */
+ /* Source prefix / prefix */
{&a_src, sizeof(a_src)},
- {(void *)&ip_address->buffer, ip_address_len(ip_address)},
+ {(void *)&prefix->address.buffer, ip_prefix_len(prefix)},
/* Priority */
{&a_prio, sizeof(a_prio)},
{(void *)&priority, sizeof(uint32_t)},
@@ -1495,7 +1495,7 @@ ERR:
return HICN_SOCKET_ERROR_UNSPEC;
}
-int _nl_del_lo_prio_rule(const ip_address_t *ip_address, uint8_t address_family,
+int _nl_del_lo_prio_rule(const ip_prefix_t *ip_address, uint8_t address_family,
const uint32_t priority) {
return _nl_del_prio_rule(ip_address, address_family, priority,
RT_TABLE_LOCAL);
diff --git a/hicn-light/src/hicn/utils/CMakeLists.txt b/hicn-light/src/hicn/utils/CMakeLists.txt
index dd9e12c15..1ab38deba 100644
--- a/hicn-light/src/hicn/utils/CMakeLists.txt
+++ b/hicn-light/src/hicn/utils/CMakeLists.txt
@@ -19,7 +19,6 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/commands.h
${CMAKE_CURRENT_SOURCE_DIR}/interface.h
${CMAKE_CURRENT_SOURCE_DIR}/interfaceSet.h
- ${CMAKE_CURRENT_SOURCE_DIR}/policy.h
${CMAKE_CURRENT_SOURCE_DIR}/punting.h
${CMAKE_CURRENT_SOURCE_DIR}/token.h
${CMAKE_CURRENT_SOURCE_DIR}/utils.h
@@ -30,7 +29,6 @@ list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/addressList.c
${CMAKE_CURRENT_SOURCE_DIR}/interface.c
${CMAKE_CURRENT_SOURCE_DIR}/interfaceSet.c
- ${CMAKE_CURRENT_SOURCE_DIR}/policy.c
${CMAKE_CURRENT_SOURCE_DIR}/punting.c
${CMAKE_CURRENT_SOURCE_DIR}/utils.c
)
diff --git a/hicn-light/src/hicn/utils/commands.h b/hicn-light/src/hicn/utils/commands.h
index 223bbffaa..834da6259 100644
--- a/hicn-light/src/hicn/utils/commands.h
+++ b/hicn-light/src/hicn/utils/commands.h
@@ -31,7 +31,9 @@
#include <stdint.h>
#include <stdlib.h>
-#include <hicn/utils/policy.h>
+#ifdef WITH_POLICY
+#include <hicn/policy.h>
+#endif /* WITH_POLICY */
typedef struct in6_addr ipv6_addr_t;
typedef uint32_t ipv4_addr_t;
@@ -113,9 +115,7 @@ typedef enum { ETHER_MODE, IP_MODE, HICN_MODE } listener_mode;
typedef struct {
char symbolic[16];
-#ifdef __linux__
char interfaceName[16];
-#endif
union commandAddr address;
uint16_t port;
// uint16_t etherType;
@@ -130,6 +130,7 @@ typedef struct {
typedef struct {
char symbolic[16];
+ //char interfaceName[16];
union commandAddr remoteIp;
union commandAddr localIp;
uint16_t remotePort;
@@ -165,6 +166,9 @@ typedef struct {
add_connection_command connectionData;
uint32_t connid;
uint8_t state;
+ uint8_t admin_state;
+ char connectionName[16];
+ char interfaceName[16];
} list_connections_command;
// SIZE=64
@@ -273,6 +277,8 @@ typedef struct {
typedef struct {
union commandAddr address;
+ char listenerName[16];
+ char interfaceName[16];
uint32_t connid;
uint16_t port;
uint8_t addressType;
@@ -300,6 +306,7 @@ typedef struct {
typedef struct {
char symbolicOrConnid[16];
uint8_t admin_state;
+ uint16_t pad16;
} connection_set_admin_state_command;
#ifdef WITH_POLICY
diff --git a/hicn-light/src/hicn/utils/policy.h b/hicn-light/src/hicn/utils/policy.h
deleted file mode 100644
index 993fdca44..000000000
--- a/hicn-light/src/hicn/utils/policy.h
+++ /dev/null
@@ -1,232 +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 policy.h
- * \brief Policy description
- */
-#ifndef HICN_POLICY_H
-#define HICN_POLICY_H
-
-#include <netinet/in.h> // INET*_ADDRSTRLEN
-#include <string.h> // strcasecmp
-#include "token.h"
-
-/* 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 MAXSZ_POLICY_TAG_ 11
-#define MAXSZ_POLICY_TAG MAXSZ_POLICY_TAG_ + 1
-
-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)
-{
-#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;
-}
-
-/* POLICY_TAGS */
-
-typedef int policy_tags_t;
-
-static inline
-void policy_tags_add(policy_tags_t * tags, policy_tag_t tag)
-{
- *tags |= (1 << tag);
-}
-
-static inline
-void policy_tags_remove(policy_tags_t * tags, policy_tag_t tag)
-{
- *tags &= ~(1 << tag);
-}
-
-static inline
-int policy_tags_has(policy_tags_t tags, policy_tag_t tag)
-{
- return tags & (1 << tag);
-}
-
-#define POLICY_TAGS_EMPTY 0
-
-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
-#undef _
- s[POLICY_TAG_N] = '\0';
- return POLICY_TAG_N + 1;
-}
-
-#define MAXSZ_POLICY_TAGS_ POLICY_TAG_N
-#define MAXSZ_POLICY_TAGS MAXSZ_POLICY_TAGS_ + 1
-
-/* 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
-
-extern const char * policy_state_str[];
-
-
-/* POLICY TAG STATE */
-
-typedef struct {
- 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);
-
-
-/* INTERFACE STATS */
-
-typedef struct {
- float throughput;
- float latency;
- float loss_rate;
-} interface_stats_t;
-
-#define INTERFACE_STATS_NONE { \
- .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;
-} policy_stats_t;
-
-#define POLICY_STATS_NONE { \
- .wired = INTERFACE_STATS_NONE, \
- .wifi = INTERFACE_STATS_NONE, \
- .cellular = INTERFACE_STATS_NONE, \
- .all = INTERFACE_STATS_NONE, \
-}
-
-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, \
-}
-
-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, \
-}
-
-/* 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;
-} policy_t;
-
-static const policy_t POLICY_NONE = {
- .app_name = { 0 },
- .tags = {
-#define _(x, y) [POLICY_TAG_ ## x] = { POLICY_STATE_NEUTRAL, 0 },
-foreach_policy_tag
-#undef _
- },
- .stats = POLICY_STATS_NONE,
-};
-
-
-/* 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];
- };
- policy_t policy;
-} policy_description_t;
-
-#endif /* HICN_POLICY_H */
diff --git a/hicn-plugin/CMakeLists.txt b/hicn-plugin/CMakeLists.txt
index ab4c8f648..8425a5cf3 100644
--- a/hicn-plugin/CMakeLists.txt
+++ b/hicn-plugin/CMakeLists.txt
@@ -55,25 +55,31 @@ set(LIBHICN_FILES
)
set(LIBHICN_HEADER_FILES_SRC
- ../lib/src/hicn.h
- ../lib/src/base.h
- ../lib/src/common.h
- ../lib/src/error.h
- ../lib/src/header.h
- ../lib/src/name.h
- ../lib/src/protocol.h
- ../lib/src/ops.h
- ../lib/src/mapme.h
+ ../lib/includes/hicn/hicn.h
+ ../lib/includes/hicn/base.h
+ ../lib/includes/hicn/common.h
+ ../lib/includes/hicn/error.h
+ ../lib/includes/hicn/header.h
+ ../lib/includes/hicn/name.h
+ ../lib/includes/hicn/protocol.h
+ ../lib/includes/hicn/ops.h
+ ../lib/includes/hicn/mapme.h
)
set(LIBHICN_HEADER_FILES_PROTOCOL
- ../lib/src/protocol/ah.h
- ../lib/src/protocol/icmp.h
- ../lib/src/protocol/icmprd.h
- ../lib/src/protocol/ipv4.h
- ../lib/src/protocol/ipv6.h
- ../lib/src/protocol/tcp.h
- ../lib/src/protocol/udp.h
+ ../lib/includes/hicn/protocol/ah.h
+ ../lib/includes/hicn/protocol/icmp.h
+ ../lib/includes/hicn/protocol/icmprd.h
+ ../lib/includes/hicn/protocol/ipv4.h
+ ../lib/includes/hicn/protocol/ipv6.h
+ ../lib/includes/hicn/protocol/tcp.h
+ ../lib/includes/hicn/protocol/udp.h
+)
+
+set(LIBHICN_HEADER_FILES_UTIL
+ ../lib/includes/hicn/util/ip_address.h
+ ../lib/includes/hicn/util/token.h
+ ../lib/includes/hicn/util/types.h
)
set(HICN_PLUGIN_SOURCE_FILES
@@ -189,6 +195,9 @@ set(HICN_VAPI_GENERATED_FILES
${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.vapi.h
${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.vapi.hpp)
+set(HICN_VPP_STARTUP_CONF_FILE
+ ${CMAKE_BINARY_DIR}/startup.conf)
+
if (NOT VPP_HOME)
set(VPP_HOME /usr)
endif()
@@ -259,6 +268,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins)
file(COPY ${LIBHICN_HEADER_FILES_SRC} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/hicn)
file(COPY ${LIBHICN_HEADER_FILES_PROTOCOL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/hicn/protocol)
+file(COPY ${LIBHICN_HEADER_FILES_UTIL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/hicn/util)
add_library(hicn_api_test_plugin SHARED
${HICN_API_TEST_SOURCE_FILES}
@@ -266,6 +276,7 @@ add_library(hicn_api_test_plugin SHARED
set(VPP_INSTALL_PLUGIN ${HICN_INSTALL_PREFIX}/vpp_plugins)
set(VPP_INSTALL_API_TEST_PLUGIN ${HICN_INSTALL_PREFIX}/vpp_api_test_plugins CACHE STRING "vpp_install_api_test_plugin")
+set(VPP_STARTUP_CONF /etc/vpp/)
set_target_properties(hicn_plugin
PROPERTIES
diff --git a/hicn-plugin/README.md b/hicn-plugin/README.md
index 5da8d6a5b..664b9a446 100644
--- a/hicn-plugin/README.md
+++ b/hicn-plugin/README.md
@@ -186,7 +186,7 @@ vpp# hicn ?
```
hicn control param { pit { size <entries> | { dfltlife | minlife | maxlife } <seconds> } | cs {size <entries> | app <portion to reserved to app>} }
- <entries> :set the maximum number of entry in the PIT or CS. Default for PIT is 131072, for CS is 4096.
+ <entries> :set the maximum number of entry in the PIT or CS. Default for PIT is 131072, for CS is 4096. CS size cannot be grater than PIT size. Moreover CS size must be smaller than (# of vlib buffer - 8196).
<seconds> :set the default, maximum or minimum lifetime of pit entries. Default value 2s (default), 0.2s (minumum), 20s (maximum)
<portion to reserved to app> :set the portion of CS to reserve to application running locally on the forwarder. Default is 30% of the cs size.
```
diff --git a/hicn-plugin/cmake/Modules/Packaging.cmake b/hicn-plugin/cmake/Modules/Packaging.cmake
index 8cace744b..61453d6fd 100644
--- a/hicn-plugin/cmake/Modules/Packaging.cmake
+++ b/hicn-plugin/cmake/Modules/Packaging.cmake
@@ -29,3 +29,18 @@ set(${HICN_PLUGIN}_RPM_DEPENDENCIES
"vpp >= stable_version-release, vpp < next_version-release, vpp-plugins >= stable_version-release, vpp-plugins < next_version-release"
CACHE STRING "Dependencies for deb/rpm package."
)
+
+set(${HICN_PLUGIN}_DEB_PACKAGE_CONTROL_EXTRA
+ "${CMAKE_CURRENT_SOURCE_DIR}/scripts/postinst"
+ CACHE STRING "Control scripts conffiles, postinst, postrm, prerm."
+)
+
+set(${HICN_PLUGIN}_RPM_POST_INSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_SOURCE_DIR}/scripts/post"
+ CACHE STRING "Install script that will be copied in the %post section"
+)
+
+set(${HICN_PLUGIN}_RPM_POST_UNINSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_SOURCE_DIR}/scripts/postun"
+ CACHE STRING "Uninstall script that will be copied in the %postun section"
+) \ No newline at end of file
diff --git a/hicn-plugin/scripts/post b/hicn-plugin/scripts/post
new file mode 100644
index 000000000..dd0a9fbf5
--- /dev/null
+++ b/hicn-plugin/scripts/post
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+if [ -e /etc/vpp/startup.conf ]; then
+ RESULTS=$(sed -n '/hicn[ ]*{/p' /etc/vpp/startup.conf | wc -l)
+ if [[ $RESULTS = 0 ]]; then
+ printf '\n hicn {
+ ## Set PIT size. Default is 131 072 entries
+ # pit-size 500000
+ #
+ ## Set CS size. Default is 4096
+ # cs-size 50000
+ #
+ ## Set maximum PIT entries lifetime in milliseconds. Assigned to a PIT entry in case an interest carries a bigger lifetime
+ # pit-lifetime-max 20
+ #
+ ## Percentage of CS to reserve for application producer faces
+ # cs-reserved-app 20\n}' >> /etc/vpp/startup.conf
+ fi;
+fi;
+ln -s /usr/lib64/vpp_plugins/hicn_plugin.so /usr/lib/vpp_plugins/hicn_plugin.so \ No newline at end of file
diff --git a/hicn-plugin/scripts/postinst b/hicn-plugin/scripts/postinst
new file mode 100644
index 000000000..d6d48509c
--- /dev/null
+++ b/hicn-plugin/scripts/postinst
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+if [ -e /etc/vpp/startup.conf ]; then
+ RESULTS=$(sed -n '/hicn[ ]*{/p' /etc/vpp/startup.conf | wc -l)
+ if [[ $RESULTS = 0 ]]; then
+ printf '\n hicn {
+ ## Set PIT size. Default is 131 072 entries
+ # pit-size 500000
+ #
+ ## Set CS size. Default is 4096
+ # cs-size 50000
+ #
+ ## Set maximum PIT entries lifetime in milliseconds. Assigned to a PIT entry in case an interest carries a bigger lifetime
+ # pit-lifetime-max 20
+ #
+ ## Percentage of CS to reserve for application producer faces
+ # cs-reserved-app 20\n}' >> /etc/vpp/startup.conf
+ fi;
+fi; \ No newline at end of file
diff --git a/hicn-plugin/scripts/postun b/hicn-plugin/scripts/postun
new file mode 100644
index 000000000..c319f014e
--- /dev/null
+++ b/hicn-plugin/scripts/postun
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+if [ -L /usr/lib/vpp_plugins/hicn_plugin.so ]; then
+ rm /usr/lib/vpp_plugins/hicn_plugin.so
+fi; \ No newline at end of file
diff --git a/hicn-plugin/src/cli.c b/hicn-plugin/src/cli.c
index 8af56dcba..bd789acad 100644
--- a/hicn-plugin/src/cli.c
+++ b/hicn-plugin/src/cli.c
@@ -40,8 +40,6 @@ extern ip_version_t ipv6;
static vl_api_hicn_api_node_params_set_t node_ctl_params = {
.pit_max_size = -1,
- .pit_dflt_lifetime_sec = -1.0f,
- .pit_min_lifetime_sec = -1.0f,
.pit_max_lifetime_sec = -1.0f,
.cs_max_size = -1,
.cs_reserved_app = -1,
@@ -85,12 +83,7 @@ hicn_cli_node_ctl_start_set_command_fn (vlib_main_t * vm,
ret = hicn_infra_plugin_enable_disable (1 /* enable */ ,
node_ctl_params.pit_max_size,
- node_ctl_params.
- pit_dflt_lifetime_sec,
- node_ctl_params.
- pit_min_lifetime_sec,
- node_ctl_params.
- pit_max_lifetime_sec,
+ node_ctl_params.pit_max_lifetime_sec,
node_ctl_params.cs_max_size,
node_ctl_params.cs_reserved_app);
@@ -133,12 +126,7 @@ hicn_cli_node_ctl_stop_set_command_fn (vlib_main_t * vm,
}
ret = hicn_infra_plugin_enable_disable (0 /* !enable */ ,
node_ctl_params.pit_max_size,
- node_ctl_params.
- pit_dflt_lifetime_sec,
- node_ctl_params.
- pit_min_lifetime_sec,
- node_ctl_params.
- pit_max_lifetime_sec,
+ node_ctl_params.pit_max_lifetime_sec,
node_ctl_params.cs_max_size,
node_ctl_params.cs_reserved_app);
@@ -197,28 +185,6 @@ hicn_cli_node_ctl_param_set_command_fn (vlib_main_t * vm,
}
node_ctl_params.pit_max_size = table_size;
}
- else if (unformat (line_input, "dfltlife %f", &lifetime))
- {
- if (!DFLTD_RANGE_OK
- (lifetime, HICN_PARAM_PIT_LIFETIME_BOUND_MIN_SEC,
- HICN_PARAM_PIT_LIFETIME_BOUND_MAX_SEC))
- {
- rv = HICN_ERROR_PIT_CONFIG_DFTLT_OOB;
- break;
- }
- node_ctl_params.pit_dflt_lifetime_sec = lifetime;
- }
- else if (unformat (line_input, "minlife %f", &lifetime))
- {
- if (!DFLTD_RANGE_OK
- (lifetime, HICN_PARAM_PIT_LIFETIME_BOUND_MIN_SEC,
- HICN_PARAM_PIT_LIFETIME_BOUND_MAX_SEC))
- {
- rv = HICN_ERROR_PIT_CONFIG_MINLT_OOB;
- break;
- }
- node_ctl_params.pit_min_lifetime_sec = lifetime;
- }
else if (unformat (line_input, "maxlife %f", &lifetime))
{
if (!DFLTD_RANGE_OK
@@ -332,8 +298,6 @@ hicn_cli_show_command_fn (vlib_main_t * vm, unformat_input_t * main_input,
if (!hicn_main.is_enabled)
{
if (node_ctl_params.pit_max_size == -1 &&
- node_ctl_params.pit_dflt_lifetime_sec == -1 &&
- node_ctl_params.pit_min_lifetime_sec == -1 &&
node_ctl_params.pit_max_lifetime_sec == -1 &&
node_ctl_params.cs_max_size == -1 &&
node_ctl_params.cs_reserved_app == -1)
@@ -349,16 +313,6 @@ hicn_cli_show_command_fn (vlib_main_t * vm, unformat_input_t * main_input,
vlib_cli_output (vm, " PIT:: max entries:%d\n",
node_ctl_params.pit_max_size);
}
- if (node_ctl_params.pit_dflt_lifetime_sec != -1)
- {
- vlib_cli_output (vm, " PIT:: dflt lifetime: %05.3f seconds\n",
- node_ctl_params.pit_dflt_lifetime_sec);
- }
- if (node_ctl_params.pit_min_lifetime_sec != -1)
- {
- vlib_cli_output (vm, " PIT:: min lifetime: %05.3f seconds\n",
- node_ctl_params.pit_min_lifetime_sec);
- }
if (node_ctl_params.pit_max_lifetime_sec != -1)
{
vlib_cli_output (vm, " PIT:: max lifetime: %05.3f seconds\n",
@@ -380,12 +334,10 @@ hicn_cli_show_command_fn (vlib_main_t * vm, unformat_input_t * main_input,
vlib_cli_output (vm,
"Forwarder: %sabled\n"
" PIT:: max entries:%d,"
- " lifetime default: %05.3f sec (min:%05.3f, max:%05.3f)\n"
+ " lifetime default: max:%05.3f\n"
" CS:: max entries:%d, network entries:%d, app entries:%d (allocated %d, free %d)\n",
hicn_main.is_enabled ? "en" : "dis",
hicn_infra_pit_size,
- ((f64) hicn_main.pit_lifetime_dflt_ms) / SEC_MS,
- ((f64) hicn_main.pit_lifetime_min_ms) / SEC_MS,
((f64) hicn_main.pit_lifetime_max_ms) / SEC_MS,
hicn_infra_cs_size,
hicn_infra_cs_size - hicn_main.pitcs.pcs_app_max,
@@ -445,7 +397,7 @@ done:
"Bucke count %d, Overflow buckets count %d, used %d\n",
hicn_main.pitcs.pcs_table->ht_bucket_count,
hicn_main.pitcs.pcs_table->ht_overflow_bucket_count,
- hicn_main.pitcs.pcs_table->ht_overflow_buckets_used);
+ hicn_main.pitcs.pcs_table->ht_overflow_buckets_used);
}
return (ret == HICN_ERROR_NONE) ? 0 : clib_error_return (0, "%s\n",
@@ -823,8 +775,8 @@ hicn_cli_pgen_client_set_command_fn (vlib_main_t * vm,
{
/* Add data node to the vpp graph */
u32 next_hit_node = vlib_node_add_next (vm,
- hicn_punt_glb.hicn_node_info.
- ip4_inacl_node_index,
+ hicn_punt_glb.
+ hicn_node_info.ip4_inacl_node_index,
hicn_pg_data_node.index);
/* Add pgen_client node to the vpp graph */
@@ -861,8 +813,8 @@ hicn_cli_pgen_client_set_command_fn (vlib_main_t * vm,
{
/* Add node to the vpp graph */
u32 next_hit_node = vlib_node_add_next (vm,
- hicn_punt_glb.
- hicn_node_info.ip6_inacl_node_index,
+ hicn_punt_glb.hicn_node_info.
+ ip6_inacl_node_index,
hicn_pg_data_node.index);
/* Add pgen_client node to the vpp graph */
@@ -1032,8 +984,8 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t * vm,
{
/* Add node to the vpp graph */
u32 next_hit_node = vlib_node_add_next (vm,
- hicn_punt_glb.hicn_node_info.
- ip4_inacl_node_index,
+ hicn_punt_glb.
+ hicn_node_info.ip4_inacl_node_index,
hicn_pg_server_node.index);
/* Create the punting table if it does not exist */
@@ -1059,8 +1011,8 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t * vm,
{
/* Add node to the vpp graph */
u32 next_hit_node = vlib_node_add_next (vm,
- hicn_punt_glb.
- hicn_node_info.ip6_inacl_node_index,
+ hicn_punt_glb.hicn_node_info.
+ ip6_inacl_node_index,
hicn_pg_server_node.index);
/* Create the punting table if it does not exist */
diff --git a/hicn-plugin/src/data_fwd_node.c b/hicn-plugin/src/data_fwd_node.c
index 53308a49d..ca3baaa0d 100644
--- a/hicn-plugin/src/data_fwd_node.c
+++ b/hicn-plugin/src/data_fwd_node.c
@@ -176,6 +176,7 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
hicn_pcs_delete (pitcs, &pitp, &node0, vm, hash_entry0,
dpo_vft0, &hicn_dpo_id0);
+#if HICN_FEATURE_CS
if (hicnb0->flags & HICN_BUFFER_FLAGS_FACE_IS_APP)
{
push_in_cache (vm, bi0, &n_left_to_next, &next0, &to_next,
@@ -186,6 +187,10 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next,
&next_index, node);
}
+#else
+ drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next,
+ &next_index, node);
+#endif
stats.pit_expired_count++;
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
diff --git a/hicn-plugin/src/data_pcslookup_node.c b/hicn-plugin/src/data_pcslookup_node.c
index aeb8c2276..fdf855e57 100644
--- a/hicn-plugin/src/data_pcslookup_node.c
+++ b/hicn-plugin/src/data_pcslookup_node.c
@@ -102,27 +102,17 @@ hicn_data_pcslookup_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
b0 = vlib_get_buffer (vm, bi0);
hb0 = hicn_get_buffer (b0);
+ next0 = HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP;
/* Incr packet counter */
stats.pkts_processed += 1;
ret0 = hicn_data_parse_pkt (b0, &name, &namelen, &hicn0, &isv6);
-
- if (PREDICT_TRUE (ret0 == HICN_ERROR_NONE))
- {
- next0 =
- isv6 ? HICN_DATA_PCSLOOKUP_NEXT_V6_LOOKUP :
- HICN_DATA_PCSLOOKUP_NEXT_V4_LOOKUP;
- }
nameptr = (u8 *) (&name);
- if (PREDICT_FALSE
- (ret0 != HICN_ERROR_NONE
- || hicn_hashtb_fullhash (nameptr, namelen,
- &name_hash) != HICN_ERROR_NONE))
- {
- next0 = HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP;
- }
- else
+
+ if (PREDICT_TRUE (ret0 == HICN_ERROR_NONE &&
+ hicn_hashtb_fullhash (nameptr, namelen,
+ &name_hash) == HICN_ERROR_NONE))
{
int res =
hicn_hashtb_lookup_node (rt->pitcs->pcs_table, nameptr,
@@ -137,9 +127,10 @@ hicn_data_pcslookup_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
stats.pkts_data_count += 1;
+#if HICN_FEATURE_CS
if ((res == HICN_ERROR_HASHTB_HASH_NOT_FOUND
|| (res == HICN_ERROR_NONE && is_cs0))
- && (hb0->flags & HICN_BUFFER_FLAGS_FACE_IS_APP))
+ && ((hb0->flags & HICN_BUFFER_FLAGS_FACE_IS_APP)))
{
next0 = HICN_DATA_PCSLOOKUP_NEXT_STORE_DATA;
}
@@ -153,6 +144,18 @@ hicn_data_pcslookup_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
next0 = HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD + is_cs0;
}
}
+#else
+ if (res == HICN_ERROR_NONE)
+ {
+ /*
+ * In case the result of the lookup
+ * is a CS entry, the packet is
+ * dropped
+ */
+ next0 = HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD + is_cs0;
+ }
+ }
+#endif
hicn_store_internal_state (b0, name_hash, node_id0, dpo_ctx_id0,
vft_id0, hash_entry_id, bucket_id,
diff --git a/hicn-plugin/src/hicn.api b/hicn-plugin/src/hicn.api
index d344061ba..da14a9faf 100644
--- a/hicn-plugin/src/hicn.api
+++ b/hicn-plugin/src/hicn.api
@@ -33,12 +33,6 @@ define hicn_api_node_params_set
/* Portion of CS reserved to application, otherwise -1 to assign default value */
i32 cs_reserved_app;
- /* Default PIT entry lifetime, otherwise -1 to assign default value */
- f64 pit_dflt_lifetime_sec;
-
- /* Lower bound on PIT entry lifetime, otherwise -1 to assign default value */
- f64 pit_min_lifetime_sec;
-
/* Upper bound on PIT entry lifetime, otherwise -1 to assign default value */
f64 pit_max_lifetime_sec;
};
@@ -84,12 +78,6 @@ define hicn_api_node_params_get_reply
/* CS maximum size, otherwise -1 to assign default value */
u32 cs_max_size;
- /* Default PIT entry lifetime */
- f64 pit_dflt_lifetime_sec;
-
- /* Lower bound on PIT entry lifetime */
- f64 pit_min_lifetime_sec;
-
/* Upper bound on PIT entry lifetime */
f64 pit_max_lifetime_sec;
};
diff --git a/hicn-plugin/src/hicn.c b/hicn-plugin/src/hicn.c
index a7b04de74..a30eac4ff 100644
--- a/hicn-plugin/src/hicn.c
+++ b/hicn-plugin/src/hicn.c
@@ -15,6 +15,7 @@
#include <vnet/vnet.h>
#include <vnet/plugin/plugin.h>
+#include <vlib/vlib.h>
#include "hicn.h"
#include "params.h"
@@ -84,8 +85,6 @@ done:
int
hicn_infra_plugin_enable_disable (int enable_disable,
int pit_size_req,
- f64 pit_dflt_lifetime_sec_req,
- f64 pit_min_lifetime_sec_req,
f64 pit_max_lifetime_sec_req,
int cs_size_req, int cs_reserved_app)
{
@@ -103,21 +102,6 @@ hicn_infra_plugin_enable_disable (int enable_disable,
/* Set up params and call fwdr_init set up PIT/CS, forwarder nodes */
/* Check the range and assign some globals */
- if (pit_min_lifetime_sec_req < 0)
- {
- sm->pit_lifetime_min_ms = HICN_PARAM_PIT_LIFETIME_DFLT_MIN_MS;
- }
- else
- {
- if (pit_min_lifetime_sec_req < HICN_PARAM_PIT_LIFETIME_BOUND_MIN_SEC ||
- pit_min_lifetime_sec_req > HICN_PARAM_PIT_LIFETIME_BOUND_MAX_SEC)
- {
- ret = HICN_ERROR_PIT_CONFIG_MINLT_OOB;
- goto done;
- }
- sm->pit_lifetime_min_ms = pit_min_lifetime_sec_req * SEC_MS;
- }
-
if (pit_max_lifetime_sec_req < 0)
{
sm->pit_lifetime_max_ms = HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS;
@@ -132,25 +116,7 @@ hicn_infra_plugin_enable_disable (int enable_disable,
}
sm->pit_lifetime_max_ms = pit_max_lifetime_sec_req * SEC_MS;
}
- if (sm->pit_lifetime_min_ms > sm->pit_lifetime_max_ms)
- {
- ret = HICN_ERROR_PIT_CONFIG_MINMAXLT;
- goto done;
- }
- if (pit_dflt_lifetime_sec_req < 0)
- {
- sm->pit_lifetime_dflt_ms = HICN_PARAM_PIT_LIFETIME_DFLT_DFLT_MS;
- }
- else
- {
- sm->pit_lifetime_dflt_ms = pit_dflt_lifetime_sec_req * SEC_MS;
- }
- if (sm->pit_lifetime_dflt_ms < sm->pit_lifetime_min_ms ||
- sm->pit_lifetime_dflt_ms > sm->pit_lifetime_max_ms)
- {
- ret = HICN_ERROR_PIT_CONFIG_DFTLT_OOB;
- goto done;
- }
+
if (pit_size_req < 0)
{
pit_size = HICN_PARAM_PIT_ENTRIES_DFLT;
@@ -172,10 +138,32 @@ hicn_infra_plugin_enable_disable (int enable_disable,
}
else
{
- if (cs_size_req > HICN_PARAM_CS_ENTRIES_MAX)
+ /*
+ * This should be relatively safe
+ * At this point vlib buffers should have been already allocated
+ */
+
+ vlib_buffer_main_t *bm;
+ vlib_buffer_pool_t *bp;
+ vlib_main_t *vm = vlib_get_main ();
+ bm = vm->buffer_main;
+
+ u32 n_buffers = 0;
+ vec_foreach (bp, bm->buffer_pools)
+ n_buffers = n_buffers < bp->n_buffers ? bp->n_buffers : n_buffers;
+
+ // check if CS is bugger tha PIT or bigger than the available vlib_buffers
+ uword cs_buffers =
+ (n_buffers >
+ HICN_PARAM_CS_MIN_MBUF) ? n_buffers - HICN_PARAM_CS_MIN_MBUF : 0;
+
+ if (cs_size_req > (pit_size_req / 2) || cs_size_req > cs_buffers)
{
- ret = HICN_ERROR_CS_CONFIG_SIZE_OOB;
- goto done;
+ cs_size_req =
+ ((pit_size_req / 2) > cs_buffers) ? cs_buffers : pit_size_req / 2;
+ vlib_cli_output (vm,
+ "WARNING!! CS too large. Please check size of PIT or the number of buffers available in VPP\n");
+
}
cs_size = (uint32_t) cs_size_req;
}
@@ -208,6 +196,42 @@ done:
return (ret);
}
+static clib_error_t *
+hicn_configure (vlib_main_t * vm, unformat_input_t * input)
+{
+ u32 pit_size = HICN_PARAM_PIT_ENTRIES_DFLT;
+ u32 cs_size = HICN_PARAM_CS_ENTRIES_DFLT;
+ u64 pit_lifetime_max_sec = HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS / SEC_MS;
+ int cs_reserved = HICN_PARAM_CS_RESERVED_APP;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "pit-size %u", &pit_size))
+ ;
+ else if (unformat (input, "cs-size %u", &cs_size))
+ ;
+ else if (unformat (input, "pit-lifetime-max %u", &pit_lifetime_max_sec))
+ ;
+ else if (unformat (input, "cs-reserved-app %u", &cs_reserved))
+ ;
+ else
+ break;
+// clib_error_return (0,
+// "hICN parameter unknown");
+ }
+
+ unformat_free (input);
+
+ hicn_infra_plugin_enable_disable (1, pit_size,
+ pit_lifetime_max_sec,
+ cs_size, cs_reserved);
+
+
+ return 0;
+}
+
+VLIB_CONFIG_FUNCTION (hicn_configure, "hicn");
+
/*
* Init entry-point for the icn plugin
*/
diff --git a/hicn-plugin/src/hicn_api.c b/hicn-plugin/src/hicn_api.c
index 42c7a804a..f8933206d 100644
--- a/hicn-plugin/src/hicn_api.c
+++ b/hicn-plugin/src/hicn_api.c
@@ -112,20 +112,10 @@ vl_api_hicn_api_node_params_set_t_handler (vl_api_hicn_api_node_params_set_t *
pit_max_size =
pit_max_size == -1 ? HICN_PARAM_PIT_ENTRIES_DFLT : pit_max_size;
- f64 pit_dflt_lifetime_sec = mp->pit_dflt_lifetime_sec;
- pit_dflt_lifetime_sec =
- pit_dflt_lifetime_sec ==
- -1 ? HICN_PARAM_PIT_LIFETIME_DFLT_DFLT_MS : pit_dflt_lifetime_sec;
-
- f64 pit_min_lifetime_sec = mp->pit_min_lifetime_sec;
- pit_min_lifetime_sec =
- pit_min_lifetime_sec ==
- -1 ? HICN_PARAM_PIT_LIFETIME_DFLT_MIN_MS : pit_min_lifetime_sec;
-
f64 pit_max_lifetime_sec = mp->pit_max_lifetime_sec;
pit_max_lifetime_sec =
pit_max_lifetime_sec ==
- -1 ? HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS : pit_max_lifetime_sec;
+ -1 ? HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS / SEC_MS : pit_max_lifetime_sec;
int cs_max_size = clib_net_to_host_i32 (mp->cs_max_size);
cs_max_size = cs_max_size == -1 ? HICN_PARAM_CS_ENTRIES_DFLT : cs_max_size;
@@ -136,8 +126,6 @@ vl_api_hicn_api_node_params_set_t_handler (vl_api_hicn_api_node_params_set_t *
rv = hicn_infra_plugin_enable_disable ((int) (mp->enable_disable),
pit_max_size,
- pit_dflt_lifetime_sec,
- pit_min_lifetime_sec,
pit_max_lifetime_sec,
cs_max_size, cs_reserved_app);
@@ -159,8 +147,6 @@ vl_api_hicn_api_node_params_get_t_handler (vl_api_hicn_api_node_params_get_t *
rmp->is_enabled = sm->is_enabled;
rmp->feature_cs = HICN_FEATURE_CS;
rmp->pit_max_size = clib_host_to_net_u32 (hicn_infra_pit_size);
- rmp->pit_dflt_lifetime_sec = ((f64) sm->pit_lifetime_dflt_ms) / SEC_MS;
- rmp->pit_min_lifetime_sec = ((f64) sm->pit_lifetime_min_ms) / SEC_MS;
rmp->pit_max_lifetime_sec = ((f64) sm->pit_lifetime_max_ms) / SEC_MS;
rmp->cs_max_size = clib_host_to_net_u32 (hicn_infra_cs_size);
rmp->retval = clib_host_to_net_i32 (rv);
@@ -491,18 +477,17 @@ static void vl_api_hicn_api_route_get_t_handler
static void
send_route_details (vl_api_registration_t * reg,
- const fib_prefix_t *pfx, u32 context)
+ const fib_prefix_t * pfx, u32 context)
{
vl_api_hicn_api_routes_details_t *mp;
hicn_main_t *hm = &hicn_main;
mp = vl_msg_api_alloc (sizeof (*mp));
memset (mp, 0, sizeof (*mp));
- mp->_vl_msg_id =
- htons (VL_API_HICN_API_ROUTES_DETAILS + hm->msg_id_base);
+ mp->_vl_msg_id = htons (VL_API_HICN_API_ROUTES_DETAILS + hm->msg_id_base);
mp->context = context;
- clib_memcpy(&mp->prefix, &pfx->fp_addr, sizeof(ip46_address_t));
+ clib_memcpy (&mp->prefix, &pfx->fp_addr, sizeof (ip46_address_t));
mp->len = pfx->fp_len;
mp->nfaces = 0;
@@ -511,21 +496,25 @@ send_route_details (vl_api_registration_t * reg,
hicn_dpo_ctx_t *hicn_dpo_ctx;
u32 fib_index;
- int rv = hicn_route_get_dpo (&pfx->fp_addr, pfx->fp_len, &hicn_dpo_id, &fib_index);
+ int rv =
+ hicn_route_get_dpo (&pfx->fp_addr, pfx->fp_len, &hicn_dpo_id, &fib_index);
if (rv == HICN_ERROR_NONE)
{
- hicn_dpo_vft = hicn_dpo_get_vft(hicn_dpo_id->dpoi_type);
- hicn_dpo_ctx = hicn_dpo_vft->hicn_dpo_get_ctx(hicn_dpo_id->dpoi_index);
+ hicn_dpo_vft = hicn_dpo_get_vft (hicn_dpo_id->dpoi_type);
+ hicn_dpo_ctx = hicn_dpo_vft->hicn_dpo_get_ctx (hicn_dpo_id->dpoi_index);
for (int i = 0; i < hicn_dpo_ctx->entry_count; i++)
- {
- if (dpo_id_is_valid(&hicn_dpo_ctx->next_hops[i]))
- {
- mp->faceids[i] = clib_host_to_net_u32(((dpo_id_t *) &hicn_dpo_ctx->next_hops[i])->dpoi_index);
- mp->nfaces++;
- }
- }
- mp->strategy_id = clib_host_to_net_u32(hicn_dpo_get_vft_id(hicn_dpo_id));
+ {
+ if (dpo_id_is_valid (&hicn_dpo_ctx->next_hops[i]))
+ {
+ mp->faceids[i] =
+ clib_host_to_net_u32 (((dpo_id_t *) & hicn_dpo_ctx->
+ next_hops[i])->dpoi_index);
+ mp->nfaces++;
+ }
+ }
+ mp->strategy_id =
+ clib_host_to_net_u32 (hicn_dpo_get_vft_id (hicn_dpo_id));
}
vl_api_send_msg (reg, (u8 *) mp);
@@ -537,41 +526,40 @@ typedef struct vl_api_hicn_api_route_dump_walk_ctx_t_
} vl_api_hicn_api_route_dump_walk_ctx_t;
static fib_table_walk_rc_t
-vl_api_hicn_api_route_dump_walk(fib_node_index_t fei, void *arg)
+vl_api_hicn_api_route_dump_walk (fib_node_index_t fei, void *arg)
{
vl_api_hicn_api_route_dump_walk_ctx_t *ctx = arg;
int found = 0;
const dpo_id_t *former_dpo_id;
/* Route already existing. We need to update the dpo. */
- const dpo_id_t * load_balance_dpo_id =
+ const dpo_id_t *load_balance_dpo_id =
fib_entry_contribute_ip_forwarding (fei);
/* The dpo is not a load balance dpo as expected */
if (load_balance_dpo_id->dpoi_type == DPO_LOAD_BALANCE)
{
/* former_dpo_id is a load_balance dpo */
- load_balance_t *lb =
- load_balance_get (load_balance_dpo_id->dpoi_index);
+ load_balance_t *lb = load_balance_get (load_balance_dpo_id->dpoi_index);
/* FIB entry exists but there is no hicn dpo. */
for (int i = 0; i < lb->lb_n_buckets && !found; i++)
- {
- former_dpo_id = load_balance_get_bucket_i (lb, i);
-
- if (dpo_is_hicn (former_dpo_id))
- {
- vec_add1 (ctx->feis, fei);
- }
- }
+ {
+ former_dpo_id = load_balance_get_bucket_i (lb, i);
+
+ if (dpo_is_hicn (former_dpo_id))
+ {
+ vec_add1 (ctx->feis, fei);
+ }
+ }
}
return (FIB_TABLE_WALK_CONTINUE);
}
static void
-vl_api_hicn_api_routes_dump_t_handler
-(vl_api_hicn_api_face_stats_dump_t * mp)
+ vl_api_hicn_api_routes_dump_t_handler
+ (vl_api_hicn_api_face_stats_dump_t * mp)
{
vl_api_registration_t *reg;
fib_table_t *fib_table;
@@ -580,34 +568,34 @@ vl_api_hicn_api_routes_dump_t_handler
fib_node_index_t *lfeip;
const fib_prefix_t *pfx;
vl_api_hicn_api_route_dump_walk_ctx_t ctx = {
- .feis = NULL,
+ .feis = NULL,
};
reg = vl_api_client_index_to_registration (mp->client_index);
if (!reg)
return;
- pool_foreach (fib_table, im->fibs,
- ({
- fib_table_walk(fib_table->ft_index,
- FIB_PROTOCOL_IP4,
- vl_api_hicn_api_route_dump_walk,
- &ctx);
- }));
-
- pool_foreach (fib_table, im6->fibs,
- ({
- fib_table_walk(fib_table->ft_index,
- FIB_PROTOCOL_IP6,
- vl_api_hicn_api_route_dump_walk,
- &ctx);
- }));
+ pool_foreach (fib_table, im->fibs, (
+ {
+ fib_table_walk (fib_table->ft_index,
+ FIB_PROTOCOL_IP4,
+ vl_api_hicn_api_route_dump_walk,
+ &ctx);}
+ ));
+
+ pool_foreach (fib_table, im6->fibs, (
+ {
+ fib_table_walk (fib_table->ft_index,
+ FIB_PROTOCOL_IP6,
+ vl_api_hicn_api_route_dump_walk,
+ &ctx);}
+ ));
vec_foreach (lfeip, ctx.feis)
- {
- pfx = fib_entry_get_prefix (*lfeip);
- send_route_details (reg, pfx, mp->context);
- }
+ {
+ pfx = fib_entry_get_prefix (*lfeip);
+ send_route_details (reg, pfx, mp->context);
+ }
vec_free (ctx.feis);
@@ -842,7 +830,7 @@ hicn_face_api_entry_params_serialize (hicn_face_id_t faceid,
clib_host_to_net_u64 (face_ip->remote_addr.as_u64[1]);
reply->swif = clib_host_to_net_u32 (face->shared.sw_if);
reply->flags = clib_host_to_net_u32 (face->shared.flags);
- reply->faceid = clib_host_to_net_u32(faceid);
+ reply->faceid = clib_host_to_net_u32 (faceid);
}
else
rv = HICN_ERROR_FACE_IP_ADJ_NOT_FOUND;
diff --git a/hicn-plugin/src/hicn_api_test.c b/hicn-plugin/src/hicn_api_test.c
index e73538814..8cd4ece36 100644
--- a/hicn-plugin/src/hicn_api_test.c
+++ b/hicn-plugin/src/hicn_api_test.c
@@ -150,8 +150,7 @@ api_hicn_api_node_params_set (vat_main_t * vam)
unformat_input_t *input = vam->input;
int enable_disable = 1;
int pit_size = -1, cs_size = -1;
- f64 pit_dflt_lifetime_sec = -1.0f;
- f64 pit_min_lifetime_sec = -1.0f, pit_max_lifetime_sec = -1.0f;
+ f64 pit_max_lifetime_sec = -1.0f;
int ret;
vl_api_hicn_api_node_params_set_t *mp;
@@ -169,12 +168,6 @@ api_hicn_api_node_params_set (vat_main_t * vam)
else if (unformat (input, "CS size %d", &cs_size))
{;
}
- else if (unformat (input, "PIT dfltlife %f", &pit_dflt_lifetime_sec))
- {;
- }
- else if (unformat (input, "PIT minlife %f", &pit_min_lifetime_sec))
- {;
- }
else if (unformat (input, "PIT maxlife %f", &pit_max_lifetime_sec))
{;
}
@@ -189,8 +182,6 @@ api_hicn_api_node_params_set (vat_main_t * vam)
mp->enable_disable = enable_disable;
mp->pit_max_size = clib_host_to_net_i32 (pit_size);
mp->cs_max_size = clib_host_to_net_i32 (cs_size);
- mp->pit_dflt_lifetime_sec = pit_dflt_lifetime_sec;
- mp->pit_min_lifetime_sec = pit_min_lifetime_sec;
mp->pit_max_lifetime_sec = pit_max_lifetime_sec;
/* send it... */
@@ -250,8 +241,6 @@ static void
mp->is_enabled,
mp->feature_cs,
clib_net_to_host_u32 (mp->pit_max_size),
- mp->pit_dflt_lifetime_sec,
- mp->pit_min_lifetime_sec,
mp->pit_max_lifetime_sec, clib_net_to_host_u32 (mp->cs_max_size));
}
@@ -627,7 +616,7 @@ api_hicn_api_route_get (vat_main_t * vam)
}
static int
-api_hicn_api_routes_dump (vat_main_t *vam)
+api_hicn_api_routes_dump (vat_main_t * vam)
{
hicn_test_main_t *hm = &hicn_test_main;
@@ -708,8 +697,8 @@ vl_api_hicn_api_route_get_reply_t_handler (vl_api_hicn_api_route_get_reply_t *
/* face_stats-details message handler */
static void
-vl_api_hicn_api_routes_details_t_handler
-(vl_api_hicn_api_routes_details_t * mp)
+ vl_api_hicn_api_routes_details_t_handler
+ (vl_api_hicn_api_routes_details_t * mp)
{
vat_main_t *vam = hicn_test_main.vat_main;
@@ -717,14 +706,15 @@ vl_api_hicn_api_routes_details_t_handler
u8 *sbuf = 0;
vec_reset_length (sbuf);
- sbuf = format (sbuf, "Prefix: %U/%u\n", format_ip46_address, &mp->prefix, 0, mp->len);
+ sbuf =
+ format (sbuf, "Prefix: %U/%u\n", format_ip46_address, &mp->prefix, 0,
+ mp->len);
sbuf = format (sbuf, "Faces: \n");
- for( int i = 0; i < mp->nfaces; i++)
+ for (int i = 0; i < mp->nfaces; i++)
{
faceid = clib_net_to_host_u32 (mp->faceids[i]);
- sbuf =
- format (sbuf, " faceid %d\n", faceid);
+ sbuf = format (sbuf, " faceid %d\n", faceid);
}
fformat (vam->ofp, "%sStrategy: %d\n",
diff --git a/hicn-plugin/src/infra.h b/hicn-plugin/src/infra.h
index a9744fe97..b859b8e46 100644
--- a/hicn-plugin/src/infra.h
+++ b/hicn-plugin/src/infra.h
@@ -38,15 +38,9 @@ typedef struct hicn_main_s
/* Global PIT lifetime info */
/*
- * Default PIT entry timeout to use in case an interest does not
- * contain a valid interest lifetime
+ * Boundaries for the interest lifetime. If greater than
+ * pit_lifetime_max_ms, pit_lifetime_max_ms is used in the PIT
*/
- u64 pit_lifetime_dflt_ms;
- /*
- * Boundarier for the interest lifetime. If outside,
- * pit_lifetime_dflt_ms is used in the PIT
- */
- u64 pit_lifetime_min_ms;
u64 pit_lifetime_max_ms;
} hicn_main_t;
@@ -65,8 +59,6 @@ u32 hicn_infra_cs_size;
* Enable the time the hICN plugin and set the forwarder parameters.
* @param enable_disable 1 if to enable, 0 otherwisw (currently only enable is supported)
* @param pit_max_size Max size of the PIT
- * @param pit_dflt_lifetime_sec_req Default PIT entry timeout to use in case an interest does not contain a valid interest lifetime
- * @param pit_min_lifetime_sec_req Minimum timeout allowed for a PIT entry lifetime
* @param pit_max_lifetime_sec_req Maximum timeout allowed for a PIT entry lifetime
* @param cs_max_size CS size. Must be <= than pit_max_size
* @param cs_reserved_app Amount of CS reserved for application faces
@@ -74,8 +66,6 @@ u32 hicn_infra_cs_size;
int
hicn_infra_plugin_enable_disable (int enable_disable,
int pit_max_size,
- f64 pit_dflt_lifetime_sec_req,
- f64 pit_min_lifetime_sec_req,
f64 pit_max_lifetime_sec_req,
int cs_max_size, int cs_reserved_app);
diff --git a/hicn-plugin/src/mgmt.c b/hicn-plugin/src/mgmt.c
index b992ba15c..cfeef6cb6 100644
--- a/hicn-plugin/src/mgmt.c
+++ b/hicn-plugin/src/mgmt.c
@@ -66,10 +66,6 @@ hicn_mgmt_node_stats_get (vl_api_hicn_api_node_stats_get_reply_t * rmp)
rmp->pkts_processed +=
clib_host_to_net_u64 (em->counters[node_cntr_base_idx +
HICNFWD_ERROR_PROCESSED]);
- n =
- vlib_get_node (this_vlib_main,
- hicn_data_pcslookup_node.index);
- node_cntr_base_idx = n->error_heap_index;
rmp->pkts_data_count +=
clib_host_to_net_u64 (em->counters[node_cntr_base_idx +
HICNFWD_ERROR_DATAS]);
diff --git a/hicn-plugin/src/params.h b/hicn-plugin/src/params.h
index 5e9d20ab7..a484d076a 100644
--- a/hicn-plugin/src/params.h
+++ b/hicn-plugin/src/params.h
@@ -62,13 +62,11 @@ STATIC_ASSERT ((ceil (log2 ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4)))) ==
STATIC_ASSERT ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX <= HICN_PARAM_FACES_MAX),
"HICN_PARAM_PIT_ENTRY_PHOP_MAX must be <= than HICN_PARAM_FACES_MAX");
-// PIT lifetime limits on API override this(in mseconds, integer type)
-#define HICN_PARAM_PIT_LIFETIME_BOUND_MIN_SEC 100
-#define HICN_PARAM_PIT_LIFETIME_BOUND_MAX_SEC 20000
+// PIT lifetime limits on API override this(in seconds, integer type)
+#define HICN_PARAM_PIT_LIFETIME_BOUND_MIN_SEC 0
+#define HICN_PARAM_PIT_LIFETIME_BOUND_MAX_SEC 200
//PIT lifetime params if not set at API(in mseconds, integer type)
-#define HICN_PARAM_PIT_LIFETIME_DFLT_MIN_MS 200
-#define HICN_PARAM_PIT_LIFETIME_DFLT_DFLT_MS 20000
#define HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS 20000
// Face CS reservation params
@@ -92,6 +90,7 @@ STATIC_ASSERT ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX <= HICN_PARAM_FACES_MAX),
/* CS reserved portion for applications */
#define HICN_PARAM_CS_RESERVED_APP 50 //%
+#define HICN_PARAM_CS_MIN_MBUF 4096 //this seems to be the minumim default number of mbuf we can have in vpp
/* Cloning parameters */
/* ip4 */
diff --git a/hicn-plugin/src/pcs.h b/hicn-plugin/src/pcs.h
index 28f9c3c37..c7e8a4b59 100644
--- a/hicn-plugin/src/pcs.h
+++ b/hicn-plugin/src/pcs.h
@@ -685,9 +685,9 @@ hicn_pcs_pit_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp,
const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id)
{
hash_entry->locks--;
- pitcs->pcs_pit_count--;
if (hash_entry->locks == 0)
{
+ pitcs->pcs_pit_count--;
hicn_pcs_delete_internal
(pitcs, pcs_entryp, hash_entry, node, vm, dpo_vft, hicn_dpo_id);
}
diff --git a/hicn-plugin/src/strategy.c b/hicn-plugin/src/strategy.c
index a6c058e4f..d07045a72 100644
--- a/hicn-plugin/src/strategy.c
+++ b/hicn-plugin/src/strategy.c
@@ -77,10 +77,9 @@ hicn_new_interest (hicn_strategy_runtime_t * rt, vlib_buffer_t * b0,
hicn_ops_vft[type.l1]->get_lifetime (type, &hicn0->protocol,
&imsg_lifetime);
- if (imsg_lifetime < sm->pit_lifetime_min_ms
- || imsg_lifetime > sm->pit_lifetime_max_ms)
+ if (imsg_lifetime > sm->pit_lifetime_max_ms)
{
- imsg_lifetime = sm->pit_lifetime_dflt_ms;
+ imsg_lifetime = sm->pit_lifetime_max_ms;
}
pitp->shared.expire_time = hicn_pcs_get_exp_time (tnow, imsg_lifetime);
@@ -210,8 +209,9 @@ hicn_forward_interest_fn (vlib_main_t * vm,
*/
if (PREDICT_TRUE
(ret == HICN_ERROR_NONE && HICN_IS_NAMEHASH_CACHED (b0)
- && strategy->hicn_select_next_hop (vnet_buffer (b0)->ip.
- adj_index[VLIB_TX], &nh_idx,
+ && strategy->hicn_select_next_hop (vnet_buffer (b0)->
+ ip.adj_index[VLIB_TX],
+ &nh_idx,
&outface) ==
HICN_ERROR_NONE))
{
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 9d8267f5f..4df09c0dd 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -46,6 +46,7 @@ else ()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996")
endif ()
+add_subdirectory(includes)
add_subdirectory (src)
add_subdirectory (doc)
diff --git a/lib/includes/CMakeLists.txt b/lib/includes/CMakeLists.txt
new file mode 100644
index 000000000..d1eaa0b57
--- /dev/null
+++ b/lib/includes/CMakeLists.txt
@@ -0,0 +1,55 @@
+# 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.
+
+# XXX
+
+set(HICN_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR} ""
+ CACHE INTERNAL
+ "" FORCE
+)
+
+
+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/mapme.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/name.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
+ PARENT_SCOPE
+)
+
+set(LIBHICN_HEADER_FILES_UTIL
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/ip_address.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/token.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/types.h
+ PARENT_SCOPE
+)
+
diff --git a/lib/src/base.h b/lib/includes/hicn/base.h
index d8a79a9c2..d8a79a9c2 100644
--- a/lib/src/base.h
+++ b/lib/includes/hicn/base.h
diff --git a/lib/src/common.h b/lib/includes/hicn/common.h
index 33323da1b..33323da1b 100644
--- a/lib/src/common.h
+++ b/lib/includes/hicn/common.h
diff --git a/lib/src/compat.h b/lib/includes/hicn/compat.h
index 7228843bb..b31d01a0d 100644
--- a/lib/src/compat.h
+++ b/lib/includes/hicn/compat.h
@@ -234,7 +234,7 @@ int hicn_packet_get_payload (hicn_format_t format,
*/
int hicn_packet_get_locator (hicn_format_t format,
const hicn_header_t * packet,
- ip_address_t * ip_address, bool is_interest);
+ ip_prefix_t * prefix, bool is_interest);
/**
* @brief Sets the locator of an interest / data packet
@@ -246,7 +246,7 @@ int hicn_packet_get_locator (hicn_format_t format,
* @return hICN error code
*/
int hicn_packet_set_locator (hicn_format_t format, hicn_header_t * packet,
- const ip_address_t * ip_address,
+ const ip_prefix_t * prefix,
bool is_interest);
/**
@@ -396,9 +396,9 @@ 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 * ip_address);
+ ip_prefix_t * prefix);
int hicn_interest_set_locator (hicn_format_t format, hicn_header_t * interest,
- const ip_address_t * ip_address);
+ const ip_prefix_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);
@@ -425,9 +425,9 @@ int hicn_data_get_name (hicn_format_t format, const hicn_header_t * data,
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 * ip_address);
+ ip_prefix_t * prefix);
int hicn_data_set_locator (hicn_format_t format, hicn_header_t * data,
- const ip_address_t * ip_address);
+ const ip_prefix_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);
diff --git a/lib/src/error.h b/lib/includes/hicn/error.h
index 3e027c4e5..3e027c4e5 100644
--- a/lib/src/error.h
+++ b/lib/includes/hicn/error.h
diff --git a/lib/src/header.h b/lib/includes/hicn/header.h
index b21fe5c84..b21fe5c84 100644
--- a/lib/src/header.h
+++ b/lib/includes/hicn/header.h
diff --git a/lib/src/hicn.h b/lib/includes/hicn/hicn.h
index 749fd4247..749fd4247 100644
--- a/lib/src/hicn.h
+++ b/lib/includes/hicn/hicn.h
diff --git a/lib/src/mapme.h b/lib/includes/hicn/mapme.h
index 8fae44530..8fae44530 100644
--- a/lib/src/mapme.h
+++ b/lib/includes/hicn/mapme.h
diff --git a/lib/src/name.h b/lib/includes/hicn/name.h
index 434b563b8..0a100dbce 100644
--- a/lib/src/name.h
+++ b/lib/includes/hicn/name.h
@@ -28,62 +28,14 @@
#ifndef _WIN32
#include <netinet/in.h> // struct sockadd
#endif
+#include <hicn/util/ip_address.h>
#include "common.h"
/******************************************************************************
- * IP address helpers
- ******************************************************************************/
-
-/* Presentation format */
-#ifndef INET_ADDRSTRLEN
-#define INET_ADDRSTRLEN 16
-#endif
-
-#ifndef INET6_ADDRSTRLEN
-#define INET6_ADDRSTRLEN 46
-#endif
-//#define INET_MAX_ADDRSTRLEN INET6_ADDRSTRLEN
-
-/* Address size */
-#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 IP_MAX_ADDR_LEN IPV6_ADDR_LEN
-#define TCP_SEQNO_LEN 4 /* bytes */
-
-struct ip_address
-{
- union
- {
- u8 buffer[IP_MAX_ADDR_LEN];
- u8 as_u8[IP_MAX_ADDR_LEN];
- u16 as_u16[IP_MAX_ADDR_LEN >> 1];
- u32 as_u32[IP_MAX_ADDR_LEN >> 2];
- u64 as_u64[IP_MAX_ADDR_LEN >> 3];
- ip46_address_t as_ip46;
- };
- int family;
- unsigned short prefix_len;
-};
-
-typedef struct ip_address ip_address_t;
-
-int ip_address_len (const ip_address_t * ip_address);
-bool ip_address_empty (const ip_address_t * ip_address);
-
-int hicn_ip_ntop (const ip_address_t * ip_address, char *dst,
- const size_t len);
-int hicn_ip_pton (const char *ip_address_str, ip_address_t * ip_address);
-int hicn_ip_to_sockaddr_address (const ip_address_t * ip_address,
- struct sockaddr *sockaddr_address);
-
-/******************************************************************************
* hICN names
******************************************************************************/
+#define TCP_SEQNO_LEN 4 /* bytes */
#define HICN_V4_PREFIX_LEN IPV4_ADDR_LEN
#define HICN_V6_PREFIX_LEN IPV6_ADDR_LEN
#define HICN_SEGMENT_LEN TCP_SEQNO_LEN
@@ -207,7 +159,7 @@ int hicn_name_create (const char *ip_address, u32 id, hicn_name_t * name);
* @param [out] Resulting - hICN name
* @return hICN error code
*/
-int hicn_name_create_from_ip_address (const ip_address_t * ip_address, u32 id,
+int hicn_name_create_from_ip_prefix (const ip_prefix_t * prefix, u32 id,
hicn_name_t * name);
/**
@@ -295,8 +247,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_address (const hicn_name_t * name,
- ip_address_t * ip_address);
+int hicn_name_to_ip_prefix (const hicn_name_t * name,
+ ip_prefix_t * ip_prefix);
/**
* @brief Convert an hICN name to presentation format
@@ -329,7 +281,7 @@ 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_address (const ip_address_t * ip_address,
+int hicn_prefix_create_from_ip_prefix (const ip_prefix_t * ip_prefix,
hicn_prefix_t * prefix);
#endif /* HICN_NAME_H */
diff --git a/lib/src/ops.h b/lib/includes/hicn/ops.h
index 47795efd5..47795efd5 100644
--- a/lib/src/ops.h
+++ b/lib/includes/hicn/ops.h
diff --git a/ctrl/facemgr/src/util/policy.h b/lib/includes/hicn/policy.h
index e20af6560..12f8c1e12 100644
--- a/ctrl/facemgr/src/util/policy.h
+++ b/lib/includes/hicn/policy.h
@@ -22,7 +22,7 @@
#include <netinet/in.h> // INET*_ADDRSTRLEN
#include <string.h> // strcasecmp
-#include "token.h"
+#include <hicn/util/token.h>
/* POLICY TAG */
@@ -83,6 +83,14 @@ int policy_tags_has(policy_tags_t tags, policy_tag_t tag)
return tags & (1 << tag);
}
+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
+#undef _
+}
+
#define POLICY_TAGS_EMPTY 0
static inline
diff --git a/lib/src/protocol.h b/lib/includes/hicn/protocol.h
index a97cc99cf..a97cc99cf 100644
--- a/lib/src/protocol.h
+++ b/lib/includes/hicn/protocol.h
diff --git a/lib/src/protocol/ah.h b/lib/includes/hicn/protocol/ah.h
index a59a5051a..a59a5051a 100644
--- a/lib/src/protocol/ah.h
+++ b/lib/includes/hicn/protocol/ah.h
diff --git a/lib/src/protocol/icmp.h b/lib/includes/hicn/protocol/icmp.h
index 36954bb6d..36954bb6d 100644
--- a/lib/src/protocol/icmp.h
+++ b/lib/includes/hicn/protocol/icmp.h
diff --git a/lib/src/protocol/icmprd.h b/lib/includes/hicn/protocol/icmprd.h
index aa1fa01ae..aa1fa01ae 100644
--- a/lib/src/protocol/icmprd.h
+++ b/lib/includes/hicn/protocol/icmprd.h
diff --git a/lib/src/protocol/ipv4.h b/lib/includes/hicn/protocol/ipv4.h
index 8a5b6683b..8a5b6683b 100644
--- a/lib/src/protocol/ipv4.h
+++ b/lib/includes/hicn/protocol/ipv4.h
diff --git a/lib/src/protocol/ipv6.h b/lib/includes/hicn/protocol/ipv6.h
index 5a83abcae..5a83abcae 100644
--- a/lib/src/protocol/ipv6.h
+++ b/lib/includes/hicn/protocol/ipv6.h
diff --git a/lib/src/protocol/tcp.h b/lib/includes/hicn/protocol/tcp.h
index ded9a06b2..ded9a06b2 100644
--- a/lib/src/protocol/tcp.h
+++ b/lib/includes/hicn/protocol/tcp.h
diff --git a/lib/src/protocol/udp.h b/lib/includes/hicn/protocol/udp.h
index 75d1ea98c..75d1ea98c 100644
--- a/lib/src/protocol/udp.h
+++ b/lib/includes/hicn/protocol/udp.h
diff --git a/lib/includes/hicn/util/ip_address.h b/lib/includes/hicn/util/ip_address.h
new file mode 100644
index 000000000..542e6e4c6
--- /dev/null
+++ b/lib/includes/hicn/util/ip_address.h
@@ -0,0 +1,160 @@
+/*
+ * 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 ip_address.h
+ * \brief IP address type
+ */
+#ifndef UTIL_IP_ADDRESS_H
+#define UTIL_IP_ADDRESS_H
+
+#include <arpa/inet.h> // inet_ntop
+#ifdef __APPLE__
+#include <libkern/OSByteOrder.h>
+#define __bswap_constant_32(x) OSSwapInt32(x)
+#include <machine/endian.h>
+#else
+#include <endian.h>
+#ifdef __ANDROID__
+#include <byteswap.h>
+#endif
+#include <endian.h>
+#endif
+#include <errno.h>
+#include <netdb.h> // struct addrinfo
+#ifndef _WIN32
+#include <netinet/in.h> // struct sockadd
+#endif
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h> // snprintf
+#include <string.h> // memset
+
+#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)
+
+/* Presentation format */
+#ifndef INET_ADDRSTRLEN
+#define INET_ADDRSTRLEN 16
+#endif
+
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+//#define INET_MAX_ADDRSTRLEN INET6_ADDRSTRLEN
+
+#define IP_MAX_ADDR_LEN IPV6_ADDR_LEN
+
+#define DUMMY_PORT 1234
+
+typedef union {
+ union {
+ struct in_addr as_inaddr;
+ u8 as_u8[4];
+ u16 as_u16[2];
+ u32 as_u32;
+ } v4;
+ union {
+ struct in6_addr as_in6addr;
+ u8 as_u8[16];
+ u16 as_u16[8];
+ u32 as_u32[4];
+ u64 as_u64[2];
+ } v6;
+ u8 buffer[IP_MAX_ADDR_LEN];
+ u8 as_u8[IP_MAX_ADDR_LEN];
+ u16 as_u16[IP_MAX_ADDR_LEN >> 1];
+ u32 as_u32[IP_MAX_ADDR_LEN >> 2];
+ u64 as_u64[IP_MAX_ADDR_LEN >> 3];
+} ip_address_t;
+
+#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
+
+typedef struct {
+ int family;
+ ip_address_t address;
+ u8 len;
+} ip_prefix_t;
+
+#define MAXSZ_PREFIX_ MAXSZ_IP_ADDRESS_ + 1 + 3
+#define MAXSZ_PREFIX MAXSZ_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;
+
+#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 MAXSZ_PORT_ 5
+#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 (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);
+
+/* 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);
+
+
+/* URL */
+
+#define MAXSZ_PROTO_ 8 /* inetX:// */
+#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
+
+int url_snprintf(char * s, size_t size, int family,
+ const ip_address_t * ip_address, u16 port);
+
+#endif /* UTIL_IP_ADDRESS_H */
diff --git a/ctrl/facemgr/src/util/token.h b/lib/includes/hicn/util/token.h
index 43e0a77b2..43e0a77b2 100644
--- a/ctrl/facemgr/src/util/token.h
+++ b/lib/includes/hicn/util/token.h
diff --git a/ctrl/facemgr/src/util/types.h b/lib/includes/hicn/util/types.h
index 10a0bdca0..50b368b8d 100644
--- a/ctrl/facemgr/src/util/types.h
+++ b/lib/includes/hicn/util/types.h
@@ -25,7 +25,7 @@ typedef uint64_t u64;
#define UNION_CAST(x, destType) \
(((union {__typeof__(x) a; destType b;})x).b)
-typedef unsigned int hash_t;
+//typedef unsigned int hash_t;
typedef int (*cmp_t)(const void *, const void *);
diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt
index 65eae8d77..d8c7b11e0 100644
--- a/lib/src/CMakeLists.txt
+++ b/lib/src/CMakeLists.txt
@@ -13,41 +13,20 @@
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-list(APPEND LIBHICN_HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn.h
- ${CMAKE_CURRENT_SOURCE_DIR}/base.h
- ${CMAKE_CURRENT_SOURCE_DIR}/common.h
- ${CMAKE_CURRENT_SOURCE_DIR}/compat.h
- ${CMAKE_CURRENT_SOURCE_DIR}/error.h
- ${CMAKE_CURRENT_SOURCE_DIR}/header.h
- ${CMAKE_CURRENT_SOURCE_DIR}/mapme.h
- ${CMAKE_CURRENT_SOURCE_DIR}/name.h
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol.h
- ${CMAKE_CURRENT_SOURCE_DIR}/ops.h
-)
-
-list(APPEND LIBHICN_HEADER_FILES_PROTOCOL
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ah.h
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/icmp.h
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/icmprd.h
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ipv4.h
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ipv6.h
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/tcp.h
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/udp.h
-)
-
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}/common.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
)
set (COMPILER_DEFINITIONS "-DWITH_MAPME")
@@ -55,48 +34,26 @@ set (COMPILER_DEFINITIONS "-DWITH_MAPME")
include(BuildMacros)
include(WindowsMacros)
-if (ANDROID_API)
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
build_library(${LIBHICN}
STATIC
- SOURCES ${LIBHICN_SOURCE_FILES} ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL}
+ SOURCES ${LIBHICN_SOURCE_FILES} ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
COMPONENT lib${LIBHICN}
- INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/..
+ INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../includes
DEFINITIONS ${COMPILER_DEFINITIONS}
INSTALL_ROOT_DIR hicn
- INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL}
+ INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
LINK_LIBRARIES ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
)
else ()
build_library(${LIBHICN}
SHARED STATIC
- SOURCES ${LIBHICN_SOURCE_FILES} ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL}
+ SOURCES ${LIBHICN_SOURCE_FILES} ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
COMPONENT lib${LIBHICN}
- INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/..
+ INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../includes
DEFINITIONS ${COMPILER_DEFINITIONS}
INSTALL_ROOT_DIR hicn
- INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL}
+ INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
LINK_LIBRARIES ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
)
endif ()
-add_custom_command(TARGET ${LIBHICN_STATIC} PRE_BUILD
- COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/hicn
-)
-
-add_custom_command(TARGET ${LIBHICN_STATIC} POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/hicn/
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBHICN_HEADER_FILES} ${CMAKE_BINARY_DIR}/hicn/
-)
-
-add_custom_command(TARGET ${LIBHICN_STATIC} POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/hicn/protocol
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBHICN_HEADER_FILES_PROTOCOL} ${CMAKE_BINARY_DIR}/hicn/protocol
-)
-
-set(HICN_INCLUDE_DIRS
- ${CMAKE_BINARY_DIR} ""
- CACHE INTERNAL
- "" FORCE
-)
-
-# install(FILES ${LIBHICN_HEADER_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/hicn COMPONENT libhicn)
-# install(FILES ${LIBHICN_HEADER_FILES_PROTOCOL} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/hicn/protocol COMPONENT libhicn)
diff --git a/lib/src/common.c b/lib/src/common.c
index de4ece339..78d25b770 100644
--- a/lib/src/common.c
+++ b/lib/src/common.c
@@ -28,7 +28,8 @@
#endif
#include <stdio.h>
-#include "common.h"
+#include <hicn/common.h>
+
int
diff --git a/lib/src/compat.c b/lib/src/compat.c
index 633037a0f..68f761ac0 100644
--- a/lib/src/compat.c
+++ b/lib/src/compat.c
@@ -23,12 +23,12 @@
#include <string.h> // memset
#include <stddef.h> // offsetof
-#include "common.h"
-#include "compat.h"
-#include "error.h"
-#include "header.h"
-#include "name.h"
-#include "ops.h"
+#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)))
@@ -182,8 +182,10 @@ hicn_packet_get_header_length (hicn_format_t format, const hicn_header_t * h,
int is_ipv4 = _is_ipv4 (format);
int is_ipv6 = _is_ipv6 (format);
// The signature payload is expressed as number of 32 bits words
- *header_length += (is_ah * is_ipv4) * (h->v4ah.ah.payloadlen) << 2;
- *header_length += (is_ah * is_ipv6) * (h->v6ah.ah.payloadlen) << 2;
+ 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;
}
@@ -319,7 +321,7 @@ hicn_packet_get_payload (hicn_format_t format, const hicn_header_t * h,
int
hicn_packet_get_locator (hicn_format_t format, const hicn_header_t * h,
- ip_address_t * ip_address, bool is_interest)
+ ip_prefix_t * prefix, bool is_interest)
{
const void *locator;
int is_ipv4 = (format & HFO_INET);
@@ -328,28 +330,28 @@ hicn_packet_get_locator (hicn_format_t format, const hicn_header_t * h,
if (is_ipv4)
{
locator = is_interest ? &h->v4.ip.saddr : &h->v4.ip.daddr;
- ip_address->family = AF_INET;
- ip_address->prefix_len = IPV4_ADDR_LEN_BITS;
+ prefix->family = AF_INET;
+ prefix->len = IPV4_ADDR_LEN_BITS;
}
else if (is_ipv6)
{
locator = is_interest ? &h->v6.ip.saddr : &h->v6.ip.daddr;
- ip_address->family = AF_INET6;
- ip_address->prefix_len = IPV6_ADDR_LEN_BITS;
+ prefix->family = AF_INET6;
+ prefix->len = IPV6_ADDR_LEN_BITS;
}
else
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
}
- memcpy (ip_address->buffer, locator, ip_address_len (ip_address));
+ memcpy (prefix->address.buffer, locator, ip_address_len(&prefix->address, prefix->family));
return HICN_LIB_ERROR_NONE;
}
int
hicn_packet_set_locator (hicn_format_t format, hicn_header_t * h,
- const ip_address_t * ip_address, bool is_interest)
+ const ip_prefix_t * prefix, bool is_interest)
{
void *locator;
int is_ipv4 = (format & HFO_INET);
@@ -368,7 +370,7 @@ hicn_packet_set_locator (hicn_format_t format, hicn_header_t * h,
return HICN_LIB_ERROR_INVALID_PARAMETER;
}
- memcpy (locator, ip_address->buffer, ip_address_len (ip_address));
+ memcpy (locator, prefix->address.buffer, ip_address_len(&prefix->address, prefix->family));
return HICN_LIB_ERROR_NONE;
}
@@ -951,16 +953,16 @@ hicn_interest_set_name (hicn_format_t format, hicn_header_t * interest,
int
hicn_interest_get_locator (hicn_format_t format,
const hicn_header_t * interest,
- ip_address_t * ip_address)
+ ip_prefix_t * prefix)
{
- return hicn_packet_get_locator (format, interest, ip_address, _INTEREST);
+ return hicn_packet_get_locator (format, interest, prefix, _INTEREST);
}
int
hicn_interest_set_locator (hicn_format_t format, hicn_header_t * interest,
- const ip_address_t * ip_address)
+ const ip_prefix_t * prefix)
{
- return hicn_packet_set_locator (format, interest, ip_address, _INTEREST);
+ return hicn_packet_set_locator (format, interest, prefix, _INTEREST);
}
int
@@ -1043,16 +1045,16 @@ hicn_data_set_name (hicn_format_t format, hicn_header_t * data,
int
hicn_data_get_locator (hicn_format_t format, const hicn_header_t * data,
- ip_address_t * ip_address)
+ ip_prefix_t * prefix)
{
- return hicn_packet_get_locator (format, data, ip_address, _DATA);
+ return hicn_packet_get_locator (format, data, prefix, _DATA);
}
int
hicn_data_set_locator (hicn_format_t format, hicn_header_t * data,
- const ip_address_t * ip_address)
+ const ip_prefix_t * prefix)
{
- return hicn_packet_set_locator (format, data, ip_address, _DATA);
+ return hicn_packet_set_locator (format, data, prefix, _DATA);
}
int
diff --git a/lib/src/error.c b/lib/src/error.c
index 865e2b47d..ab5d6e27d 100644
--- a/lib/src/error.c
+++ b/lib/src/error.c
@@ -18,7 +18,7 @@
* @brief Implementation of error management functions.
*/
-#include "error.h"
+#include <hicn/error.h>
const char *HICN_LIB_ERROR_STRING[] = {
#define _(a,b,c) [b] = c,
diff --git a/lib/src/mapme.c b/lib/src/mapme.c
index ccd384b21..3e7e8bc80 100644
--- a/lib/src/mapme.c
+++ b/lib/src/mapme.c
@@ -18,12 +18,12 @@
* @brief Implementation of MAP-Me anchorless producer mobility management.
*/
-#include "mapme.h"
-#include "common.h"
-#include "error.h"
+#include <hicn/mapme.h>
+#include <hicn/common.h>
+#include <hicn/error.h>
-#include "protocol/ipv4.h"
-#include "protocol/ipv6.h"
+#include <hicn/protocol/ipv4.h>
+#include <hicn/protocol/ipv6.h>
size_t
hicn_mapme_v4_create_packet (u8 * buf, const hicn_prefix_t * prefix,
diff --git a/lib/src/name.c b/lib/src/name.c
index 0a0da63cf..a19971d49 100644
--- a/lib/src/name.c
+++ b/lib/src/name.c
@@ -26,11 +26,9 @@
#include <stdlib.h> // strtoul
#include <string.h> // memcpy
-#include "common.h"
-#include "error.h"
-#include "name.h"
-
-#define DUMMY_PORT ntohs(1234)
+#include <hicn/common.h>
+#include <hicn/error.h>
+#include <hicn/name.h>
#if ! HICN_VPP_PLUGIN
int
@@ -76,10 +74,10 @@ hicn_name_create (const char *ip_address, u32 id, hicn_name_t * name)
}
int
-hicn_name_create_from_ip_address (const ip_address_t * ip_address, u32 id,
+hicn_name_create_from_prefix (const ip_prefix_t * prefix, u32 id,
hicn_name_t * name)
{
- switch (ip_address->family)
+ switch (prefix->family)
{
case AF_INET:
name->type = HNT_CONTIGUOUS_V4;
@@ -91,13 +89,14 @@ hicn_name_create_from_ip_address (const ip_address_t * ip_address, u32 id,
return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
}
- name->len = (u8) ip_address_len (ip_address);
+ name->len = (u8) (prefix->len);
if ((name->type != HNT_CONTIGUOUS_V4) && (name->type != HNT_CONTIGUOUS_V6))
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
}
- memcpy (name->buffer, ip_address->buffer, name->len);
+ memcpy (name->buffer, prefix->address.buffer,
+ ip_address_len(&prefix->address, prefix->family));
*(u32 *) (name->buffer + name->len) = id;
return HICN_LIB_ERROR_NONE;
@@ -391,27 +390,27 @@ hicn_name_to_sockaddr_address (const hicn_name_t * name,
}
int
-hicn_name_to_ip_address (const hicn_name_t * name, ip_address_t * ip_address)
+hicn_name_to_ip_prefix (const hicn_name_t * name, ip_prefix_t * prefix)
{
switch (name->type)
{
case HNT_CONTIGUOUS_V6:
- memcpy (&ip_address->buffer, name->buffer, IPV6_ADDR_LEN);
- ip_address->family = AF_INET6;
+ memcpy (&prefix->address.buffer, name->buffer, IPV6_ADDR_LEN);
+ prefix->family = AF_INET6;
break;
case HNT_IOV_V6:
- memcpy (&ip_address->buffer, name->iov.buffers[0].iov_base,
+ memcpy (&prefix->address.buffer, name->iov.buffers[0].iov_base,
name->iov.buffers[0].iov_len);
- ip_address->family = AF_INET6;
+ prefix->family = AF_INET6;
break;
case HNT_CONTIGUOUS_V4:
- memcpy (&ip_address->buffer, name->buffer, IPV4_ADDR_LEN);
- ip_address->family = AF_INET;
+ memcpy (&prefix->address.buffer, name->buffer, IPV4_ADDR_LEN);
+ prefix->family = AF_INET;
break;
case HNT_IOV_V4:
- memcpy (&ip_address->buffer, name->iov.buffers[0].iov_base,
+ memcpy (&prefix->address.buffer, name->iov.buffers[0].iov_base,
name->iov.buffers[0].iov_len);
- ip_address->family = AF_INET;
+ prefix->family = AF_INET;
break;
default:
return HICN_LIB_ERROR_UNEXPECTED;
@@ -525,143 +524,28 @@ hicn_name_get_family (const hicn_name_t * name, int *family)
}
int
-hicn_prefix_create_from_ip_address (const ip_address_t * ip_address,
+hicn_prefix_create_from_ip_prefix (const ip_prefix_t * ip_prefix,
hicn_prefix_t * prefix)
{
- switch (ip_address->family)
+ switch (ip_prefix->family)
{
case AF_INET:
- prefix->name.ip4.as_u32 = ip_address->as_u32[0];
+ prefix->name.ip4.as_u32 = ip_prefix->address.as_u32[0];
break;
case AF_INET6:
- prefix->name.ip6.as_u64[0] = ip_address->as_u64[0];
- prefix->name.ip6.as_u64[1] = ip_address->as_u64[1];
+ prefix->name.ip6.as_u64[0] = ip_prefix->address.as_u64[0];
+ prefix->name.ip6.as_u64[1] = ip_prefix->address.as_u64[1];
break;
default:
return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
}
- prefix->len = (u8) (ip_address->prefix_len);
+ prefix->len = (u8) (ip_prefix->len);
return HICN_LIB_ERROR_NONE;
}
#endif /* ! HICN_VPP_PLUGIN */
-/********
- * IP
- */
-
-inline int
-ip_address_len (const ip_address_t * ip_address)
-{
- return (ip_address->family == AF_INET6) ? IPV6_ADDR_LEN :
- (ip_address->family == AF_INET) ? IPV4_ADDR_LEN : 0;
-}
-
-bool
-ip_address_empty (const ip_address_t * ip_address)
-{
- return ip_address->prefix_len == 0;
-}
-
-int
-hicn_ip_ntop (const ip_address_t * ip_address, char *dst, const size_t len)
-{
- const char *rc;
-
- rc = inet_ntop (ip_address->family, ip_address->buffer, dst, len);
- if (!rc)
- {
- printf ("error ntop: %d %s\n", errno, strerror (errno));
- return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
- }
-
- return HICN_LIB_ERROR_NONE;
-}
-
-/*
- * Parse ip addresses in presentation format, or prefixes (in bits, separated by a slash)
- */
-int
-hicn_ip_pton (const char *ip_address_str, ip_address_t * ip_address)
-{
- int pton_fd;
- char *p;
- char *eptr;
- u32 dst_len;
- char *addr = strdup (ip_address_str);
-
- p = strchr (addr, '/');
- if (!p)
- {
- dst_len = 0; // until we get the ip address family
- }
- else
- {
- dst_len = strtoul (p + 1, &eptr, 10);
- *p = 0;
- }
-
- ip_address->family = get_addr_family (addr);
-
- switch (ip_address->family)
- {
- case AF_INET6:
- if (dst_len > IPV6_ADDR_LEN_BITS)
- goto ERR;
- pton_fd = inet_pton (AF_INET6, addr, &ip_address->buffer);
- ip_address->prefix_len = dst_len ? dst_len : IPV6_ADDR_LEN_BITS;
- break;
- case AF_INET:
- if (dst_len > IPV4_ADDR_LEN_BITS)
- goto ERR;
- pton_fd = inet_pton (AF_INET, addr, &ip_address->buffer);
- ip_address->prefix_len = dst_len ? dst_len : IPV4_ADDR_LEN_BITS;
- break;
- default:
- goto ERR;
- }
-
- // 0 = not in presentation format
- // < 0 = other error (use perror)
- if (pton_fd <= 0)
- {
- goto ERR;
- }
-
- return HICN_LIB_ERROR_NONE;
-ERR:
- free (addr);
- return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
-}
-
-int
-hicn_ip_to_sockaddr_address (const ip_address_t * ip_address,
- struct sockaddr *sockaddr_address)
-{
- struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) sockaddr_address;
- struct sockaddr_in *tmp4 = (struct sockaddr_in *) sockaddr_address;
-
- switch (ip_address->family)
- {
- case AF_INET6:
- tmp6->sin6_family = AF_INET6;
- tmp6->sin6_port = DUMMY_PORT;
- tmp6->sin6_scope_id = 0;
- memcpy (&tmp6->sin6_addr, ip_address->buffer, IPV6_ADDR_LEN);
- break;
- case AF_INET:
- tmp4->sin_family = AF_INET;
- tmp4->sin_port = DUMMY_PORT;
- memcpy (&tmp4->sin_addr, ip_address->buffer, IPV4_ADDR_LEN);
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- 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 3e272572a..9bb78be65 100644
--- a/lib/src/ops.c
+++ b/lib/src/ops.c
@@ -22,9 +22,9 @@
#include <netinet/in.h>
#endif
#include <stdlib.h>
-#include "ops.h"
+#include <hicn/ops.h>
-#include "header.h"
+#include <hicn/header.h>
extern const hicn_ops_t hicn_ops_ipv4;
extern const hicn_ops_t hicn_ops_icmp;
diff --git a/hicn-light/src/hicn/utils/policy.c b/lib/src/policy.c
index 6c8651ee3..336249bbb 100644
--- a/hicn-light/src/hicn/utils/policy.c
+++ b/lib/src/policy.c
@@ -19,7 +19,7 @@
*/
#include <stdio.h>
-#include "policy.h"
+#include <hicn/policy.h>
const char * policy_tag_str[] = {
#define _(x, y) [POLICY_TAG_ ## x] = STRINGIZE(x),
diff --git a/lib/src/protocol/ah.c b/lib/src/protocol/ah.c
index 5a30f66f6..c2f3f552a 100644
--- a/lib/src/protocol/ah.c
+++ b/lib/src/protocol/ah.c
@@ -19,11 +19,11 @@
*/
#include <string.h> // memcpy
-#include "../common.h"
-#include "../error.h"
-#include "../header.h"
-#include "../ops.h"
-#include "ah.h"
+#include <hicn/common.h>
+#include <hicn/error.h>
+#include <hicn/header.h>
+#include <hicn/ops.h>
+#include <hicn/protocol/ah.h>
DECLARE_get_interest_locator (ah, UNEXPECTED);
DECLARE_set_interest_locator (ah, UNEXPECTED);
diff --git a/lib/src/protocol/icmp.c b/lib/src/protocol/icmp.c
index 45a28959c..85605a2c3 100644
--- a/lib/src/protocol/icmp.c
+++ b/lib/src/protocol/icmp.c
@@ -14,10 +14,10 @@
*/
#include <string.h>
-#include "icmp.h"
+#include <hicn/protocol/icmp.h>
-#include "../error.h"
-#include "../ops.h"
+#include <hicn/error.h>
+#include <hicn/ops.h>
DECLARE_get_interest_locator (icmp, UNEXPECTED)
DECLARE_set_interest_locator (icmp, UNEXPECTED)
diff --git a/lib/src/protocol/ipv4.c b/lib/src/protocol/ipv4.c
index 3c82b3223..d8d958350 100644
--- a/lib/src/protocol/ipv4.c
+++ b/lib/src/protocol/ipv4.c
@@ -27,12 +27,12 @@
#include <stdlib.h>
#include <string.h>
-#include "../error.h"
-#include "../ops.h"
-#include "../common.h"
-#include "../header.h"
+#include <hicn/error.h>
+#include <hicn/ops.h>
+#include <hicn/common.h>
+#include <hicn/header.h>
-#include "ipv4.h"
+#include <hicn/protocol/ipv4.h>
int ipv4_get_payload_length (hicn_type_t type, const hicn_protocol_t * h,
size_t * payload_length);
diff --git a/lib/src/protocol/ipv6.c b/lib/src/protocol/ipv6.c
index 7554eadf2..622355294 100644
--- a/lib/src/protocol/ipv6.c
+++ b/lib/src/protocol/ipv6.c
@@ -16,9 +16,9 @@
#include <stdlib.h>
#include <string.h>
-#include "../common.h"
-#include "../error.h"
-#include "../ops.h"
+#include <hicn/common.h>
+#include <hicn/error.h>
+#include <hicn/ops.h>
int
ipv6_get_payload_length (hicn_type_t type, const hicn_protocol_t * h,
diff --git a/lib/src/protocol/tcp.c b/lib/src/protocol/tcp.c
index b9f1d2775..0e3155020 100644
--- a/lib/src/protocol/tcp.c
+++ b/lib/src/protocol/tcp.c
@@ -14,10 +14,10 @@
*/
#include <string.h>
-#include "tcp.h"
+#include <hicn/protocol/tcp.h>
-#include "../error.h"
-#include "../ops.h"
+#include <hicn/error.h>
+#include <hicn/ops.h>
#define TCP_DEFAULT_SRC_PORT 0x8000
#define TCP_DEFAULT_DST_PORT 0x0080
diff --git a/ctrl/facemgr/src/util/ip_address.h b/lib/src/util/ip_address.c
index 243ce048b..2cf2aaef3 100644
--- a/ctrl/facemgr/src/util/ip_address.h
+++ b/lib/src/util/ip_address.c
@@ -14,120 +14,47 @@
*/
/**
- * \file ip_address.h
- * \brief IP address type support
+ * \file ip_address.c
+ * \brief Implementation of IP address type
*/
-#ifndef UTIL_IP_ADDRESS_H
-#define UTIL_IP_ADDRESS_H
-
-#include <arpa/inet.h> // inet_ntop
-#ifdef __APPLE__
-#include <libkern/OSByteOrder.h>
-#define __bswap_constant_32(x) OSSwapInt32(x)
-#include <machine/endian.h>
-#else
-#include <endian.h>
-#ifdef __ANDROID__
-#include <byteswap.h>
-#endif
-#endif
-#include <errno.h>
-#include <netdb.h> // struct addrinfo
-#include <netinet/in.h> // INET*_ADDRSTRLEN, IN*ADDR_LOOPBACK
-#include <stdlib.h>
-#include <stdio.h> // snprintf
-#include <string.h> // memset
-
-#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 IP_MAX_ADDR_LEN IPV6_ADDR_LEN
-
-#define DUMMY_PORT 1234
-
-typedef union {
- union {
- struct in_addr as_inaddr;
- u8 as_u8[4];
- u16 as_u16[2];
- u32 as_u32;
- } v4;
- union {
- struct in6_addr as_in6addr;
- u8 as_u8[16];
- u16 as_u16[8];
- u32 as_u32[4];
- u64 as_u64[2];
- } v6;
- u8 buffer[IP_MAX_ADDR_LEN];
- u8 as_u8[IP_MAX_ADDR_LEN];
- u16 as_u16[IP_MAX_ADDR_LEN >> 1];
- u32 as_u32[IP_MAX_ADDR_LEN >> 2];
- u64 as_u64[IP_MAX_ADDR_LEN >> 3];
-} ip_address_t;
-
-#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
-
-typedef struct {
- int family;
- ip_address_t address;
- u8 len;
-} ip_prefix_t;
-#define MAXSZ_PREFIX_ MAXSZ_IP_ADDRESS_ + 1 + 3
-#define MAXSZ_PREFIX MAXSZ_PREFIX_ + 1
+#include <hicn/util/ip_address.h>
-/* No htonl() with const */
-static const ip_address_t IPV4_LOOPBACK = {
#if __BYTE_ORDER == __LITTLE_ENDIAN
#ifdef __ANDROID__
- .v4.as_inaddr.s_addr = bswap_32(INADDR_LOOPBACK),
+#define SWAP(x) bswap_32(x)
#else
- .v4.as_inaddr.s_addr = __bswap_constant_32(INADDR_LOOPBACK),
+#define SWAP(x) __bswap_constant_32(x)
#endif
#else
- .v4.as_inaddr.s_addr = INADDR_LOOPBACK,
+#define SWAP(x) x
#endif
+
+
+/* No htonl() with const */
+const ip_address_t IPV4_LOOPBACK = (ip_address_t) {
+ .v4.as_inaddr.s_addr = SWAP(INADDR_LOOPBACK),
};
-static const ip_address_t IPV6_LOOPBACK = {
+const ip_address_t IPV6_LOOPBACK = (ip_address_t) {
.v6.as_in6addr = IN6ADDR_LOOPBACK_INIT,
};
-static const ip_address_t IPV4_ANY = {
+const ip_address_t IPV4_ANY = (ip_address_t) {
.v4.as_inaddr.s_addr = INADDR_ANY,
};
-static const ip_address_t IPV6_ANY = {
+const ip_address_t IPV6_ANY = (ip_address_t) {
.v6.as_in6addr = IN6ADDR_ANY_INIT,
};
-#define IP_ANY(family) (family == AF_INET) ? IPV4_ANY : IPV6_ANY
-
-static const ip_address_t IP_ADDRESS_EMPTY = {
+const ip_address_t IP_ADDRESS_EMPTY = {
.as_u64 = { 0 },
};
-#define MAX_PORT 1 << (8 * sizeof(u16))
-#define IS_VALID_PORT(x) ((x > 0) && (x < MAX_PORT))
-
-#define MAXSZ_PORT_ 5
-#define MAXSZ_PORT MAXSZ_PORT_ + 1
+/* IP address */
-#define IS_VALID_FAMILY(x) ((x == AF_INET) || (x == AF_INET6))
-
-static inline
int
ip_address_get_family (const char * ip_address)
{
@@ -149,7 +76,6 @@ ip_address_get_family (const char * ip_address)
return rc;
}
-static inline
int
ip_address_len (const ip_address_t * ip_address, int family)
{
@@ -157,7 +83,6 @@ ip_address_len (const ip_address_t * ip_address, int family)
(family == AF_INET) ? IPV4_ADDR_LEN : 0;
}
-static inline
int
ip_address_ntop (const ip_address_t * ip_address, char *dst, const size_t len,
int family)
@@ -169,7 +94,6 @@ ip_address_ntop (const ip_address_t * ip_address, char *dst, const size_t len,
/*
* Parse ip addresses in presentation format
*/
-static inline
int
ip_address_pton (const char *ip_address_str, ip_address_t * ip_address)
{
@@ -205,9 +129,6 @@ ERR:
return -1;
}
-
-
-static inline
int
ip_address_snprintf(char * s, size_t size, const ip_address_t * ip_address, int family)
{
@@ -216,14 +137,12 @@ ip_address_snprintf(char * s, size_t size, const ip_address_t * ip_address, int
return rc ? strlen(rc) : -1;
}
-
-static inline
int
ip_address_to_sockaddr(const ip_address_t * ip_address,
- struct sockaddr *sockaddr_address, int family)
+ struct sockaddr *sa, int family)
{
- struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) sockaddr_address;
- struct sockaddr_in *tmp4 = (struct sockaddr_in *) sockaddr_address;
+ struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) sa;
+ struct sockaddr_in *tmp4 = (struct sockaddr_in *) sa;
switch (family)
{
@@ -245,22 +164,23 @@ ip_address_to_sockaddr(const ip_address_t * ip_address,
return 1;
}
-static inline
int
ip_address_cmp(const ip_address_t * ip1, const ip_address_t * ip2, int family)
{
return memcmp(ip1, ip2, ip_address_len(ip1, family));
}
-static inline
int
ip_address_empty(const ip_address_t * ip)
{
return (memcmp(ip, &IP_ADDRESS_EMPTY, sizeof(IP_ADDRESS_EMPTY)) == 0);
}
+
+
+/* Prefix */
+
/* Parse IP Prefixes in presentation format (in bits, separated by a slash) */
-static inline
int
ip_prefix_pton (const char *ip_address_str, ip_prefix_t * ip_prefix)
{
@@ -271,14 +191,11 @@ ip_prefix_pton (const char *ip_address_str, ip_prefix_t * ip_prefix)
p = strchr (addr, '/');
if (!p)
- {
ip_prefix->len = 0; // until we get the ip address family
- }
- else
- {
- ip_prefix->len = strtoul (p + 1, &eptr, 10);
- *p = 0;
- }
+ else {
+ ip_prefix->len = strtoul (p + 1, &eptr, 10);
+ *p = 0;
+ }
ip_prefix->family = ip_address_get_family (addr);
@@ -301,9 +218,7 @@ 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;
- }
return 1;
ERR:
@@ -311,9 +226,20 @@ ERR:
return -1;
}
-static inline
int
-ip_prefix_ntop (const ip_prefix_t * ip_prefix, char *dst, size_t size)
+ip_prefix_ntop_short(const ip_prefix_t * ip_prefix, char *dst, size_t size)
+{
+ char ip_s[MAXSZ_IP_ADDRESS];
+ const char * s = inet_ntop (ip_prefix->family, ip_prefix->address.buffer, ip_s, MAXSZ_IP_ADDRESS);
+ if (!s)
+ return -1;
+ size_t n = snprintf(dst, size, "%s", ip_s);
+
+ return (n > 0 ? 1 : -1);
+}
+
+int
+ip_prefix_ntop(const ip_prefix_t * ip_prefix, char *dst, size_t size)
{
char ip_s[MAXSZ_IP_ADDRESS];
const char * s = inet_ntop (ip_prefix->family, ip_prefix->address.buffer, ip_s, MAXSZ_IP_ADDRESS);
@@ -324,5 +250,78 @@ ip_prefix_ntop (const ip_prefix_t * ip_prefix, char *dst, size_t size)
return (n > 0 ? 1 : -1);
}
+int
+ip_prefix_len (const ip_prefix_t * prefix)
+{
+ return prefix->len; // ip_address_len(&prefix->address, prefix->family);
+}
+
+bool
+ip_prefix_empty (const ip_prefix_t * prefix)
+{
+ return prefix->len == 0;
+}
+
+int ip_prefix_to_sockaddr(const ip_prefix_t * prefix,
+ struct sockaddr *sa)
+{
+ // XXX assert len == ip_address_len
+ return ip_address_to_sockaddr(&prefix->address, sa, prefix->family);
+}
+
+
+/* URL */
+
+#define MAXSZ_PROTO_ 8 /* inetX:// */
+#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
-#endif /* UTIL_IP_ADDRESS_H */
+int
+url_snprintf(char * s, size_t size, int family,
+ const ip_address_t * ip_address, u16 port)
+{
+ char * cur = s;
+ int rc;
+
+ /* Other address are currently not supported */
+ if (!IS_VALID_FAMILY(family)) {
+ return -1;
+ }
+
+ rc = snprintf(cur, s + size - cur, "inet%c://",
+ (family == AF_INET) ? '4' : '6');
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+
+ rc = ip_address_snprintf(cur, s + size - cur, ip_address, family);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+
+ rc = snprintf(cur, s + size - cur, ":");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+
+ rc = snprintf(cur, s + size - cur, "%d", port);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return cur - s;
+
+ return cur - s;
+}
diff --git a/libtransport/CMakeLists.txt b/libtransport/CMakeLists.txt
index e68e45c40..dc3409c6f 100644
--- a/libtransport/CMakeLists.txt
+++ b/libtransport/CMakeLists.txt
@@ -85,7 +85,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
set(LIBTRANSPORT_SHARED ${LIBTRANSPORT}.shared)
set(LIBTRANSPORT_STATIC ${LIBTRANSPORT}.static)
else()
- if(ANDROID_API)
+ if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
set(HICN_LIBRARIES ${LIBHICN_STATIC})
list(APPEND DEPENDENCIES
${LIBHICN_STATIC}
@@ -130,7 +130,7 @@ if (${COMPILE_TESTS})
)
endif()
-if(ANDROID_API)
+if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
find_package(OpenSSL REQUIRED)
endif ()
diff --git a/libtransport/src/hicn/transport/CMakeLists.txt b/libtransport/src/hicn/transport/CMakeLists.txt
index 5fe101c18..6e0ae5b88 100644
--- a/libtransport/src/hicn/transport/CMakeLists.txt
+++ b/libtransport/src/hicn/transport/CMakeLists.txt
@@ -54,11 +54,11 @@ else ()
set(CMAKE_SHARED_LINKER_FLAGS "/NODEFAULTLIB:\"MSVCRTD\"" )
endif ()
endif ()
-if (ANDROID_API)
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -isystem -lm")
endif()
-if (ANDROID_API)
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
build_library(${LIBTRANSPORT}
STATIC
SOURCES ${SOURCE_FILES} ${HEADER_FILES}
diff --git a/libtransport/src/hicn/transport/core/content_object.cc b/libtransport/src/hicn/transport/core/content_object.cc
index 83b545c05..d05239372 100644
--- a/libtransport/src/hicn/transport/core/content_object.cc
+++ b/libtransport/src/hicn/transport/core/content_object.cc
@@ -22,6 +22,7 @@ extern "C" {
TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat")
#endif
#include <hicn/hicn.h>
+#include <hicn/util/ip_address.h>
}
#include <cstring>
@@ -153,7 +154,7 @@ ContentObject &ContentObject::setPathLabel(uint32_t path_label) {
return *this;
}
-void ContentObject::setLocator(const ip_address_t &ip_address) {
+void ContentObject::setLocator(const ip_prefix_t &ip_address) {
if (hicn_data_set_locator(format_, packet_start_, &ip_address) < 0) {
throw errors::RuntimeException("Error setting content object locator");
}
@@ -161,8 +162,8 @@ void ContentObject::setLocator(const ip_address_t &ip_address) {
return;
}
-ip_address_t ContentObject::getLocator() const {
- ip_address_t ip;
+ip_prefix_t ContentObject::getLocator() const {
+ ip_prefix_t ip;
if (hicn_data_get_locator(format_, packet_start_, &ip) < 0) {
throw errors::RuntimeException("Error getting content object locator.");
diff --git a/libtransport/src/hicn/transport/core/content_object.h b/libtransport/src/hicn/transport/core/content_object.h
index 5af548fe4..ef5144c23 100644
--- a/libtransport/src/hicn/transport/core/content_object.h
+++ b/libtransport/src/hicn/transport/core/content_object.h
@@ -60,9 +60,9 @@ class ContentObject : public Packet {
ContentObject &setPathLabel(uint32_t path_label);
- void setLocator(const ip_address_t &ip_address) override;
+ void setLocator(const ip_prefix_t &ip_address) override;
- ip_address_t getLocator() const override;
+ ip_prefix_t getLocator() const override;
void setLifetime(uint32_t lifetime) override;
diff --git a/libtransport/src/hicn/transport/core/facade.h b/libtransport/src/hicn/transport/core/facade.h
index c28c84671..27e738e62 100644
--- a/libtransport/src/hicn/transport/core/facade.h
+++ b/libtransport/src/hicn/transport/core/facade.h
@@ -37,7 +37,7 @@ namespace core {
using HicnForwarderPortal = Portal<HicnForwarderInterface>;
#ifdef __linux__
-#ifndef __ANDROID_API__
+#ifndef __ANDROID__
using RawSocketPortal = Portal<RawSocketInterface>;
#endif
#ifdef __vpp__
diff --git a/libtransport/src/hicn/transport/core/forwarder_interface.h b/libtransport/src/hicn/transport/core/forwarder_interface.h
index 8fefba8ad..a89ed8a3c 100644
--- a/libtransport/src/hicn/transport/core/forwarder_interface.h
+++ b/libtransport/src/hicn/transport/core/forwarder_interface.h
@@ -50,7 +50,9 @@ class ForwarderInterface {
output_interface_(""),
content_store_reserved_(standard_cs_reserved) {
inet_address_.family = AF_INET;
+ inet_address_.len = IPV4_ADDR_LEN;
inet6_address_.family = AF_INET6;
+ inet6_address_.len = IPV6_ADDR_LEN;
}
public:
@@ -133,8 +135,8 @@ class ForwarderInterface {
protected:
ConnectorType &connector_;
- ip_address_t inet_address_;
- ip_address_t inet6_address_;
+ ip_prefix_t inet_address_;
+ ip_prefix_t inet6_address_;
uint16_t mtu_;
std::string output_interface_;
uint32_t content_store_reserved_;
diff --git a/libtransport/src/hicn/transport/core/hicn_binary_api.c b/libtransport/src/hicn/transport/core/hicn_binary_api.c
index 3868c0a14..8fde516fd 100644
--- a/libtransport/src/hicn/transport/core/hicn_binary_api.c
+++ b/libtransport/src/hicn/transport/core/hicn_binary_api.c
@@ -92,12 +92,12 @@ int hicn_binary_api_register_prod_app(
CONTEXT_SAVE(context_store, api, mp)
- mp->len = (u8)input_params->prefix->prefix_len;
+ mp->len = (u8)input_params->prefix->len;
mp->swif = clib_host_to_net_u32(input_params->swif);
mp->cs_reserved = clib_host_to_net_u32(input_params->cs_reserved);
- mp->prefix[0] = clib_host_to_net_u64(input_params->prefix->as_u64[0]);
- mp->prefix[1] = clib_host_to_net_u64(input_params->prefix->as_u64[1]);
+ mp->prefix[0] = clib_host_to_net_u64(input_params->prefix->address.as_u64[0]);
+ mp->prefix[1] = clib_host_to_net_u64(input_params->prefix->address.as_u64[1]);
return vpp_binary_api_send_request_wait_reply(api->vpp_api, mp);
}
@@ -112,8 +112,8 @@ static void vl_api_hicn_api_register_prod_app_reply_t_handler(
vpp_binary_api_set_ret_value(binary_api->vpp_api,
clib_net_to_host_u32(mp->retval));
params->cs_reserved = mp->cs_reserved;
- params->prod_addr->as_u64[0] = mp->prod_addr[0];
- params->prod_addr->as_u64[1] = mp->prod_addr[1];
+ params->prod_addr->address.as_u64[0] = mp->prod_addr[0];
+ params->prod_addr->address.as_u64[1] = mp->prod_addr[1];
params->face_id = clib_net_to_host_u32(mp->faceid);
vpp_binary_api_unlock_waiting_thread(binary_api->vpp_api);
@@ -147,9 +147,9 @@ static void vl_api_hicn_api_register_cons_app_reply_t_handler(
vpp_binary_api_set_ret_value(binary_api->vpp_api,
clib_net_to_host_u32(mp->retval));
- params->src4->as_ip46.ip4.as_u32 = clib_net_to_host_u32(mp->src_addr4);
- params->src6->as_u64[0] = clib_net_to_host_u64(mp->src_addr6[0]);
- params->src6->as_u64[1] = clib_net_to_host_u64(mp->src_addr6[1]);
+ params->src4->address.v4.as_u32 = clib_net_to_host_u32(mp->src_addr4);
+ params->src6->address.as_u64[0] = clib_net_to_host_u64(mp->src_addr6[0]);
+ params->src6->address.as_u64[1] = clib_net_to_host_u64(mp->src_addr6[1]);
params->face_id = clib_host_to_net_u32(mp->faceid);
vpp_binary_api_unlock_waiting_thread(binary_api->vpp_api);
@@ -166,9 +166,9 @@ int hicn_binary_api_register_route(
CONTEXT_SAVE(context_store, api, mp)
- mp->prefix[0] = input_params->prefix->as_u64[0];
- mp->prefix[1] = input_params->prefix->as_u64[1];
- mp->len = input_params->prefix->prefix_len;
+ mp->prefix[0] = input_params->prefix->address.as_u64[0];
+ mp->prefix[1] = input_params->prefix->address.as_u64[1];
+ mp->len = input_params->prefix->len;
mp->face_ids[0] = input_params->face_id;
mp->n_faces = 1;
diff --git a/libtransport/src/hicn/transport/core/hicn_binary_api.h b/libtransport/src/hicn/transport/core/hicn_binary_api.h
index 410ffb96c..b09b5f4a7 100644
--- a/libtransport/src/hicn/transport/core/hicn_binary_api.h
+++ b/libtransport/src/hicn/transport/core/hicn_binary_api.h
@@ -16,6 +16,7 @@
#pragma once
#include <hicn/transport/config.h>
+#include <hicn/util/ip_address.h>
#ifdef __vpp__
@@ -27,10 +28,8 @@ extern "C" {
#include "stdint.h"
-typedef struct ip_address ip_address_t;
-
typedef struct {
- ip_address_t* prefix;
+ ip_prefix_t* prefix;
uint32_t swif;
uint32_t cs_reserved;
} hicn_producer_input_params;
@@ -41,18 +40,18 @@ typedef struct {
typedef struct {
uint32_t cs_reserved;
- ip_address_t* prod_addr;
+ ip_prefix_t* prod_addr;
uint32_t face_id;
} hicn_producer_output_params;
typedef struct {
- ip_address_t* src4;
- ip_address_t* src6;
+ ip_prefix_t* src4;
+ ip_prefix_t* src6;
uint32_t face_id;
} hicn_consumer_output_params;
typedef struct {
- ip_address_t* prefix;
+ ip_prefix_t* prefix;
uint32_t face_id;
} hicn_producer_set_route_params;
@@ -75,4 +74,4 @@ char* hicn_binary_api_get_error_string(int ret_val);
}
#endif
-#endif // __vpp__ \ No newline at end of file
+#endif // __vpp__
diff --git a/libtransport/src/hicn/transport/core/interest.cc b/libtransport/src/hicn/transport/core/interest.cc
index 60ab10967..6465053de 100644
--- a/libtransport/src/hicn/transport/core/interest.cc
+++ b/libtransport/src/hicn/transport/core/interest.cc
@@ -119,7 +119,7 @@ void Interest::setName(Name &&name) {
}
}
-void Interest::setLocator(const ip_address_t &ip_address) {
+void Interest::setLocator(const ip_prefix_t &ip_address) {
if (hicn_interest_set_locator(format_, packet_start_, &ip_address) < 0) {
throw errors::RuntimeException("Error setting interest locator.");
}
@@ -127,8 +127,8 @@ void Interest::setLocator(const ip_address_t &ip_address) {
return;
}
-ip_address_t Interest::getLocator() const {
- ip_address_t ip;
+ip_prefix_t Interest::getLocator() const {
+ ip_prefix_t ip;
if (hicn_interest_get_locator(format_, packet_start_, &ip) < 0) {
throw errors::RuntimeException("Error getting interest locator.");
@@ -163,4 +163,4 @@ void Interest::resetForHash() {
} // end namespace core
-} // end namespace transport \ No newline at end of file
+} // end namespace transport
diff --git a/libtransport/src/hicn/transport/core/interest.h b/libtransport/src/hicn/transport/core/interest.h
index 48c833a73..12fd597e5 100644
--- a/libtransport/src/hicn/transport/core/interest.h
+++ b/libtransport/src/hicn/transport/core/interest.h
@@ -55,9 +55,9 @@ class Interest
void setName(Name &&name) override;
- void setLocator(const ip_address_t &ip_address) override;
+ void setLocator(const ip_prefix_t &ip_address) override;
- ip_address_t getLocator() const override;
+ ip_prefix_t getLocator() const override;
void setLifetime(uint32_t lifetime) override;
diff --git a/libtransport/src/hicn/transport/core/name.cc b/libtransport/src/hicn/transport/core/name.cc
index 0621eeeb5..46ef98948 100644
--- a/libtransport/src/hicn/transport/core/name.cc
+++ b/libtransport/src/hicn/transport/core/name.cc
@@ -169,11 +169,11 @@ std::shared_ptr<Sockaddr> Name::getAddress() const {
return std::shared_ptr<Sockaddr>(ret);
}
-ip_address_t Name::toIpAddress() const {
- ip_address_t ret;
+ip_prefix_t Name::toIpAddress() const {
+ ip_prefix_t ret;
std::memset(&ret, 0, sizeof(ret));
- if (hicn_name_to_ip_address(&name_, &ret) < 0) {
+ if (hicn_name_to_ip_prefix(&name_, &ret) < 0) {
throw errors::InvalidIpAddressException();
}
diff --git a/libtransport/src/hicn/transport/core/name.h b/libtransport/src/hicn/transport/core/name.h
index 061371be5..35625ddd1 100644
--- a/libtransport/src/hicn/transport/core/name.h
+++ b/libtransport/src/hicn/transport/core/name.h
@@ -93,7 +93,7 @@ class Name {
Name &setSuffix(uint32_t seq_number);
- ip_address_t toIpAddress() const;
+ ip_prefix_t toIpAddress() const;
void copyToDestination(uint8_t *destination,
bool include_suffix = false) const;
diff --git a/libtransport/src/hicn/transport/core/packet.h b/libtransport/src/hicn/transport/core/packet.h
index 4ec93205a..825c4c9dd 100644
--- a/libtransport/src/hicn/transport/core/packet.h
+++ b/libtransport/src/hicn/transport/core/packet.h
@@ -133,9 +133,9 @@ class Packet : public std::enable_shared_from_this<Packet> {
void dump() const;
- virtual void setLocator(const ip_address_t &locator) = 0;
+ virtual void setLocator(const ip_prefix_t &locator) = 0;
- virtual ip_address_t getLocator() const = 0;
+ virtual ip_prefix_t getLocator() const = 0;
void setSignatureTimestamp(const uint64_t &timestamp);
diff --git a/libtransport/src/hicn/transport/core/prefix.cc b/libtransport/src/hicn/transport/core/prefix.cc
index 74d1466ac..6b87ccd1f 100644
--- a/libtransport/src/hicn/transport/core/prefix.cc
+++ b/libtransport/src/hicn/transport/core/prefix.cc
@@ -33,7 +33,7 @@ namespace transport {
namespace core {
-Prefix::Prefix() { std::memset(&ip_address_, 0, sizeof(ip_address_t)); }
+Prefix::Prefix() { std::memset(&ip_address_, 0, sizeof(ip_prefix_t)); }
Prefix::Prefix(const char *prefix) : Prefix(std::string(prefix)) {}
@@ -67,7 +67,7 @@ Prefix::Prefix(const core::Name &content_name, uint16_t prefix_length) {
}
ip_address_ = content_name.toIpAddress();
- ip_address_.prefix_len = prefix_length;
+ ip_address_.len = prefix_length;
ip_address_.family = family;
}
@@ -77,13 +77,13 @@ void Prefix::buildPrefix(std::string &prefix, uint16_t prefix_length,
throw errors::InvalidIpAddressException();
}
- int ret = inet_pton(family, prefix.c_str(), ip_address_.buffer);
+ int ret = inet_pton(family, prefix.c_str(), ip_address_.address.buffer);
if (ret != 1) {
throw errors::InvalidIpAddressException();
}
- ip_address_.prefix_len = prefix_length;
+ ip_address_.len = prefix_length;
ip_address_.family = family;
}
@@ -101,17 +101,17 @@ std::unique_ptr<Sockaddr> Prefix::toSockaddr() {
throw errors::InvalidIpAddressException();
}
- if (hicn_ip_to_sockaddr_address(&ip_address_, ret) < 0) {
+ if (ip_prefix_to_sockaddr(&ip_address_, ret) < 0) {
throw errors::InvalidIpAddressException();
}
return std::unique_ptr<Sockaddr>(ret);
}
-uint16_t Prefix::getPrefixLength() { return ip_address_.prefix_len; }
+uint16_t Prefix::getPrefixLength() { return ip_address_.len; }
Prefix &Prefix::setPrefixLength(uint16_t prefix_length) {
- ip_address_.prefix_len = prefix_length;
+ ip_address_.len = prefix_length;
return *this;
}
@@ -123,17 +123,17 @@ Prefix &Prefix::setAddressFamily(int address_family) {
}
std::string Prefix::getNetwork() const {
- if (!checkPrefixLengthAndAddressFamily(ip_address_.prefix_len,
+ if (!checkPrefixLengthAndAddressFamily(ip_address_.len,
ip_address_.family)) {
throw errors::InvalidIpAddressException();
}
std::size_t size =
- ip_address_.family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN;
+ ip_address_.family == 4 + AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN;
std::string network(size, 0);
- if (hicn_ip_ntop(&ip_address_, (char *)network.c_str(), size) < 0) {
+ if (ip_prefix_ntop_short(&ip_address_, (char *)network.c_str(), size) < 0) {
throw errors::RuntimeException(
"Impossible to retrieve network from ip address.");
}
@@ -147,7 +147,7 @@ Name Prefix::getName() const {
}
Prefix &Prefix::setNetwork(std::string &network) {
- if (!inet_pton(AF_INET6, network.c_str(), ip_address_.buffer)) {
+ if (!inet_pton(AF_INET6, network.c_str(), ip_address_.address.buffer)) {
throw errors::RuntimeException("The network name is not valid.");
}
@@ -163,10 +163,10 @@ Name Prefix::makeRandomName() const {
0, std::numeric_limits<uint32_t>::max());
uint64_t random_number = idis(eng);
- uint32_t hash_size_bits = IPV6_ADDR_LEN_BITS - ip_address_.prefix_len;
+ uint32_t hash_size_bits = IPV6_ADDR_LEN_BITS - ip_address_.len;
uint64_t ip_address[2];
- memcpy(ip_address, ip_address_.buffer, sizeof(uint64_t));
- memcpy(ip_address + 1, ip_address_.buffer + 8, sizeof(uint64_t));
+ memcpy(ip_address, ip_address_.address.buffer, sizeof(uint64_t));
+ memcpy(ip_address + 1, ip_address_.address.buffer + 8, sizeof(uint64_t));
std::string network(IPV6_ADDR_LEN * 3, 0);
// Let's do the magic ;)
@@ -208,7 +208,7 @@ bool Prefix::checkPrefixLengthAndAddressFamily(uint16_t prefix_length,
return true;
}
-ip_address_t &Prefix::toIpAddressStruct() { return ip_address_; }
+ip_prefix_t &Prefix::toIpAddressStruct() { return ip_address_; }
} // namespace core
diff --git a/libtransport/src/hicn/transport/core/prefix.h b/libtransport/src/hicn/transport/core/prefix.h
index b68c6bdf6..022e2bec2 100644
--- a/libtransport/src/hicn/transport/core/prefix.h
+++ b/libtransport/src/hicn/transport/core/prefix.h
@@ -52,7 +52,7 @@ class Prefix {
Name makeRandomName() const;
- ip_address_t &toIpAddressStruct();
+ ip_prefix_t &toIpAddressStruct();
private:
static bool checkPrefixLengthAndAddressFamily(uint16_t prefix_length,
@@ -60,9 +60,9 @@ class Prefix {
void buildPrefix(std::string &prefix, uint16_t prefix_length, int family);
- ip_address_t ip_address_;
+ ip_prefix_t ip_address_;
};
} // end namespace core
-} // end namespace transport \ No newline at end of file
+} // end namespace transport
diff --git a/libtransport/src/hicn/transport/core/raw_socket_interface.cc b/libtransport/src/hicn/transport/core/raw_socket_interface.cc
index 4cf7b2ca6..ef365fce7 100644
--- a/libtransport/src/hicn/transport/core/raw_socket_interface.cc
+++ b/libtransport/src/hicn/transport/core/raw_socket_interface.cc
@@ -45,7 +45,7 @@ void RawSocketInterface::connect(bool is_consumer) {
utils::retrieveInterfaceAddress(output_interface_, &address);
inet6_address_.family = address.sin6_family;
- std::memcpy(inet6_address_.buffer, &address.sin6_addr,
+ std::memcpy(inet6_address_.address.buffer, &address.sin6_addr,
sizeof(address.sin6_addr));
connector_.connect(output_interface_, remote_mac_address_);
}
diff --git a/libtransport/src/hicn/transport/core/vpp_forwarder_interface.cc b/libtransport/src/hicn/transport/core/vpp_forwarder_interface.cc
index 61c5dfc7f..c8a4f9c88 100644
--- a/libtransport/src/hicn/transport/core/vpp_forwarder_interface.cc
+++ b/libtransport/src/hicn/transport/core/vpp_forwarder_interface.cc
@@ -87,8 +87,8 @@ uint32_t VPPForwarderInterface::getMemifConfiguration() {
void VPPForwarderInterface::consumerConnection() {
hicn_consumer_input_params input = {0};
hicn_consumer_output_params output = {0};
- ip_address_t ip4_address;
- ip_address_t ip6_address;
+ ip_prefix_t ip4_address;
+ ip_prefix_t ip6_address;
output.src4 = &ip4_address;
output.src6 = &ip6_address;
@@ -103,12 +103,12 @@ void VPPForwarderInterface::consumerConnection() {
}
inet_address_.family = AF_INET;
- inet_address_.prefix_len = output.src4->prefix_len;
- std::memcpy(inet_address_.buffer, output.src4->buffer, IPV6_ADDR_LEN);
+ inet_address_.len = output.src4->len;
+ std::memcpy(inet_address_.address.buffer, output.src4->address.buffer, IPV6_ADDR_LEN);
inet6_address_.family = AF_INET6;
- inet6_address_.prefix_len = output.src6->prefix_len;
- std::memcpy(inet6_address_.buffer, output.src6->buffer, IPV6_ADDR_LEN);
+ inet6_address_.len = output.src6->len;
+ std::memcpy(inet6_address_.address.buffer, output.src6->address.buffer, IPV6_ADDR_LEN);
}
void VPPForwarderInterface::producerConnection() {
@@ -144,7 +144,7 @@ void VPPForwarderInterface::registerRoute(Prefix &prefix) {
auto &addr = prefix.toIpAddressStruct();
// Same ip address for input and outurt params
- ip_address_t ip_address;
+ ip_prefix_t ip_address;
if (face_id_ == uint32_t(~0)) {
hicn_producer_input_params input;
@@ -160,10 +160,10 @@ void VPPForwarderInterface::registerRoute(Prefix &prefix) {
// memif_id, since this function should be called after the
// memif creation.
input.swif = sw_if_index_;
- input.prefix->as_u64[0] = addr.as_u64[0];
- input.prefix->as_u64[1] = addr.as_u64[1];
+ input.prefix->address.as_u64[0] = addr.address.as_u64[0];
+ input.prefix->address.as_u64[1] = addr.address.as_u64[1];
input.prefix->family = addr.family == AF_INET6 ? AF_INET6 : AF_INET;
- input.prefix->prefix_len = addr.prefix_len;
+ input.prefix->len = addr.len;
input.cs_reserved = content_store_reserved_;
int ret = hicn_binary_api_register_prod_app(
@@ -174,25 +174,25 @@ void VPPForwarderInterface::registerRoute(Prefix &prefix) {
}
if (addr.family == AF_INET6) {
- inet6_address_.prefix_len = output.prod_addr->prefix_len;
- inet6_address_.as_u64[0] = output.prod_addr->as_u64[0];
- inet6_address_.as_u64[1] = output.prod_addr->as_u64[1];
+ inet6_address_.len = output.prod_addr->len;
+ inet6_address_.address.as_u64[0] = output.prod_addr->address.as_u64[0];
+ inet6_address_.address.as_u64[1] = output.prod_addr->address.as_u64[1];
} else {
- inet_address_.prefix_len = output.prod_addr->prefix_len;
+ inet_address_.len = output.prod_addr->len;
// The ipv4 is written in the last 4 bytes of the ipv6 address, so we need
// to copy from the byte 12
- inet_address_.as_u64[0] = output.prod_addr->as_u64[0];
- inet_address_.as_u64[1] = output.prod_addr->as_u64[1];
+ inet_address_.address.as_u64[0] = output.prod_addr->address.as_u64[0];
+ inet_address_.address.as_u64[1] = output.prod_addr->address.as_u64[1];
}
face_id_ = output.face_id;
} else {
hicn_producer_set_route_params params;
params.prefix = &ip_address;
- params.prefix->as_u64[0] = addr.as_u64[0];
- params.prefix->as_u64[1] = addr.as_u64[1];
+ params.prefix->address.as_u64[0] = addr.address.as_u64[0];
+ params.prefix->address.as_u64[1] = addr.address.as_u64[1];
params.prefix->family = addr.family == AF_INET6 ? AF_INET6 : AF_INET;
- params.prefix->prefix_len = addr.prefix_len;
+ params.prefix->len = addr.len;
params.face_id = face_id_;
int ret = hicn_binary_api_register_route(VPPForwarderInterface::hicn_api_,
@@ -225,4 +225,4 @@ void VPPForwarderInterface::closeConnection() {
} // namespace transport
-#endif \ No newline at end of file
+#endif
diff --git a/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.cc b/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.cc
index d1e89efdc..5667b0640 100644
--- a/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.cc
+++ b/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.cc
@@ -31,6 +31,11 @@
#define HICN_MAX_DATA_SEQ 0xefffffff
+//slow production rate param
+#define MIN_PRODUCTION_RATE 8000 // in bytes per sec. this value is computed
+ // through experiments
+#define LIFETIME_FRACTION 0.5
+
// NACK HEADER
// +-----------------------------------------+
// | 4 bytes: current segment in production |
@@ -58,12 +63,15 @@ RTCProducerSocket::RTCProducerSocket(asio::io_service &io_service)
bytesProductionRate_(INIT_PACKET_PRODUCTION_RATE * 1400),
packetsProductionRate_(INIT_PACKET_PRODUCTION_RATE),
perSecondFactor_(MILLI_IN_A_SEC / STATS_INTERVAL_DURATION),
+ timer_on_(false),
active_(false) {
lastStats_ = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
srand((unsigned int)time(NULL));
prodLabel_ = ((rand() % 255) << 24UL);
+ interests_cache_timer_ = std::make_unique<asio::steady_timer>(
+ this->getIoService());
}
RTCProducerSocket::RTCProducerSocket()
@@ -74,12 +82,15 @@ RTCProducerSocket::RTCProducerSocket()
bytesProductionRate_(INIT_PACKET_PRODUCTION_RATE * 1400),
packetsProductionRate_(INIT_PACKET_PRODUCTION_RATE),
perSecondFactor_(MILLI_IN_A_SEC / STATS_INTERVAL_DURATION),
+ timer_on_(false),
active_(false) {
lastStats_ = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
srand((unsigned int)time(NULL));
prodLabel_ = ((rand() % 255) << 24UL);
+ interests_cache_timer_ = std::make_unique<asio::steady_timer>(
+ this->getIoService());
}
RTCProducerSocket::~RTCProducerSocket() {}
@@ -159,6 +170,24 @@ void RTCProducerSocket::produce(std::unique_ptr<utils::MemBuf> &&buffer) {
portal_->sendContentObject(content_object);
+ //remove interests from the interest cache if it exists
+ if(!seqs_map_.empty()){
+
+ utils::SpinLock::Acquire locked(interests_cache_lock_);
+
+ auto it_seqs = seqs_map_.find(currentSeg_);
+ if(it_seqs != seqs_map_.end()){
+ auto range = timers_map_.equal_range(it_seqs->second);
+ for(auto it_timers = range.first; it_timers != range.second; it_timers++){
+ if(it_timers->second == it_seqs->first){
+ timers_map_.erase(it_timers);
+ break;
+ }
+ }
+ seqs_map_.erase(it_seqs);
+ }
+ }
+
currentSeg_ = (currentSeg_ + 1) % HICN_MAX_DATA_SEQ;
}
@@ -170,14 +199,15 @@ void RTCProducerSocket::onInterest(Interest::Ptr &&interest) {
on_interest_input_(*this, *interest);
}
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+
bool isActive;
{
utils::SpinLock::Acquire locked(lock_);
isActive = active_;
if (isActive) {
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
if ((now - lastProduced_) > INACTIVE_TIME) {
// socket is inactive
active_ = false;
@@ -186,13 +216,68 @@ void RTCProducerSocket::onInterest(Interest::Ptr &&interest) {
}
}
- if (TRANSPORT_EXPECT_FALSE(!isActive)) {
- sendNack(*interest, false);
+ if(interestSeg > HICN_MAX_DATA_SEQ){
+ sendNack(interestSeg, isActive);
return;
}
- if(interestSeg > HICN_MAX_DATA_SEQ){
- sendNack(*interest, isActive);
+ // if the production rate is less than MIN_PRODUCTION_RATE we put the
+ // interest in a queue, otherwise we handle it in the usual way
+ if(bytesProductionRate_ < MIN_PRODUCTION_RATE && interestSeg > currentSeg_){
+
+ utils::SpinLock::Acquire locked(interests_cache_lock_);
+
+ uint64_t next_timer = ~0;
+ if(!timers_map_.empty()){
+ next_timer = timers_map_.begin()->first;
+ }
+
+ uint64_t expiration = now + (lifetime * LIFETIME_FRACTION);
+ //check if the seq number exists already
+ auto it_seqs = seqs_map_.find(interestSeg);
+ if(it_seqs != seqs_map_.end()){
+ //the seq already exists
+ if(expiration < it_seqs->second){
+ // we need to update the timer becasue we got a smaller one
+ // 1) remove the entry from the multimap
+ // 2) update this entry
+ auto range = timers_map_.equal_range(it_seqs->second);
+ for(auto it_timers = range.first; it_timers != range.second; it_timers++){
+ if(it_timers->second == it_seqs->first){
+ timers_map_.erase(it_timers);
+ break;
+ }
+ }
+ timers_map_.insert(std::pair<uint64_t,uint32_t>(expiration, interestSeg));
+ it_seqs->second = expiration;
+ }else{
+ //nothing to do here
+ return;
+ }
+ }else{
+ // add the new seq
+ timers_map_.insert(std::pair<uint64_t,uint32_t>(expiration, interestSeg));
+ seqs_map_.insert(std::pair<uint32_t,uint64_t>(interestSeg, expiration));
+ }
+
+ //here we have at least one interest in the queue, we need to start or
+ //update the timer
+ if(!timer_on_){
+ //set timeout
+ timer_on_ = true;
+ scheduleTimer(timers_map_.begin()->first - now);
+ } else {
+ //re-schedule the timer because a new interest will expires sooner
+ if(next_timer > timers_map_.begin()->first){
+ interests_cache_timer_->cancel();
+ scheduleTimer(timers_map_.begin()->first - now);
+ }
+ }
+ return;
+ }
+
+ if (TRANSPORT_EXPECT_FALSE(!isActive)) {
+ sendNack(interestSeg, false);
return;
}
@@ -202,18 +287,55 @@ void RTCProducerSocket::onInterest(Interest::Ptr &&interest) {
(double)packetsProductionRate_.load()));
if (interestSeg < currentSeg_ || interestSeg > (max_gap + currentSeg_)) {
- sendNack(*interest, true);
+ sendNack(interestSeg, true);
}
// else drop packet
}
-void RTCProducerSocket::sendNack(const Interest &interest, bool isActive) {
+void RTCProducerSocket::scheduleTimer(uint64_t wait){
+ interests_cache_timer_->expires_from_now(
+ std::chrono::milliseconds(wait));
+ interests_cache_timer_->async_wait([this](std::error_code ec) {
+ if (ec) return;
+ interestCacheTimer();
+ });
+}
+
+void RTCProducerSocket::interestCacheTimer(){
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+
+ utils::SpinLock::Acquire locked(interests_cache_lock_);
+
+ for(auto it_timers = timers_map_.begin(); it_timers != timers_map_.end();){
+ uint64_t expire = it_timers->first;
+ if(expire <= now){
+ uint32_t seq = it_timers->second;
+ sendNack(seq, active_);
+ //remove the interest from the other map
+ seqs_map_.erase(seq);
+ it_timers = timers_map_.erase(it_timers);
+ }else{
+ //stop, we are done!
+ break;
+ }
+ }
+ if(timers_map_.empty()){
+ timer_on_ = false;
+ }else{
+ timer_on_ = true;
+ scheduleTimer(timers_map_.begin()->first - now);
+ }
+}
+
+void RTCProducerSocket::sendNack(uint32_t sequence, bool isActive) {
auto nack_payload = utils::MemBuf::create(NACK_HEADER_SIZE);
nack_payload->append(NACK_HEADER_SIZE);
ContentObject nack;
nack.appendPayload(std::move(nack_payload));
- nack.setName(interest.getName());
+ nack.setName(flowName_.setSuffix(sequence));
uint32_t *payload_ptr = (uint32_t *)nack.getPayload()->data();
*payload_ptr = currentSeg_;
diff --git a/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.h b/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.h
index 5b9a23dd7..aa67f1a29 100644
--- a/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.h
+++ b/libtransport/src/hicn/transport/interfaces/rtc_socket_producer.h
@@ -41,8 +41,10 @@ class RTCProducerSocket : public ProducerSocket {
void onInterest(Interest::Ptr &&interest) override;
private:
- void sendNack(const Interest &interest, bool isActive);
+ void sendNack(uint32_t sequence, bool isActive);
void updateStats(uint32_t packet_size, uint64_t now);
+ void scheduleTimer(uint64_t wait);
+ void interestCacheTimer();
uint32_t currentSeg_;
uint32_t prodLabel_;
@@ -55,6 +57,20 @@ class RTCProducerSocket : public ProducerSocket {
uint32_t perSecondFactor_;
uint64_t lastStats_;
+ // cache for the received interests
+ // this map maps the expiration time of an interest to
+ // its sequence number. the map is sorted by timeouts
+ // the same timeout may be used for multiple sequence numbers
+ // but for each sequence number we store only the smallest
+ // expiry time. In this way the mapping from seqs_map_ to
+ // timers_map_ is unique
+ std::multimap<uint64_t,uint32_t> timers_map_;
+ // this map does the opposite, this map is not ordered
+ std::unordered_map<uint32_t,uint64_t> seqs_map_;
+ bool timer_on_;
+ std::unique_ptr<asio::steady_timer> interests_cache_timer_;
+ utils::SpinLock interests_cache_lock_;
+
uint64_t lastProduced_;
bool active_;
utils::SpinLock lock_;
diff --git a/libtransport/src/hicn/transport/protocols/rtc.cc b/libtransport/src/hicn/transport/protocols/rtc.cc
index b3a00c58d..4104d8883 100644
--- a/libtransport/src/hicn/transport/protocols/rtc.cc
+++ b/libtransport/src/hicn/transport/protocols/rtc.cc
@@ -744,7 +744,7 @@ bool RTCTransportProtocol::onNack(const ContentObject &content_object, bool rtx)
old_nack = true;
} else if (productionSeg < nackSegment) {
- actualSegment_ = (productionSeg + 1) % HICN_MIN_PROBE_SEQ;
+ actualSegment_ = productionSeg % HICN_MIN_PROBE_SEQ;
if(!rtx){
// we are asking stuff in the future
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index 5fc071734..4e73ab2b0 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -34,7 +34,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
find_package(Libtransport REQUIRED)
set(HICN_UTILS hicn-utils)
else()
- if (ANDROID_API)
+ if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_STATIC})
set(DEPENDENCIES ${LIBTRANSPORT_STATIC})
else ()