aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordan Augé <jordan.auge+fdio@cisco.com>2020-09-23 17:50:52 +0200
committerMauro Sardara <msardara@cisco.com>2021-03-19 14:15:14 +0100
commita070b0de9f9e9cbca150eea4eda74757ca588bed (patch)
tree9f2a11fa1afcd51b0b14f4b26bebf4deb8289a2f
parent32dccec98e4c7d7e4ce902e19ba8d1b29b823758 (diff)
[HICN-645] Control plane (WIP)
Change-Id: I4be6a40b690b62f22f57de6d8c10b01a1be42a6d Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com> Signed-off-by: Enrico Loparco (eloparco) <eloparco@cisco.com> Signed-off-by: Mauro Sardara <msardara@cisco.com>
-rw-r--r--CMakeLists.txt8
-rw-r--r--ctrl/libhicnctrl/includes/CMakeLists.txt1
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h58
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/cli.h31
-rw-r--r--ctrl/libhicnctrl/src/CMakeLists.txt3
-rw-r--r--ctrl/libhicnctrl/src/api.c43
-rw-r--r--ctrl/libhicnctrl/src/cli.c889
-rw-r--r--ctrl/libhicnctrl/src/hicnctrl.c842
-rw-r--r--hicn-light/CMakeLists.txt12
-rw-r--r--hicn-light/src/hicn/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/base/bitmap.h6
-rw-r--r--hicn-light/src/hicn/base/pool.c6
-rw-r--r--hicn-light/src/hicn/base/test/CMakeLists.txt4
-rw-r--r--hicn-light/src/hicn/base/test/test-bitmap.cc14
-rw-r--r--hicn-light/src/hicn/base/test/test-pool.cc21
-rw-r--r--hicn-light/src/hicn/base/test/test-vector.cc6
-rw-r--r--hicn-light/src/hicn/base/vector.h2
-rw-r--r--hicn-light/src/hicn/cli/CMakeLists.txt56
-rw-r--r--hicn-light/src/hicn/cli/color.c81
-rw-r--r--hicn-light/src/hicn/cli/color.h43
-rw-r--r--hicn-light/src/hicn/cli/hicnc.c181
-rw-r--r--hicn-light/src/hicn/cli/hicnd.c400
-rw-r--r--hicn-light/src/hicn/cli/hicns.c216
-rw-r--r--hicn-light/src/hicn/cli/logo.h39
-rw-r--r--hicn-light/src/hicn/command_line/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/command_line/controller/CMakeLists.txt25
-rw-r--r--hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c375
-rw-r--r--hicn-light/src/hicn/command_line/daemon/CMakeLists.txt25
-rw-r--r--hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c423
-rw-r--r--hicn-light/src/hicn/config/CMakeLists.txt99
-rw-r--r--hicn-light/src/hicn/config/command.c61
-rw-r--r--hicn-light/src/hicn/config/command.h163
-rw-r--r--hicn-light/src/hicn/config/command_connection.c113
-rw-r--r--hicn-light/src/hicn/config/command_face.c14
-rw-r--r--hicn-light/src/hicn/config/command_listener.c87
-rw-r--r--hicn-light/src/hicn/config/command_mapme.c0
-rw-r--r--hicn-light/src/hicn/config/command_policy.c53
-rw-r--r--hicn-light/src/hicn/config/command_punting.c36
-rw-r--r--hicn-light/src/hicn/config/command_route.c51
-rw-r--r--hicn-light/src/hicn/config/command_strategy.c12
-rw-r--r--hicn-light/src/hicn/config/parse.c354
-rw-r--r--hicn-light/src/hicn/config/parse.h6
-rw-r--r--hicn-light/src/hicn/core/CMakeLists.txt4
-rw-r--r--hicn-light/src/hicn/core/address_pair.h3
-rw-r--r--hicn-light/src/hicn/core/connection.h7
-rw-r--r--hicn-light/src/hicn/core/connection_table.h10
-rw-r--r--hicn-light/src/hicn/core/content_store.c14
-rw-r--r--hicn-light/src/hicn/core/content_store.h16
-rw-r--r--hicn-light/src/hicn/core/fib.h13
-rw-r--r--hicn-light/src/hicn/core/fib_entry.h17
-rw-r--r--hicn-light/src/hicn/core/forwarder.c20
-rw-r--r--hicn-light/src/hicn/core/forwarder.h19
-rw-r--r--hicn-light/src/hicn/core/listener.c2
-rw-r--r--hicn-light/src/hicn/core/listener.h2
-rw-r--r--hicn-light/src/hicn/core/listener_table.h12
-rw-r--r--hicn-light/src/hicn/core/messageHandler.h4
-rw-r--r--hicn-light/src/hicn/core/msgbuf_pool.c16
-rw-r--r--hicn-light/src/hicn/core/msgbuf_pool.h68
-rw-r--r--hicn-light/src/hicn/core/nameBitvector.h2
-rw-r--r--hicn-light/src/hicn/core/nexthops.h2
-rw-r--r--hicn-light/src/hicn/core/pit.c9
-rw-r--r--hicn-light/src/hicn/core/pit.h15
-rw-r--r--hicn-light/src/hicn/core/prefix_stats.h2
-rw-r--r--hicn-light/src/hicn/core/test/CMakeLists.txt25
-rw-r--r--hicn-light/src/hicn/core/test/test-msgbuf_pool.cc112
-rw-r--r--hicn-light/src/hicn/utils/commands.h5
-rw-r--r--lib/includes/hicn/policy.h5
-rw-r--r--lib/includes/hicn/protocol/ipv6.h37
-rw-r--r--lib/src/policy.c12
-rw-r--r--scripts/build-extras.sh157
-rw-r--r--scripts/build-packages.sh218
-rw-r--r--scripts/functions.sh144
72 files changed, 3564 insertions, 2271 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c76d89e22..194084de8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,6 +19,10 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules")
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+# Enable gtests (`make test`)
+# `make test ARGS="-V"` can be used for verbose output
+enable_testing()
+
## Enabled components
option(BUILD_LIBHICN "Build the hicn core library" ON)
option(BUILD_HICNLIGHT "Build the hicn light forwarder" ON)
@@ -62,9 +66,9 @@ endif()
list(APPEND dir_options
BUILD_LIBHICN
+ BUILD_CTRL
BUILD_HICNLIGHT
BUILD_HICNPLUGIN
- BUILD_CTRL
BUILD_LIBTRANSPORT
BUILD_UTILS
BUILD_APPS
@@ -103,4 +107,4 @@ foreach(dir ${subdirs})
endforeach()
include(Packager)
-make_packages() \ No newline at end of file
+make_packages()
diff --git a/ctrl/libhicnctrl/includes/CMakeLists.txt b/ctrl/libhicnctrl/includes/CMakeLists.txt
index 36a55caa2..88f8519b7 100644
--- a/ctrl/libhicnctrl/includes/CMakeLists.txt
+++ b/ctrl/libhicnctrl/includes/CMakeLists.txt
@@ -20,6 +20,7 @@ set(LIBHICNCTRL_INCLUDE_DIRS
set(TO_INSTALL_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/ctrl.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/api.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/cli.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/commands.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/route.h
PARENT_SCOPE
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
index c3fb62534..3771b3abd 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -89,7 +89,9 @@
* Message helper types and aliases
******************************************************************************/
-#define foreach_command \
+/* Action */
+
+#define foreach_action \
_(UNDEFINED) \
_(CREATE) \
_(UPDATE) \
@@ -100,10 +102,41 @@
typedef enum {
#define _(x) ACTION_##x,
- foreach_command
+ foreach_action
#undef _
} hc_action_t;
+extern const char * action_str[];
+
+#define action_str(x) action_str[x]
+
+hc_action_t action_from_str(const char * action_str);
+
+/* Object type */
+
+#define foreach_object \
+ _(UNDEFINED) \
+ _(CONNECTION) \
+ _(LISTENER) \
+ _(ROUTE) \
+ _(FACE) \
+ _(STRATEGY) \
+ _(PUNTING) \
+ _(POLICY) \
+ _(N)
+
+typedef enum {
+#define _(x) OBJECT_ ## x,
+foreach_object
+#undef _
+} hc_object_type_t;
+
+extern const char * object_str[];
+
+#define object_str(x) object_str[x]
+
+hc_object_type_t object_from_str(const char * object_str);
+
/**
* \brief hICN control message header
*/
@@ -729,4 +762,25 @@ int hc_policy_snprintf(char *s, size_t size, hc_policy_t *policy);
#endif /* WITH_POLICY */
+/* Object */
+
+typedef struct {
+ hc_object_type_t type;
+ union {
+ hc_connection_t connection;
+ hc_listener_t listener;
+ hc_route_t route;
+ hc_face_t face;
+ hc_punting_t punting;
+ hc_strategy_t strategy;
+ hc_policy_t policy;
+ uint8_t as_uint8;
+ };
+} hc_object_t;
+
+typedef struct {
+ hc_action_t action;
+ hc_object_t object;
+} hc_command_t;
+
#endif /* HICNTRL_API */
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/cli.h b/ctrl/libhicnctrl/includes/hicn/ctrl/cli.h
new file mode 100644
index 000000000..ce1ee7c74
--- /dev/null
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/cli.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file cli.h
+ * @brief Command line helpers
+ */
+
+#ifndef HICNCTRL_CLI
+#define HICNCTRL_CLI
+
+#include "api.h"
+
+#define MAXSZ_OBJECT 255 // XXX
+
+int hc_object_type_snprintf(char * buf, size_t size, hc_object_type_t type, uint8_t * data);
+int hc_object_snprintf(char * buf, size_t size, hc_object_t * object);
+
+#endif /* HICNCTRL_CLI */
diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt
index c3d843100..1a64296e8 100644
--- a/ctrl/libhicnctrl/src/CMakeLists.txt
+++ b/ctrl/libhicnctrl/src/CMakeLists.txt
@@ -16,7 +16,6 @@ list(APPEND COMPILER_DEFINITIONS
)
set(HEADER_FILES
- api.h
commands.h
)
@@ -24,6 +23,8 @@ set(UTIL_HEADER_FILES
)
set(SOURCE_FILES
+ hicnctrl.c
+ cli.c
route.c
)
diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c
index 84f34d3c2..080b6541a 100644
--- a/ctrl/libhicnctrl/src/api.c
+++ b/ctrl/libhicnctrl/src/api.c
@@ -3115,3 +3115,46 @@ hc_policy_snprintf(char * s, size_t size, hc_policy_t * policy)
}
#endif /* WITH_POLICY */
+
+const char * action_str[] = {
+#define _(x) [ACTION_ ## x] = #x,
+ foreach_action
+#undef _
+};
+
+hc_action_t
+action_from_str(const char * action_str)
+{
+#define _(x) \
+ if (strcasecmp(action_str, # x) == 0) \
+ return ACTION_ ## x; \
+ else
+ foreach_action
+#undef _
+ if (strcasecmp(action_str, "add") == 0)
+ return ACTION_CREATE;
+ else
+ if (strcasecmp(action_str, "remove") == 0)
+ return ACTION_DELETE;
+ else
+ return ACTION_UNDEFINED;
+}
+
+const char * object_str[] = {
+#define _(x) [OBJECT_ ## x] = #x,
+ foreach_object
+#undef _
+};
+
+hc_object_type_t
+object_from_str(const char * object_str)
+{
+#define _(x) \
+ if (strcasecmp(object_str, # x) == 0) \
+ return OBJECT_ ## x; \
+ else
+ foreach_object
+#undef _
+ return OBJECT_UNDEFINED;
+}
+
diff --git a/ctrl/libhicnctrl/src/cli.c b/ctrl/libhicnctrl/src/cli.c
index fc81139d6..17ffa2bd5 100644
--- a/ctrl/libhicnctrl/src/cli.c
+++ b/ctrl/libhicnctrl/src/cli.c
@@ -1,868 +1,49 @@
-/*
- * 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 <hicn/ctrl/api.h>
+#include <hicn/ctrl/cli.h>
-/**
- * \file cli.c
- * \brief Command line interface
- */
-#include <ctype.h> // isalpha isalnum
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h> // getopt
+typedef int (*hc_object_snprintf_type)(char*, size_t, uint8_t*);
-#include <hicn/ctrl.h>
-#include <hicn/util/ip_address.h>
-#include <hicn/util/token.h>
+static const hc_object_snprintf_type map_object_snprintf[] = {
+ [OBJECT_CONNECTION] = (hc_object_snprintf_type)hc_connection_snprintf,
+ [OBJECT_LISTENER] = (hc_object_snprintf_type)hc_listener_snprintf,
+ [OBJECT_ROUTE] = (hc_object_snprintf_type)hc_route_snprintf,
+ [OBJECT_FACE] = (hc_object_snprintf_type)hc_face_snprintf,
+ [OBJECT_STRATEGY] = (hc_object_snprintf_type)hc_strategy_snprintf,
+ [OBJECT_POLICY] = (hc_object_snprintf_type)hc_policy_snprintf,
+ [OBJECT_PUNTING] = (hc_object_snprintf_type)hc_punting_snprintf,
+};
-
-#define die(LABEL, MESSAGE) do { \
- printf(MESSAGE "\n"); \
- rc = -1; \
- goto ERR_ ## LABEL; \
-} while(0)
-
-#define foreach_object \
- _(UNDEFINED) \
- _(FACE) \
- _(ROUTE) \
- _(STRATEGY) \
- _(LISTENER) \
- _(CONNECTION) \
- _(N)
-
-typedef enum {
-#define _(x) OBJECT_ ## x,
-foreach_object
-#undef _
-} hc_object_t;
-
-void
-usage_header()
-{
- fprintf(stderr, "Usage:\n");
-}
-
-void
-usage_face_create(const char * prog, bool header, bool verbose)
-{
-
- if (header)
- usage_header();
- fprintf(stderr, "%s -f TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Create a face on specified address and port.\n");
-}
-
-void
-usage_face_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -df ID\n", prog);
- //fprintf(stderr, "%s -df NAME\n", prog);
- fprintf(stderr, "%s -df TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Delete a face...\n");
-}
-
-void
-usage_face_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -F\n", prog);
- if (verbose)
- fprintf(stderr, " List all faces.\n");
-}
-
-void
-usage_face(const char * prog, bool header, bool verbose)
-{
- usage_face_create(prog, header, verbose);
- usage_face_delete(prog, header, verbose);
- usage_face_list(prog, header, verbose);
-}
-
-void
-usage_route_create(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -r FACE_ID PREFIX [COST]\n", prog);
- //fprintf(stderr, "%s -r [FACE_ID|NAME] PREFIX [COST]\n", prog);
- if (verbose)
- fprintf(stderr, " Create a route...\n");
-}
-
-void
-usage_route_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -dr FACE_ID PREFIX\n", prog);
- //fprintf(stderr, "%s -dr [FACE_ID|NAME] PREFIX\n", prog);
- if (verbose)
- fprintf(stderr, " Delete a route...\n");
-}
-
-void
-usage_route_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -R\n", prog);
- if (verbose)
- fprintf(stderr, " List all routes.\n");
-}
-
-void
-usage_route(const char * prog, bool header, bool verbose)
-{
- usage_route_create(prog, header, verbose);
- usage_route_delete(prog, header, verbose);
- usage_route_list(prog, header, verbose);
-}
-
-void
-usage_forwarding_strategy_create(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
-}
-void
-usage_forwarding_strategy_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
-}
-
-void
-usage_forwarding_strategy_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -S\n", prog);
- if (verbose)
- fprintf(stderr, " List all availble forwarding strategies.\n");
-}
-
-void
-usage_forwarding_strategy(const char * prog, bool header, bool verbose)
-{
- usage_forwarding_strategy_create(prog, header, verbose);
- usage_forwarding_strategy_delete(prog, header, verbose);
- usage_forwarding_strategy_list(prog, header, verbose);
-}
-
-void
-usage_listener_create(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -l NAME TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Create a listener on specified address and port.\n");
-}
-
-void
-usage_listener_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -dl ID\n", prog);
- fprintf(stderr, "%s -dl NAME\n", prog);
- fprintf(stderr, "%s -dl TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Delete a listener...\n");
-}
-
-void
-usage_listener_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -L\n", prog);
- if (verbose)
- fprintf(stderr, " List all listeners.\n");
-}
-
-void
-usage_listener(const char * prog, bool header, bool verbose)
-{
- usage_listener_create(prog, header, verbose);
- usage_listener_delete(prog, header, verbose);
- usage_listener_list(prog, header, verbose);
-}
-void
-usage_connection_create(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -c NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Create a connection on specified address and port.\n");
-}
-
-void
-usage_connection_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -dc ID\n", prog);
- fprintf(stderr, "%s -dc NAME\n", prog);
- fprintf(stderr, "%s -dc TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Delete a connection...\n");
-}
-
-void
-usage_connection_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -C\n", prog);
- if (verbose)
- fprintf(stderr, " List all connections.\n");
-}
-
-void
-usage_connection(const char * prog, bool header, bool verbose)
-{
- usage_connection_create(prog, header, verbose);
- usage_connection_delete(prog, header, verbose);
- usage_connection_list(prog, header, verbose);
-}
-
-void usage(const char * prog)
-{
- fprintf(stderr, "Usage: %s [ [-d] [-f|-l|-c|-r] PARAMETERS | [-F|-L|-C|-R] ]\n", prog);
- fprintf(stderr, "\n");
- fprintf(stderr, "High-level commands\n");
- fprintf(stderr, "\n");
- usage_face(prog, false, true);
- usage_route(prog, false, true);
- usage_forwarding_strategy(prog, false, true);
- fprintf(stderr, "\n");
- fprintf(stderr, "Low level commands (hicn-light specific)\n");
- fprintf(stderr, "\n");
- usage_listener(prog, false, true);
- usage_connection(prog, false, true);
-}
-
-typedef struct {
- hc_action_t action;
- hc_object_t object;
- union {
- hc_face_t face;
- hc_route_t route;
- hc_connection_t connection;
- hc_listener_t listener;
- };
-} hc_command_t;
-
-/**
- * Return true if string is purely an integer
- */
-static inline
-bool
-is_number(const char *string) {
- size_t len = strlen(string);
- for (size_t i = 0; i < len; i++)
- if (!isdigit(string[i]))
- return false;
- return true;
-}
-
-/**
- * A symbolic name must be at least 1 character and must begin with an alpha.
- * The remainder must be an alphanum.
- */
-static inline
-bool
-is_symbolic_name(const char *name)
-{
- size_t len = strlen(name);
- if (len <= 0)
- return false;
- if (!isalpha(name[0]))
- return false;
- for (size_t i = 1; i < len; i++) {
- if (!isalnum(name[i]))
- return false;
- }
- return true;
-}
-
-face_type_t
-face_type_from_str(const char * str)
+int
+hc_object_type_snprintf(char * buffer, size_t size, hc_object_type_t type, uint8_t * data)
{
-#define _(x) \
- if (strcasecmp(str, STRINGIZE(x)) == 0) \
- return FACE_TYPE_ ## x; \
- else
-foreach_face_type
-#undef _
- return FACE_TYPE_UNDEFINED;
+ return map_object_snprintf[type](buffer, size, data);
}
-
int
-parse_options(int argc, char *argv[], hc_command_t * command)
+hc_object_snprintf(char * buffer, size_t size, hc_object_t * object)
{
- command->object = OBJECT_UNDEFINED;
- command->action = ACTION_CREATE;
- int opt;
- int family;
-
- while ((opt = getopt(argc, argv, "dflcrFLCRSh")) != -1) {
- switch (opt) {
- case 'd':
- command->action = ACTION_DELETE;
- break;
- case 'f':
- command->object = OBJECT_FACE;
- break;
- case 'l':
- command->object = OBJECT_LISTENER;
- break;
- case 'c':
- command->object = OBJECT_CONNECTION;
- break;
- case 'r':
- command->object = OBJECT_ROUTE;
- break;
- case 'F':
- command->action = ACTION_LIST;
- command->object = OBJECT_FACE;
- break;
- case 'L':
- command->action = ACTION_LIST;
- command->object = OBJECT_LISTENER;
- break;
- case 'C':
- command->action = ACTION_LIST;
- command->object = OBJECT_CONNECTION;
- break;
- case 'R':
- command->action = ACTION_LIST;
- command->object = OBJECT_ROUTE;
- break;
- case 'S':
- command->action = ACTION_LIST;
- command->object = OBJECT_STRATEGY;
- break;
- default: /* "h" */
- usage(argv[0]);
- exit(EXIT_SUCCESS);
- }
- }
-
- if (command->object == OBJECT_UNDEFINED) {
- fprintf(stderr, "Missing object specification: connection | listener | route\n");
- return -1;
- }
-
- /* Parse and validate parameters for add/delete */
- switch(command->object) {
- case OBJECT_FACE:
- switch(command->action) {
- case ACTION_CREATE:
- if ((argc - optind != 5) && (argc - optind != 6)) {
- usage_face_create(argv[0], true, false);
- goto ERR_PARAM;
- }
- /* NAME will be autogenerated (and currently not used) */
- //snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- command->face.face.type = face_type_from_str(argv[optind++]);
- if (command->face.face.type == FACE_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->face.face.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->face.face.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->face.face.local_addr) < 0)
- goto ERR_PARAM;
- command->face.face.local_port = atoi(argv[optind++]);
- family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(family) || (command->face.face.family != family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->face.face.remote_addr) < 0)
- goto ERR_PARAM;
- command->face.face.remote_port = atoi(argv[optind++]);
- if (argc != optind) {
- //netdevice_set_name(&command->face.face.netdevice, argv[optind++]);
- command->face.face.netdevice.index = atoi(argv[optind++]);
- }
-
- break;
- case ACTION_DELETE:
- if ((argc - optind != 1) && (argc - optind != 5) && (argc - optind != 6)) {
- usage_face_delete(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- if (argc - optind == 1) {
- /* Id or name */
- if (is_number(argv[optind])) {
- command->face.id = atoi(argv[optind++]);
- snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- //} else if (is_symbolic_name(argv[optind])) {
- // snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else {
- fprintf(stderr, "Invalid argument\n");
- goto ERR_PARAM;
- }
- } else {
- command->face.face.type = face_type_from_str(argv[optind++]);
- if (command->face.face.type == FACE_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->face.face.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->face.face.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->face.face.local_addr) < 0)
- goto ERR_PARAM;
- command->face.face.local_port = atoi(argv[optind++]);
- family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(family) || (command->face.face.family != family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->face.face.remote_addr) < 0)
- goto ERR_PARAM;
- command->face.face.remote_port = atoi(argv[optind++]);
- if (argc != optind) {
- command->face.face.netdevice.index = atoi(argv[optind++]);
- //netdevice_set_name(&command->face.face.netdevice, argv[optind++]);
- }
- }
- break;
-
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_face_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- case OBJECT_ROUTE:
- switch(command->action) {
- case ACTION_CREATE:
- if ((argc - optind != 2) && (argc - optind != 3)) {
- usage_route_create(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- command->route.face_id = atoi(argv[optind++]);
-
- {
- ip_prefix_t prefix;
- ip_prefix_pton(argv[optind++], &prefix);
- command->route.family = prefix.family;
- command->route.remote_addr = prefix.address;
- command->route.len = prefix.len;
- }
-
- if (argc != optind) {
- printf("parse cost\n");
- command->route.cost = atoi(argv[optind++]);
- }
- break;
-
- case ACTION_DELETE:
- if (argc - optind != 2) {
- usage_route_delete(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- command->route.face_id = atoi(argv[optind++]);
-
- {
- ip_prefix_t prefix;
- ip_prefix_pton(argv[optind++], &prefix);
- command->route.family = prefix.family;
- command->route.remote_addr = prefix.address;
- command->route.len = prefix.len;
- }
- break;
-
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_route_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- case OBJECT_STRATEGY:
- switch(command->action) {
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_forwarding_strategy_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- case OBJECT_LISTENER:
- switch(command->action) {
- case ACTION_CREATE:
- if ((argc - optind != 4) && (argc - optind != 5)) {
- usage_listener_create(argv[0], true, false);
- goto ERR_PARAM;
- }
- snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- command->listener.type = connection_type_from_str(argv[optind++]);
- if (command->listener.type == CONNECTION_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->listener.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->listener.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->listener.local_addr) < 0)
- goto ERR_PARAM;
- command->listener.local_port = atoi(argv[optind++]);
- if (argc != optind) {
- snprintf(command->listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]);
- }
- break;
-
- case ACTION_DELETE:
- if ((argc - optind != 1) && (argc - optind != 3) && (argc - optind != 4)) {
- usage_listener_delete(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- if (argc - optind == 1) {
- /* Id or name */
- if (is_number(argv[optind])) {
- command->listener.id = atoi(argv[optind++]);
- snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else if (is_symbolic_name(argv[optind])) {
- snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else {
- fprintf(stderr, "Invalid argument\n");
- goto ERR_PARAM;
- }
- } else {
- command->listener.type = connection_type_from_str(argv[optind++]);
- if (command->listener.type == CONNECTION_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->listener.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->listener.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->listener.local_addr) < 0)
- goto ERR_PARAM;
- command->listener.local_port = atoi(argv[optind++]);
- if (argc != optind) {
- snprintf(command->listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]);
- }
- }
- break;
-
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_listener_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
+ // XXX assert valid object
+ return hc_object_type_snprintf(buffer, size, object->type, &object->as_uint8);
+#if 0
+ switch(object->type) {
case OBJECT_CONNECTION:
- switch(command->action) {
- case ACTION_CREATE:
- /* NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT */
- if ((argc - optind != 6) && (argc - optind != 7)) {
- usage_connection_create(argv[0], true, false);
- goto ERR_PARAM;
- }
- snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- command->connection.type = connection_type_from_str(argv[optind++]);
- if (command->connection.type == CONNECTION_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->connection.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->connection.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->connection.local_addr) < 0)
- goto ERR_PARAM;
- command->connection.local_port = atoi(argv[optind++]);
- family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(family) || (command->connection.family != family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->connection.remote_addr) < 0)
- goto ERR_PARAM;
- command->connection.remote_port = atoi(argv[optind++]);
-
- break;
-
- case ACTION_DELETE:
- if ((argc - optind != 1) && (argc - optind != 5) && (argc - optind != 6)) {
- usage_connection_delete(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- if (argc - optind == 1) {
- /* Id or name */
- if (is_number(argv[optind])) {
- command->connection.id = atoi(argv[optind++]);
- snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else if (is_symbolic_name(argv[optind])) {
- snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else {
- fprintf(stderr, "Invalid argument\n");
- goto ERR_PARAM;
- }
- } else {
- command->connection.type = connection_type_from_str(argv[optind++]);
- if (command->connection.type == CONNECTION_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->connection.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->connection.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->connection.local_addr) < 0)
- goto ERR_PARAM;
- command->connection.local_port = atoi(argv[optind++]);
- family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(family) || (command->connection.family != family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->connection.remote_addr) < 0)
- goto ERR_PARAM;
- command->connection.remote_port = atoi(argv[optind++]);
- }
- break;
-
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_connection_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
-
- return 0;
-
-ERR_PARAM:
-ERR_COMMAND:
- return -1;
-}
-
-int main(int argc, char *argv[])
-{
- hc_data_t * data;
- int rc = 1;
- hc_command_t command = {0};
- char buf_listener[MAXSZ_HC_LISTENER];
- char buf_connection[MAXSZ_HC_CONNECTION];
- char buf_route[MAXSZ_HC_ROUTE];
- char buf_strategy[MAXSZ_HC_STRATEGY];
-
- if (parse_options(argc, argv, &command) < 0)
- die(OPTIONS, "Bad arguments");
-
- hc_sock_t * s = hc_sock_create();
- if (!s)
- die(SOCKET, "Error creating socket.");
-
- if (hc_sock_connect(s) < 0)
- die(CONNECT, "Error connecting to the forwarder.");
-
- switch(command.object) {
- case OBJECT_FACE:
- switch(command.action) {
- case ACTION_CREATE:
- if (hc_face_create(s, &command.face) < 0)
- die(COMMAND, "Error creating face");
- printf("OK\n");
- break;
-
- case ACTION_DELETE:
- if (hc_face_delete(s, &command.face) < 0)
- die(COMMAND, "Error creating face");
- printf("OK\n");
- break;
-
- case ACTION_LIST:
- if (hc_face_list(s, &data) < 0)
- die(COMMAND, "Error getting connections.");
-
- printf("Faces:\n");
- foreach_face(f, data) {
- if (hc_face_snprintf(buf_connection, MAXSZ_HC_FACE, f) >= MAXSZ_HC_FACE)
- die(COMMAND, "Display error");
- printf("[%s] %s\n", f->name, buf_connection);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for connection");
- break;
- }
- break;
-
+ return hc_connection_snprintf(buffer, size, &object->connection);
+ case OBJECT_LISTENER:
+ return hc_listener_snprintf(buffer, size, &object->listener);
case OBJECT_ROUTE:
- switch(command.action) {
- case ACTION_CREATE:
- if (hc_route_create(s, &command.route) < 0)
- die(COMMAND, "Error creating route");
- printf("OK\n");
- break;
-
- case ACTION_DELETE:
- if (hc_route_delete(s, &command.route) < 0)
- die(COMMAND, "Error creating route");
- printf("OK\n");
- break;
-
- case ACTION_LIST:
- if (hc_route_list(s, &data) < 0)
- die(COMMAND, "Error getting routes.");
-
- printf("Routes:\n");
- foreach_route(r, data) {
- if (hc_route_snprintf(buf_route, MAXSZ_HC_ROUTE, r) >= MAXSZ_HC_ROUTE)
- die(COMMAND, "Display error");
- printf("%s\n", buf_route);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for route");
- break;
- }
- break;
-
+ return hc_route_snprintf(buffer, size, &object->route);
+ case OBJECT_FACE:
+ return hc_face_snprintf(buffer, size, &object->face);
case OBJECT_STRATEGY:
- switch(command.action) {
- case ACTION_LIST:
- if (hc_strategy_list(s, &data) < 0)
- die(COMMAND, "Error getting routes.");
-
- printf("Forwarding strategies:\n");
- foreach_strategy(st, data) {
- if (hc_strategy_snprintf(buf_strategy, MAXSZ_HC_STRATEGY, st) >= MAXSZ_HC_STRATEGY)
- die(COMMAND, "Display error");
- printf("%s\n", buf_strategy);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for strategy");
- break;
- }
- break;
-
- case OBJECT_LISTENER:
- switch(command.action) {
- case ACTION_CREATE:
- if (hc_listener_create(s, &command.listener) < 0)
- die(COMMAND, "Error creating listener");
- printf("OK\n");
- break;
- case ACTION_DELETE:
- if (hc_listener_delete(s, &command.listener) < 0)
- die(COMMAND, "Error deleting listener");
- printf("OK\n");
- break;
- break;
- case ACTION_LIST:
- if (hc_listener_list(s, &data) < 0)
- die(COMMAND, "Error getting listeners.");
-
- printf("Listeners:\n");
- foreach_listener(l, data) {
- if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER+17, l) >= MAXSZ_HC_LISTENER)
- die(COMMAND, "Display error");
- printf("[%d] %s\n", l->id, buf_listener);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for listener");
- break;
- }
- break;
-
- case OBJECT_CONNECTION:
- switch(command.action) {
- case ACTION_CREATE:
- if (hc_connection_create(s, &command.connection) < 0)
- die(COMMAND, "Error creating connection");
- printf("OK\n");
- break;
- case ACTION_DELETE:
- if (hc_connection_delete(s, &command.connection) < 0)
- die(COMMAND, "Error creating connection");
- printf("OK\n");
- break;
- case ACTION_LIST:
- if (hc_connection_list(s, &data) < 0)
- die(COMMAND, "Error getting connections.");
-
- printf("Connections:\n");
- foreach_connection(c, data) {
- if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION, c) >= MAXSZ_HC_CONNECTION)
- die(COMMAND, "Display error");
- printf("[%s] %s\n", c->name, buf_connection);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for connection");
- break;
- }
- break;
-
+ return hc_strategy_snprintf(buffer, size, &object->strategy);
+ case OBJECT_POLICY:
+ return hc_policy_snprintf(buffer, size, &object->policy);
+ case OBJECT_PUNTING:
+ return hc_punting_snprintf(buffer, size, &object->punting);
+ case OBJECT_UNDEFINED:
+ case OBJECT_N:
default:
- die(COMMAND, "Unsupported object");
- break;
+ return -1;
}
-
-ERR_COMMAND:
-ERR_CONNECT:
- hc_sock_free(s);
-ERR_SOCKET:
-ERR_OPTIONS:
- return (rc < 0) ? EXIT_FAILURE : EXIT_SUCCESS;
+#endif
}
diff --git a/ctrl/libhicnctrl/src/hicnctrl.c b/ctrl/libhicnctrl/src/hicnctrl.c
new file mode 100644
index 000000000..4be9f196c
--- /dev/null
+++ b/ctrl/libhicnctrl/src/hicnctrl.c
@@ -0,0 +1,842 @@
+/*
+ * 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 cli.c
+ * \brief Command line interface
+ */
+#include <ctype.h> // isalpha isalnum
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h> // getopt
+
+#include <hicn/ctrl.h>
+#include <hicn/util/ip_address.h>
+#include <hicn/util/token.h>
+
+
+#define die(LABEL, MESSAGE) do { \
+ printf(MESSAGE "\n"); \
+ rc = -1; \
+ goto ERR_ ## LABEL; \
+} while(0)
+
+void
+usage_header()
+{
+ fprintf(stderr, "Usage:\n");
+}
+
+void
+usage_face_create(const char * prog, bool header, bool verbose)
+{
+
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -f TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
+ if (verbose)
+ fprintf(stderr, " Create a face on specified address and port.\n");
+}
+
+void
+usage_face_delete(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -df ID\n", prog);
+ //fprintf(stderr, "%s -df NAME\n", prog);
+ fprintf(stderr, "%s -df TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
+ if (verbose)
+ fprintf(stderr, " Delete a face...\n");
+}
+
+void
+usage_face_list(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -F\n", prog);
+ if (verbose)
+ fprintf(stderr, " List all faces.\n");
+}
+
+void
+usage_face(const char * prog, bool header, bool verbose)
+{
+ usage_face_create(prog, header, verbose);
+ usage_face_delete(prog, header, verbose);
+ usage_face_list(prog, header, verbose);
+}
+
+void
+usage_route_create(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -r FACE_ID PREFIX [COST]\n", prog);
+ //fprintf(stderr, "%s -r [FACE_ID|NAME] PREFIX [COST]\n", prog);
+ if (verbose)
+ fprintf(stderr, " Create a route...\n");
+}
+
+void
+usage_route_delete(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -dr FACE_ID PREFIX\n", prog);
+ //fprintf(stderr, "%s -dr [FACE_ID|NAME] PREFIX\n", prog);
+ if (verbose)
+ fprintf(stderr, " Delete a route...\n");
+}
+
+void
+usage_route_list(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -R\n", prog);
+ if (verbose)
+ fprintf(stderr, " List all routes.\n");
+}
+
+void
+usage_route(const char * prog, bool header, bool verbose)
+{
+ usage_route_create(prog, header, verbose);
+ usage_route_delete(prog, header, verbose);
+ usage_route_list(prog, header, verbose);
+}
+
+void
+usage_forwarding_strategy_create(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+}
+void
+usage_forwarding_strategy_delete(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+}
+
+void
+usage_forwarding_strategy_list(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -S\n", prog);
+ if (verbose)
+ fprintf(stderr, " List all availble forwarding strategies.\n");
+}
+
+void
+usage_forwarding_strategy(const char * prog, bool header, bool verbose)
+{
+ usage_forwarding_strategy_create(prog, header, verbose);
+ usage_forwarding_strategy_delete(prog, header, verbose);
+ usage_forwarding_strategy_list(prog, header, verbose);
+}
+
+void
+usage_listener_create(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -l NAME TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", prog);
+ if (verbose)
+ fprintf(stderr, " Create a listener on specified address and port.\n");
+}
+
+void
+usage_listener_delete(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -dl ID\n", prog);
+ fprintf(stderr, "%s -dl NAME\n", prog);
+ fprintf(stderr, "%s -dl TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", prog);
+ if (verbose)
+ fprintf(stderr, " Delete a listener...\n");
+}
+
+void
+usage_listener_list(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -L\n", prog);
+ if (verbose)
+ fprintf(stderr, " List all listeners.\n");
+}
+
+void
+usage_listener(const char * prog, bool header, bool verbose)
+{
+ usage_listener_create(prog, header, verbose);
+ usage_listener_delete(prog, header, verbose);
+ usage_listener_list(prog, header, verbose);
+}
+void
+usage_connection_create(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -c NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
+ if (verbose)
+ fprintf(stderr, " Create a connection on specified address and port.\n");
+}
+
+void
+usage_connection_delete(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -dc ID\n", prog);
+ fprintf(stderr, "%s -dc NAME\n", prog);
+ fprintf(stderr, "%s -dc TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
+ if (verbose)
+ fprintf(stderr, " Delete a connection...\n");
+}
+
+void
+usage_connection_list(const char * prog, bool header, bool verbose)
+{
+ if (header)
+ usage_header();
+ fprintf(stderr, "%s -C\n", prog);
+ if (verbose)
+ fprintf(stderr, " List all connections.\n");
+}
+
+void
+usage_connection(const char * prog, bool header, bool verbose)
+{
+ usage_connection_create(prog, header, verbose);
+ usage_connection_delete(prog, header, verbose);
+ usage_connection_list(prog, header, verbose);
+}
+
+void usage(const char * prog)
+{
+ fprintf(stderr, "Usage: %s [ [-d] [-f|-l|-c|-r] PARAMETERS | [-F|-L|-C|-R] ]\n", prog);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "High-level commands\n");
+ fprintf(stderr, "\n");
+ usage_face(prog, false, true);
+ usage_route(prog, false, true);
+ usage_forwarding_strategy(prog, false, true);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Low level commands (hicn-light specific)\n");
+ fprintf(stderr, "\n");
+ usage_listener(prog, false, true);
+ usage_connection(prog, false, true);
+}
+
+/**
+ * Return true if string is purely an integer
+ */
+static inline
+bool
+is_number(const char *string) {
+ size_t len = strlen(string);
+ for (size_t i = 0; i < len; i++)
+ if (!isdigit(string[i]))
+ return false;
+ return true;
+}
+
+/**
+ * A symbolic name must be at least 1 character and must begin with an alpha.
+ * The remainder must be an alphanum.
+ */
+static inline
+bool
+is_symbolic_name(const char *name)
+{
+ size_t len = strlen(name);
+ if (len <= 0)
+ return false;
+ if (!isalpha(name[0]))
+ return false;
+ for (size_t i = 1; i < len; i++) {
+ if (!isalnum(name[i]))
+ return false;
+ }
+ return true;
+}
+
+face_type_t
+face_type_from_str(const char * str)
+{
+#define _(x) \
+ if (strcasecmp(str, STRINGIZE(x)) == 0) \
+ return FACE_TYPE_ ## x; \
+ else
+foreach_face_type
+#undef _
+ return FACE_TYPE_UNDEFINED;
+}
+
+
+int
+parse_options(int argc, char *argv[], hc_command_t * command)
+{
+ command->object.type = OBJECT_UNDEFINED;
+ command->action = ACTION_CREATE;
+ int opt;
+ int family;
+
+ while ((opt = getopt(argc, argv, "dflcrFLCRSh")) != -1) {
+ switch (opt) {
+ case 'd':
+ command->action = ACTION_DELETE;
+ break;
+ case 'f':
+ command->object.type = OBJECT_FACE;
+ break;
+ case 'l':
+ command->object.type = OBJECT_LISTENER;
+ break;
+ case 'c':
+ command->object.type = OBJECT_CONNECTION;
+ break;
+ case 'r':
+ command->object.type = OBJECT_ROUTE;
+ break;
+ case 'F':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_FACE;
+ break;
+ case 'L':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_LISTENER;
+ break;
+ case 'C':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_CONNECTION;
+ break;
+ case 'R':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_ROUTE;
+ break;
+ case 'S':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_STRATEGY;
+ break;
+ default: /* "h" */
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+ }
+ }
+
+ if (command->object.type == OBJECT_UNDEFINED) {
+ fprintf(stderr, "Missing object specification: connection | listener | route\n");
+ return -1;
+ }
+
+ /* Parse and validate parameters for add/delete */
+ switch(command->object.type) {
+ case OBJECT_FACE:
+ switch(command->action) {
+ case ACTION_CREATE:
+ if ((argc - optind != 5) && (argc - optind != 6)) {
+ usage_face_create(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ /* NAME will be autogenerated (and currently not used) */
+ //snprintf(command->object.face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ command->object.face.face.type = face_type_from_str(argv[optind++]);
+ if (command->object.face.face.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.face.face.family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.face.face.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->object.face.face.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.face.face.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) || (command->object.face.face.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->object.face.face.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->object.face.face.remote_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ //netdevice_set_name(&command->object.face.face.netdevice, argv[optind++]);
+ command->object.face.face.netdevice.index = atoi(argv[optind++]);
+ }
+
+ break;
+ case ACTION_DELETE:
+ if ((argc - optind != 1) && (argc - optind != 5) && (argc - optind != 6)) {
+ usage_face_delete(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ if (argc - optind == 1) {
+ /* Id or name */
+ if (is_number(argv[optind])) {
+ command->object.face.id = atoi(argv[optind++]);
+ snprintf(command->object.face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ //} else if (is_symbolic_name(argv[optind])) {
+ // snprintf(command->object.face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ } else {
+ fprintf(stderr, "Invalid argument\n");
+ goto ERR_PARAM;
+ }
+ } else {
+ command->object.face.face.type = face_type_from_str(argv[optind++]);
+ if (command->object.face.face.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.face.face.family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.face.face.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->object.face.face.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.face.face.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) || (command->object.face.face.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->object.face.face.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->object.face.face.remote_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ command->object.face.face.netdevice.index = atoi(argv[optind++]);
+ //netdevice_set_name(&command->object.face.face.netdevice, argv[optind++]);
+ }
+ }
+ break;
+
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_face_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ break;
+ }
+ break;
+
+ case OBJECT_ROUTE:
+ switch(command->action) {
+ case ACTION_CREATE:
+ if ((argc - optind != 2) && (argc - optind != 3)) {
+ usage_route_create(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ command->object.route.face_id = atoi(argv[optind++]);
+
+ {
+ ip_prefix_t prefix;
+ ip_prefix_pton(argv[optind++], &prefix);
+ command->object.route.family = prefix.family;
+ command->object.route.remote_addr = prefix.address;
+ command->object.route.len = prefix.len;
+ }
+
+ if (argc != optind) {
+ printf("parse cost\n");
+ command->object.route.cost = atoi(argv[optind++]);
+ }
+ break;
+
+ case ACTION_DELETE:
+ if (argc - optind != 2) {
+ usage_route_delete(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ command->object.route.face_id = atoi(argv[optind++]);
+
+ {
+ ip_prefix_t prefix;
+ ip_prefix_pton(argv[optind++], &prefix);
+ command->object.route.family = prefix.family;
+ command->object.route.remote_addr = prefix.address;
+ command->object.route.len = prefix.len;
+ }
+ break;
+
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_route_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ break;
+ }
+ break;
+
+ case OBJECT_STRATEGY:
+ switch(command->action) {
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_forwarding_strategy_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+ default:
+ goto ERR_COMMAND;
+ break;
+ }
+ break;
+
+ case OBJECT_LISTENER:
+ switch(command->action) {
+ case ACTION_CREATE:
+ if ((argc - optind != 4) && (argc - optind != 5)) {
+ usage_listener_create(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ snprintf(command->object.listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ command->object.listener.type = connection_type_from_str(argv[optind++]);
+ if (command->object.listener.type == CONNECTION_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.listener.family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.listener.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->object.listener.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.listener.local_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ snprintf(command->object.listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]);
+ }
+ break;
+
+ case ACTION_DELETE:
+ if ((argc - optind != 1) && (argc - optind != 3) && (argc - optind != 4)) {
+ usage_listener_delete(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ if (argc - optind == 1) {
+ /* Id or name */
+ if (is_number(argv[optind])) {
+ command->object.listener.id = atoi(argv[optind++]);
+ snprintf(command->object.listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ } else if (is_symbolic_name(argv[optind])) {
+ snprintf(command->object.listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ } else {
+ fprintf(stderr, "Invalid argument\n");
+ goto ERR_PARAM;
+ }
+ } else {
+ command->object.listener.type = connection_type_from_str(argv[optind++]);
+ if (command->object.listener.type == CONNECTION_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.listener.family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.listener.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->object.listener.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.listener.local_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ snprintf(command->object.listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]);
+ }
+ }
+ break;
+
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_listener_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ break;
+ }
+ break;
+
+ case OBJECT_CONNECTION:
+ switch(command->action) {
+ case ACTION_CREATE:
+ /* NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT */
+ if ((argc - optind != 6) && (argc - optind != 7)) {
+ usage_connection_create(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ snprintf(command->object.connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ command->object.connection.type = connection_type_from_str(argv[optind++]);
+ if (command->object.connection.type == CONNECTION_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.connection.family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.connection.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->object.connection.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.connection.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) || (command->object.connection.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->object.connection.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->object.connection.remote_port = atoi(argv[optind++]);
+
+ break;
+
+ case ACTION_DELETE:
+ if ((argc - optind != 1) && (argc - optind != 5) && (argc - optind != 6)) {
+ usage_connection_delete(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ if (argc - optind == 1) {
+ /* Id or name */
+ if (is_number(argv[optind])) {
+ command->object.connection.id = atoi(argv[optind++]);
+ snprintf(command->object.connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ } else if (is_symbolic_name(argv[optind])) {
+ snprintf(command->object.connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ } else {
+ fprintf(stderr, "Invalid argument\n");
+ goto ERR_PARAM;
+ }
+ } else {
+ command->object.connection.type = connection_type_from_str(argv[optind++]);
+ if (command->object.connection.type == CONNECTION_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.connection.family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.connection.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->object.connection.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.connection.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) || (command->object.connection.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->object.connection.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->object.connection.remote_port = atoi(argv[optind++]);
+ }
+ break;
+
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_connection_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ break;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ break;
+ }
+
+ return 0;
+
+ERR_PARAM:
+ERR_COMMAND:
+ return -1;
+}
+
+int main(int argc, char *argv[])
+{
+ hc_data_t * data;
+ int rc = 1;
+ hc_command_t command = {0};
+ char buf_listener[MAXSZ_HC_LISTENER];
+ char buf_connection[MAXSZ_HC_CONNECTION];
+ char buf_route[MAXSZ_HC_ROUTE];
+ char buf_strategy[MAXSZ_HC_STRATEGY];
+
+ if (parse_options(argc, argv, &command) < 0)
+ die(OPTIONS, "Bad arguments");
+
+ hc_sock_t * s = hc_sock_create();
+ if (!s)
+ die(SOCKET, "Error creating socket.");
+
+ if (hc_sock_connect(s) < 0)
+ die(CONNECT, "Error connecting to the forwarder.");
+
+ switch(command.object.type) {
+ case OBJECT_FACE:
+ switch(command.action) {
+ case ACTION_CREATE:
+ if (hc_face_create(s, &command.object.face) < 0)
+ die(COMMAND, "Error creating face");
+ printf("OK\n");
+ break;
+
+ case ACTION_DELETE:
+ if (hc_face_delete(s, &command.object.face) < 0)
+ die(COMMAND, "Error creating face");
+ printf("OK\n");
+ break;
+
+ case ACTION_LIST:
+ if (hc_face_list(s, &data) < 0)
+ die(COMMAND, "Error getting connections.");
+
+ printf("Faces:\n");
+ foreach_face(f, data) {
+ if (hc_face_snprintf(buf_connection, MAXSZ_HC_FACE, f) >= MAXSZ_HC_FACE)
+ die(COMMAND, "Display error");
+ printf("[%s] %s\n", f->name, buf_connection);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for connection");
+ break;
+ }
+ break;
+
+ case OBJECT_ROUTE:
+ switch(command.action) {
+ case ACTION_CREATE:
+ if (hc_route_create(s, &command.object.route) < 0)
+ die(COMMAND, "Error creating route");
+ printf("OK\n");
+ break;
+
+ case ACTION_DELETE:
+ if (hc_route_delete(s, &command.object.route) < 0)
+ die(COMMAND, "Error creating route");
+ printf("OK\n");
+ break;
+
+ case ACTION_LIST:
+ if (hc_route_list(s, &data) < 0)
+ die(COMMAND, "Error getting routes.");
+
+ printf("Routes:\n");
+ foreach_route(r, data) {
+ if (hc_route_snprintf(buf_route, MAXSZ_HC_ROUTE, r) >= MAXSZ_HC_ROUTE)
+ die(COMMAND, "Display error");
+ printf("%s\n", buf_route);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for route");
+ break;
+ }
+ break;
+
+ case OBJECT_STRATEGY:
+ switch(command.action) {
+ case ACTION_LIST:
+ if (hc_strategy_list(s, &data) < 0)
+ die(COMMAND, "Error getting routes.");
+
+ printf("Forwarding strategies:\n");
+ foreach_strategy(st, data) {
+ if (hc_strategy_snprintf(buf_strategy, MAXSZ_HC_STRATEGY, st) >= MAXSZ_HC_STRATEGY)
+ die(COMMAND, "Display error");
+ printf("%s\n", buf_strategy);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for strategy");
+ break;
+ }
+ break;
+
+ case OBJECT_LISTENER:
+ switch(command.action) {
+ case ACTION_CREATE:
+ if (hc_listener_create(s, &command.object.listener) < 0)
+ die(COMMAND, "Error creating listener");
+ printf("OK\n");
+ break;
+ case ACTION_DELETE:
+ if (hc_listener_delete(s, &command.object.listener) < 0)
+ die(COMMAND, "Error deleting listener");
+ printf("OK\n");
+ break;
+ break;
+ case ACTION_LIST:
+ if (hc_listener_list(s, &data) < 0)
+ die(COMMAND, "Error getting listeners.");
+
+ printf("Listeners:\n");
+ foreach_listener(l, data) {
+ if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER+17, l) >= MAXSZ_HC_LISTENER)
+ die(COMMAND, "Display error");
+ printf("[%d] %s\n", l->id, buf_listener);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for listener");
+ break;
+ }
+ break;
+
+ case OBJECT_CONNECTION:
+ switch(command.action) {
+ case ACTION_CREATE:
+ if (hc_connection_create(s, &command.object.connection) < 0)
+ die(COMMAND, "Error creating connection");
+ printf("OK\n");
+ break;
+ case ACTION_DELETE:
+ if (hc_connection_delete(s, &command.object.connection) < 0)
+ die(COMMAND, "Error creating connection");
+ printf("OK\n");
+ break;
+ case ACTION_LIST:
+ if (hc_connection_list(s, &data) < 0)
+ die(COMMAND, "Error getting connections.");
+
+ printf("Connections:\n");
+ foreach_connection(c, data) {
+ if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION, c) >= MAXSZ_HC_CONNECTION)
+ die(COMMAND, "Display error");
+ printf("[%s] %s\n", c->name, buf_connection);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for connection");
+ break;
+ }
+ break;
+
+ default:
+ die(COMMAND, "Unsupported object");
+ break;
+ }
+
+ERR_COMMAND:
+ERR_CONNECT:
+ hc_sock_free(s);
+ERR_SOCKET:
+ERR_OPTIONS:
+ return (rc < 0) ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/hicn-light/CMakeLists.txt b/hicn-light/CMakeLists.txt
index 42e7d0a01..fa8c6664e 100644
--- a/hicn-light/CMakeLists.txt
+++ b/hicn-light/CMakeLists.txt
@@ -35,6 +35,8 @@ include( CTest )
include( detectCacheSize )
if(NOT WIN32)
+ # NOTE: -fPIC -shared is needed to preserve constructors when targetting a
+ # shared library
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
else ()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996")
@@ -52,28 +54,32 @@ include(WindowsMacros)
set(HICN_LIGHT hicn-light CACHE INTERNAL "" FORCE)
set(HICN_LIGHT_CONTROL ${HICN_LIGHT}-control CACHE INTERNAL "" FORCE)
+set(HICN_LIGHT_SHELL ${HICN_LIGHT}-shell CACHE INTERNAL "" FORCE)
set(HICN_LIGHT_DAEMON ${HICN_LIGHT}-daemon CACHE INTERNAL "" FORCE)
find_package_wrapper(LibEvent REQUIRED)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
find_package_wrapper(Libhicn REQUIRED)
+ find_package_wrapper(Libhicnctrl REQUIRED)
else()
if (DISABLE_SHARED_LIBRARIES)
if (WIN32)
- set(HICN_LIBRARIES ${LIBEVENT_STATIC} ${LIBHICN_STATIC})
+ set(HICN_LIBRARIES ${LIBEVENT_STATIC} ${LIBHICN_STATIC} ${LIBHICNCTRL_STATIC})
else ()
- set(HICN_LIBRARIES ${LIBEVENT_STATIC} ${LIBHICN_STATIC} log)
+ set(HICN_LIBRARIES ${LIBEVENT_STATIC} ${LIBHICN_STATIC} ${LIBHICNCTRL_STATIC} log)
endif ()
list(APPEND DEPENDENCIES
${LIBEVENT_STATIC}
${LIBHICN_STATIC}
+ ${LIBHICNCTRL_STATIC}
)
else ()
set(HICN_LIBRARIES ${LIBHICN_SHARED})
list(APPEND DEPENDENCIES
${LIBEVENT_SHARED}
${LIBHICN_SHARED}
+ ${LIBHICNCTRL_SHARED}
)
endif ()
endif()
@@ -88,6 +94,7 @@ set(LIBHICN_LIGHT_SHARED ${LIBHICN_LIGHT}.shared)
set(HICN_LIGHT_LINK_LIBRARIES
${HICN_LIBRARIES}
+ ${LIBHICNCTRL_LIBRARIES}
${LIBEVENT_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${WINDOWS_LIBRARIES}
@@ -97,6 +104,7 @@ set(HICN_LIGHT_LINK_LIBRARIES
# Include dirs -- Order does matter!
list(APPEND HICN_LIGHT_INCLUDE_DIRS
${HICN_INCLUDE_DIRS}
+ ${LIBHICNCTRL_INCLUDE_DIRS}
${LIBEVENT_INCLUDE_DIRS}
${WINDOWS_INCLUDE_DIRS}
)
diff --git a/hicn-light/src/hicn/CMakeLists.txt b/hicn-light/src/hicn/CMakeLists.txt
index 4ecd5e2a0..ff1f2d4fb 100644
--- a/hicn-light/src/hicn/CMakeLists.txt
+++ b/hicn-light/src/hicn/CMakeLists.txt
@@ -32,7 +32,7 @@ endif()
if (NOT DISABLE_EXECUTABLES)
- add_subdirectory(command_line)
+ add_subdirectory(cli)
endif()
add_subdirectory(base)
diff --git a/hicn-light/src/hicn/base/bitmap.h b/hicn-light/src/hicn/base/bitmap.h
index 4a78af567..ebc3dddbb 100644
--- a/hicn-light/src/hicn/base/bitmap.h
+++ b/hicn-light/src/hicn/base/bitmap.h
@@ -43,8 +43,8 @@ typedef uint_fast32_t bitmap_t;
* @param[in] max_size Bitmap max_size
*/
#define bitmap_init(bitmap, init_size, max_size) \
- vector_init(bitmap, next_pow2(init_size / BITMAP_WIDTH(bitmap)), \
- max_size == 0 ? 0 : next_pow2(max_size / BITMAP_WIDTH(bitmap)))
+ vector_init(bitmap, next_pow2((init_size) / BITMAP_WIDTH(bitmap)), \
+ max_size == 0 ? 0 : next_pow2((max_size) / BITMAP_WIDTH(bitmap)))
/*
* @brief Ensures a bitmap is sufficiently large to hold an element at the
@@ -156,7 +156,7 @@ bitmap_set_range(bitmap_t * bitmap, off_t from, off_t to)
*/
if ((pos_to != BITMAP_WIDTH(bitmap) - 1) && (offset_to != offset_from)) {
size_t to_start = MAX(from, offset_to * BITMAP_WIDTH(bitmap));
- for (size_t k = to_start; k < to; k++) {
+ for (size_t k = to_start; k < (size_t) to; k++) {
if (bitmap_set(bitmap, k) < 0)
goto END;
}
diff --git a/hicn-light/src/hicn/base/pool.c b/hicn-light/src/hicn/base/pool.c
index 31abb13f1..cb650b9e5 100644
--- a/hicn-light/src/hicn/base/pool.c
+++ b/hicn-light/src/hicn/base/pool.c
@@ -16,7 +16,7 @@
/**
* \file pool.c
* \brief Implementation of fixed-size pool allocator.
- *
+ *
* NOTE:
* - Ideally, we should have a single realloc per resize, that would encompass
* both the free indices vector and bitmap, by nesting data structures. Because
@@ -81,6 +81,10 @@ ERR_MAX_SIZE:
void
_pool_free(void ** pool_ptr)
{
+ pool_hdr_t * ph = pool_hdr(*pool_ptr);
+ vector_free(ph->free_indices);
+ bitmap_free(ph->free_bitmap);
+
free(pool_hdr(*pool_ptr));
*pool_ptr = NULL;
}
diff --git a/hicn-light/src/hicn/base/test/CMakeLists.txt b/hicn-light/src/hicn/base/test/CMakeLists.txt
index 351e7bd34..cdf6ed11b 100644
--- a/hicn-light/src/hicn/base/test/CMakeLists.txt
+++ b/hicn-light/src/hicn/base/test/CMakeLists.txt
@@ -15,9 +15,9 @@ foreach(test ${TESTS})
build_executable(${test}
NO_INSTALL
SOURCES ${test}.cc
- LINK_LIBRARIES ${LIBHICN_LIGHT_SHARED} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
+ LINK_LIBRARIES ${LIBHICN_LIGHT_SHARED} ${LIBHICNCTRL_SHARED} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
INCLUDE_DIRS ${HICN_LIGHT_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
- DEPENDS gtest ${LIBHICN_LIGHT_SHARED}
+ DEPENDS gtest ${LIBHICNCTRL_SHARED} ${LIBHICN_LIGHT_SHARED}
COMPONENT ${HICN_LIGHT}
DEFINITIONS "${COMPILER_DEFINITIONS}"
)
diff --git a/hicn-light/src/hicn/base/test/test-bitmap.cc b/hicn-light/src/hicn/base/test/test-bitmap.cc
index 1a62edba3..d1b335ace 100644
--- a/hicn-light/src/hicn/base/test/test-bitmap.cc
+++ b/hicn-light/src/hicn/base/test/test-bitmap.cc
@@ -57,32 +57,32 @@ TEST_F(BitmapTest, BitmapAllocation)
* Bitmap should have been allocated with a size rounded to the next power
* of 2
*/
- EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL);
/* By default, no element should be set */
EXPECT_FALSE(bitmap_is_set(bitmap, 0));
EXPECT_TRUE(bitmap_is_unset(bitmap, 0));
- EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL);
EXPECT_FALSE(bitmap_is_set(bitmap, size_not_pow2 - 1));
EXPECT_TRUE(bitmap_is_unset(bitmap, size_not_pow2 - 1));
/* Bitmap should not have been reallocated */
- EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL);
/* After setting a bit after the end, bitmap should have been reallocated */
bitmap_set(bitmap, sizeof(bitmap[0]) * 8 - 1);
- EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL);
/* After setting a bit after the end, bitmap should have been reallocated */
rc = bitmap_set(bitmap, sizeof(bitmap[0]) * 8);
EXPECT_GE(rc, 0);
- EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2UL);
rc = bitmap_set(bitmap, sizeof(bitmap[0]) * 8 + 1);
EXPECT_GE(rc, 0);
- EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2UL);
bitmap_free(bitmap);
@@ -90,7 +90,7 @@ TEST_F(BitmapTest, BitmapAllocation)
/* Limiting test for allocation size */
bitmap_init(bitmap, size_pow2, 0);
- EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL);
bitmap_free(bitmap);
}
diff --git a/hicn-light/src/hicn/base/test/test-pool.cc b/hicn-light/src/hicn/base/test/test-pool.cc
index 1146ef2b7..f87ff65dd 100644
--- a/hicn-light/src/hicn/base/test/test-pool.cc
+++ b/hicn-light/src/hicn/base/test/test-pool.cc
@@ -56,7 +56,7 @@ TEST_F(PoolTest, PoolAllocation)
/* Check that free indices and bitmaps are correctly initialize */
off_t * fi = pool_get_free_indices(pool);
EXPECT_EQ(vector_len(fi), pool_size);
- EXPECT_EQ(fi[0], pool_size - 1);
+ EXPECT_EQ(fi[0], (long) (pool_size - 1));
EXPECT_EQ(fi[pool_size - 1], 0);
/* The allocated size of the underlying vector should be the next power of two */
@@ -89,12 +89,12 @@ TEST_F(PoolTest, PoolAllocation)
rc = pool_get(pool, elt);
EXPECT_GE(rc, 0);
- EXPECT_EQ(vector_len(fi), 1);
+ EXPECT_EQ(vector_len(fi), 1UL);
EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 2));
rc = pool_get(pool, elt);
EXPECT_GE(rc, 0);
- EXPECT_EQ(vector_len(fi), 0);
+ EXPECT_EQ(vector_len(fi), 0UL);
EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 1));
/*
@@ -155,6 +155,21 @@ TEST_F(PoolTest, PoolPut)
pool_free(pool);
}
+// TODO: this test fails, there is a problem when N = n*64
+// (i.e. when a bitmap reallocation occurs)
+TEST_F(PoolTest, PoolGetForceBitmapRealloc)
+{
+ const int N = 64;
+ int *elts[N];
+ int *elt = NULL;
+ pool_init(pool, N, 0);
+
+ for (int i = 0; i < N; i++)
+ pool_get(pool, elts[i]);
+ pool_get(pool, elt);
+
+ pool_free(pool);
+}
int main(int argc, char **argv)
{
diff --git a/hicn-light/src/hicn/base/test/test-vector.cc b/hicn-light/src/hicn/base/test/test-vector.cc
index 59571b053..aaec7a92c 100644
--- a/hicn-light/src/hicn/base/test/test-vector.cc
+++ b/hicn-light/src/hicn/base/test/test-vector.cc
@@ -49,15 +49,15 @@ TEST_F(VectorTest, VectorAllocate)
vector_init(vector, DEFAULT_SIZE, 0);
/* Allocated size should be the next power of two */
- EXPECT_EQ(vector_get_alloc_size(vector), 16);
+ EXPECT_EQ(vector_get_alloc_size(vector), 16UL);
/* Setting elements within the allocated size should not trigger a resize */
vector_ensure_pos(vector, 15);
- EXPECT_EQ(vector_get_alloc_size(vector), 16);
+ EXPECT_EQ(vector_get_alloc_size(vector), 16UL);
/* Setting elements after should through */
vector_ensure_pos(vector, 16);
- EXPECT_EQ(vector_get_alloc_size(vector), 32);
+ EXPECT_EQ(vector_get_alloc_size(vector), 32UL);
/* Check that free indices and bitmaps are correctly updated */
diff --git a/hicn-light/src/hicn/base/vector.h b/hicn-light/src/hicn/base/vector.h
index ff12e6ee6..b369086fc 100644
--- a/hicn-light/src/hicn/base/vector.h
+++ b/hicn-light/src/hicn/base/vector.h
@@ -129,7 +129,7 @@ int
_vector_ensure_pos(void ** vector_ptr, size_t elt_size, off_t pos)
{
vector_hdr_t * vh = vector_hdr(*vector_ptr);
- if (pos >= vh->alloc_size)
+ if (pos >= (off_t) vh->alloc_size)
return _vector_resize(vector_ptr, elt_size, pos + 1);
return 0;
}
diff --git a/hicn-light/src/hicn/cli/CMakeLists.txt b/hicn-light/src/hicn/cli/CMakeLists.txt
new file mode 100644
index 000000000..3f9906b19
--- /dev/null
+++ b/hicn-light/src/hicn/cli/CMakeLists.txt
@@ -0,0 +1,56 @@
+# Copyright (c) 2017-2020 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if (NOT DISABLE_EXECUTABLES)
+
+ list(APPEND CONTROLLER_SRC
+ color.c
+ hicnc.c
+ )
+
+ build_executable(${HICN_LIGHT_CONTROL}
+ SOURCES ${CONTROLLER_SRC}
+#LINK_LIBRARIES -Wl,--whole-archive ${LIBHICN_LIGHT_STATIC} -Wl,--no-whole-archive ${LIBHICNCTRL_STATIC}
+ LINK_LIBRARIES ${LIBHICN_LIGHT_SHARED} ${LIBHICNCTRL_STATIC}
+ DEPENDS ${LIBHICN_LIGHT_STATIC}
+ COMPONENT ${HICN_LIGHT}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ )
+
+ list(APPEND SHELL_SRC
+ color.c
+ hicns.c
+ )
+
+ # XXX here linking to libhicnctrl should be sufficient
+ build_executable(${HICN_LIGHT_SHELL}
+ SOURCES ${SHELL_SRC}
+ LINK_LIBRARIES ${LIBHICN_LIGHT_SHARED} ${LIBHICNCTRL_STATIC}
+ DEPENDS ${LIBHICN_LIGHT_STATIC}
+ COMPONENT ${HICN_LIGHT}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ )
+
+ list(APPEND DAEMON_SRC
+ color.c
+ hicnd.c
+ )
+
+ build_executable(${HICN_LIGHT_DAEMON}
+ SOURCES ${DAEMON_SRC}
+ LINK_LIBRARIES ${LIBHICN_LIGHT_SHARED} ${LIBHICNCTRL_STATIC}
+ DEPENDS ${LIBHICN_LIGHT_STATIC}
+ COMPONENT ${HICN_LIGHT}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ )
+endif ()
diff --git a/hicn-light/src/hicn/cli/color.c b/hicn-light/src/hicn/cli/color.c
new file mode 100644
index 000000000..2fff2ead6
--- /dev/null
+++ b/hicn-light/src/hicn/cli/color.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include "color.h"
+
+#ifndef _WIN32
+
+void
+vprintfc(color_t color, const char * fmt, va_list ap)
+{
+ char * color_s;
+ switch(color) {
+#define _(x, y, z) \
+ case COLOR_ ## x: \
+ color_s = y; \
+ break;
+ foreach_color
+#undef _
+
+ case COLOR_UNDEFINED:
+ case COLOR_N:
+ color_s = "";
+ break;
+ }
+ printf("%s", color_s);
+ vprintf(fmt, ap);
+}
+#else
+void
+vprintfc(color_t color, const char * fmt, va_list ap)
+{
+ int color_id;
+ switch(color) {
+#define _(x, y, z) \
+ case COLOR_ ## x: \
+ color_id = z; \
+ break;
+ foreach_color
+#undef _
+
+ case COLOR_UNDEFINED:
+ case COLOR_N:
+ color_id = 0;
+ break;
+ }
+ HANDLE hConsole = NULL;
+ WORD currentConsoleAttr;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (GetConsoleScreenBufferInfo(hConsole, &csbi))
+ currentConsoleAttr = csbi.wAttributes;
+ if (color_id != 0)
+ SetConsoleTextAttribute(hConsole, color_id);
+ fprintf("%s", color);
+ vfprintf(fmt, ap);
+ SetConsoleTextAttribute(hConsole, currentConsoleAttr);
+}
+#endif
+
+void
+printfc(color_t color, const char * fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vprintfc(color, fmt, ap);
+ va_end(ap);
+}
diff --git a/hicn-light/src/hicn/cli/color.h b/hicn-light/src/hicn/cli/color.h
new file mode 100644
index 000000000..763666f18
--- /dev/null
+++ b/hicn-light/src/hicn/cli/color.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HICNLIGHT_COLOR
+#define HICNLIGHT_COLOR
+
+#include <stdarg.h>
+
+/*
+ * Format : color_name, escape sequence, windows id
+ */
+#define foreach_color \
+ _(RED, "\033[0;31m", 4) \
+ _(WHITE, "\033[0m", 7)
+
+typedef enum {
+ COLOR_UNDEFINED,
+#define _(x, y, z) COLOR_ ## x,
+ foreach_color
+#undef _
+ COLOR_N,
+} color_t;
+
+#define IS_VALID_COLOR(color) \
+ ((color != COLOR_UNDEFINED) && (color != COLOR_N))
+
+void vprintfc(color_t color, const char * fmt, va_list ap);
+
+void printfc(color_t color, const char * fmt, ...);
+
+#endif /* HICNLIGHT_COLOR */
diff --git a/hicn-light/src/hicn/cli/hicnc.c b/hicn-light/src/hicn/cli/hicnc.c
new file mode 100644
index 000000000..d6c7c4180
--- /dev/null
+++ b/hicn-light/src/hicn/cli/hicnc.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <limits.h> // LONG_MAX, LONG_MIN
+#include <hicn/ctrl.h>
+
+#ifndef _WIN32
+#include <getopt.h>
+#endif
+
+#include "color.h"
+#include "../config/parse.h"
+
+#define PORT 9695
+
+static
+struct option longFormOptions[] = {
+ {"help", no_argument, 0, 'h'},
+ {"server", required_argument, 0, 'S'},
+ {"port", required_argument, 0, 'P'},
+ {0, 0, 0, 0}};
+
+static void usage(char *prog) {
+ printf("%s: portable hICN forwarder\n", prog);
+ printf("\n");
+ printf("Usage: %s COMMAND [PARAMETERS]\n", prog);
+ printf("\n");
+ printf(" %s -h This help screen.\n", prog);
+ printf(" %s help Obtain a list of available commands.\n", prog);
+ printf("\n");
+}
+
+int
+main(int argc, char * const * argv)
+{
+ /* Parse commandline */
+ char *server_ip = NULL;
+ uint16_t server_port = 0;
+
+ for(;;) {
+ // getopt_long stores the option index here.
+ int optind = 0;
+
+ int c = getopt_long(argc, argv, "hS:P:", longFormOptions, &optind);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'S':
+ server_ip = optarg;
+ break;
+
+ case 'P':
+ {
+ char *endptr;
+ long val = strtol(optarg, &endptr, 10);
+
+ errno = 0; /* To distinguish success/failure after call */
+
+ if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
+ || (errno != 0 && val == 0)) {
+ perror("strtol");
+ exit(EXIT_FAILURE);
+ }
+
+ if (endptr == optarg) {
+ fprintf(stderr, "No digits were found.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (*endptr != '\0') {
+ fprintf(stderr, "Spurious characters after number: %s.\n", endptr);
+ exit(EXIT_FAILURE);
+ }
+
+ if ((val < 1) || (val > 65535)) {
+ fprintf(stderr, "Invalid port number: %ld.\n", val);
+ exit(EXIT_FAILURE);
+ }
+
+ server_port = val;
+ break;
+ }
+
+ case 'h':
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+
+ default:
+ fprintf(stderr, "Invalid argument.\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Parse */
+ char * param = argv[optind];
+ for (; optind < argc - 1; optind++) {
+ char * arg = argv[optind];
+ arg[strlen(arg)] = ' ';
+ }
+
+ if (!param) {
+ usage(argv[0]);
+ goto ERR_PARAM;
+ }
+
+ hc_command_t command;
+ if (parse(param, &command) < 0) {
+ fprintf(stderr, "Error parsing command : '%s'\n", param);
+ goto ERR_PARSE;
+ }
+
+
+ hc_data_t * data;
+
+ hc_sock_t * s;
+ if (server_ip) {
+ if (server_port == 0)
+ server_port = PORT;
+#define BUFSIZE 255
+ char url[BUFSIZE];
+ snprintf(url, BUFSIZE, "tcp://%s:%d/", server_ip, server_port);
+ s = hc_sock_create_url(url);
+ } else {
+ s = hc_sock_create();
+ }
+ if (!s) {
+ fprintf(stderr, "Could not create socket.\n");
+ goto ERR_SOCK;
+ }
+
+ if (hc_sock_connect(s) < 0) {
+ fprintf(stderr, "Could not establish connection to forwarder.\n");
+ goto ERR_CONNECT;
+ }
+
+ /* XXX connection list */
+ if (hc_connection_list(s, &data) < 0) {
+ fprintf(stderr, "Error running command");
+ goto ERR_CMD;
+ }
+
+ char buf[MAXSZ_HC_CONNECTION]; // XXX
+ foreach_connection(c, data) {
+ /* XXX connection print */
+ int rc = hc_connection_snprintf(buf, MAXSZ_HC_CONNECTION, c);
+ if (rc < 0) {
+ strncpy(buf, "(Error)", MAXSZ_HC_CONNECTION);
+ } else if (rc >= MAXSZ_HC_CONNECTION) {
+ buf[MAXSZ_HC_CONNECTION-1] = '\0';
+ buf[MAXSZ_HC_CONNECTION-2] = '.';
+ buf[MAXSZ_HC_CONNECTION-3] = '.';
+ buf[MAXSZ_HC_CONNECTION-4] = '.';
+ }
+ printf("%s\n", buf);
+ }
+
+ hc_data_free(data);
+ exit(EXIT_SUCCESS);
+
+ERR_CMD:
+ERR_CONNECT:
+ hc_sock_free(s);
+ERR_SOCK:
+ERR_PARSE:
+ERR_PARAM:
+ exit(EXIT_FAILURE);
+}
diff --git a/hicn-light/src/hicn/cli/hicnd.c b/hicn-light/src/hicn/cli/hicnd.c
new file mode 100644
index 000000000..a989cff25
--- /dev/null
+++ b/hicn-light/src/hicn/cli/hicnd.c
@@ -0,0 +1,400 @@
+/*
+ * 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 _WIN32
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+//#include <hicn/hicn-light/config.h>
+#include <hicn/util/log.h>
+
+#include "logo.h"
+#include "../base/loop.h"
+#include "../core/forwarder.h"
+
+static
+void
+usage(const char * prog)
+{
+ printf("Usage: %s [--port port]"
+#ifndef _WIN32
+ " [--daemon]"
+#endif
+ " [--capacity objectStoreSize] [--log facility=level]"
+ "[--log-file filename] [--config file]\n", prog);
+ printf("\n");
+ printf(
+ "hicn-light run as a daemon is the program to launch the forwarder, "
+ "either as a console program\n");
+ printf(
+ "or a background daemon (detatched from console). Once running, use the "
+ "program controller to\n");
+ printf("configure hicn-light.\n");
+ printf("\n");
+ printf(
+ "The configuration file contains configuration lines as per "
+ "controller\n");
+ printf(
+ "If logging level or content store capacity is set in the configuraiton "
+ "file, it overrides the command_line\n");
+ printf(
+ "When a configuration file is specified, no default listeners on 'port' "
+ "are setup. Only 'add listener' lines\n");
+ printf("in the configuration file matter.\n");
+ printf("\n");
+ printf(
+ "If no configuration file is specified, daemon will listen on TCP and "
+ "UDP ports specified by\n");
+ printf(
+ "the --port flag (or default port). It will listen on both IPv4 and "
+ "IPv6 if available.\n");
+ printf("\n");
+ printf("Options:\n");
+ printf("--port = tcp port for in-bound connections\n");
+#ifndef _WIN32
+ printf("--daemon = start as daemon process\n");
+#endif
+ printf("--objectStoreSize = maximum number of content objects to cache\n");
+ printf(
+ "--log = sets a facility to a given log level. You can have "
+ "multiple of these.\n");
+ printf(
+ " facilities: all, config, core, io, message, "
+ "processor\n");
+ printf(
+ " levels: debug, info, notice, warning, error, "
+ "critical, alert, off\n");
+ printf(" example: daemon --log io=debug --log core=off\n");
+ printf(
+ "--log-file = file to write log messages to (required in daemon "
+ "mode)\n");
+ printf("--config = configuration filename\n");
+ printf("\n");
+}
+
+#if 0
+static void _setLogLevelToLevel(int logLevelArray[LoggerFacility_END],
+ LoggerFacility facility,
+ const char *levelString) {
+ PARCLogLevel level = parcLogLevel_FromString(levelString);
+
+ if (level < PARCLogLevel_All) {
+ // we have a good facility and level
+ logLevelArray[facility] = level;
+ } else {
+ printf("Invalid log level string %s\n", levelString);
+ usage(""); // XXX
+ exit(EXIT_FAILURE);
+ }
+}
+
+/**
+ * string: "facility=level"
+ * Set the right thing in the logger
+ */
+static void _setLogLevel(int logLevelArray[LoggerFacility_END],
+ const char *string) {
+ char *tofree = parcMemory_StringDuplicate(string, strlen(string));
+ char *p = tofree;
+
+ char *facilityString = strtok(p, "=");
+ if (facilityString) {
+ char *levelString = strtok(NULL, "=");
+
+ if (strcasecmp(facilityString, "all") == 0) {
+ for (LoggerFacility facility = 0; facility < LoggerFacility_END;
+ facility++) {
+ _setLogLevelToLevel(logLevelArray, facility, levelString);
+ }
+ } else {
+ LoggerFacility facility;
+ for (facility = 0; facility < LoggerFacility_END; facility++) {
+ if (strcasecmp(facilityString, logger_FacilityString(facility)) == 0) {
+ break;
+ }
+ }
+
+ if (facility < LoggerFacility_END) {
+ _setLogLevelToLevel(logLevelArray, facility, levelString);
+ } else {
+ printf("Invalid facility string %s\n", facilityString);
+ usage(""); // XXX
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ parcMemory_Deallocate((void **)&tofree);
+}
+#endif
+
+#ifndef _WIN32
+static
+int daemonize(void)
+{
+ /* Check whether we already are a daemon */
+ if (getppid() == 1)
+ return 0;
+
+ int rc = fork();
+ if (rc < 0) {
+ ERROR("Fork error");
+ goto ERR_FORK;
+ } else if (rc > 0) {
+ /* Parent exits successfully */
+ exit(EXIT_SUCCESS);
+ }
+
+ /* Child daemon detaches */
+ DEBUG("child continuing, pid = %u\n", getpid());
+
+ /* get a new process group independent from old parent */
+ setsid();
+
+ /* close all descriptors */
+#ifdef __ANDROID__
+ for (int i = sysconf(_SC_OPEN_MAX); i >= 0; --i)
+ close(i);
+#else
+ for (int i = getdtablesize(); i >= 0; --i)
+ close(i);
+#endif
+
+ /*
+ * Reset errno because it might be seg to EBADF from the close calls above
+ */
+ errno = 0;
+
+ /* Redirect stdin and stdout and stderr to /dev/null */
+ const char *devnull = "/dev/null";
+ int nullfile = open(devnull, O_RDWR);
+ if (nullfile < 0) {
+ ERROR("Error opening file '%s': (%d) %s", devnull, errno, strerror(errno));
+ goto ERR_DEVNULL;
+ }
+
+
+ rc = dup(nullfile);
+ if (rc != 1) {
+ ERROR("Error duping fd 1 got %d file: (%d) %s", rc, errno, strerror(errno));
+ goto ERR_DUP1;
+ }
+ rc = dup(nullfile);
+ if (rc != 2) {
+ ERROR("Error duping fd 2 got %d file: (%d) %s", rc, errno, strerror(errno));
+ goto ERR_DUP2;
+ }
+
+ /* Forwarder will capture signals */
+ return 0;
+
+ERR_DUP2:
+ERR_DUP1:
+ERR_DEVNULL:
+ERR_FORK:
+ return -1;
+}
+#endif
+
+#if 0
+static Logger *_createLogfile(const char *logfile) {
+#ifndef _WIN32
+ int logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, S_IWUSR | S_IRUSR);
+#else
+ int logfd =
+ _open(logfile, _O_WRONLY | _O_APPEND | _O_CREAT, _S_IWRITE | _S_IREAD);
+#endif
+ if (logfd < 0) {
+ fprintf(stderr, "Error opening %s for writing: (%d) %s\n", logfile, errno,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+#ifndef _WIN32
+ chmod(logfile, S_IRWXU);
+#endif
+
+ PARCFileOutputStream *fos = parcFileOutputStream_Create(logfd);
+ PARCOutputStream *pos = parcFileOutputStream_AsOutputStream(fos);
+ PARCLogReporter *reporter = parcLogReporterFile_Create(pos);
+
+ Logger *logger = logger_Create(reporter, parcClock_Wallclock());
+
+ parcOutputStream_Release(&pos);
+ parcLogReporter_Release(&reporter);
+
+ return logger;
+}
+#endif
+
+int
+main(int argc, const char * argv[])
+{
+ logo();
+
+#ifndef _WIN32
+ bool daemon = false;
+#else
+ WSADATA wsaData = {0};
+ WSAStartup(MAKEWORD(2, 2), &wsaData);
+#endif
+
+ uint16_t port = PORT_NUMBER;
+ uint16_t configurationPort = 2001;
+ int capacity = -1;
+ const char *fn_config = NULL;
+
+ char *logfile = NULL;
+
+ if (argc == 2 && strcasecmp(argv[1], "-h") == 0) {
+ usage(argv[0]);
+ exit(EXIT_SUCCESS); // XXX redundant
+ }
+
+#if 0
+ int logLevelArray[LoggerFacility_END];
+ for (int i = 0; i < LoggerFacility_END; i++)
+ logLevelArray[i] = -1;
+#endif
+
+ // XXX use getoptlong ????
+ for (int i = 0; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (strcmp(argv[i], "--config") == 0) {
+ fn_config = argv[i + 1];
+ i++;
+ } else if (strcmp(argv[i], "--port") == 0) {
+ port = atoi(argv[i + 1]);
+ i++;
+#ifndef _WIN32
+ } else if (strcmp(argv[i], "--daemon") == 0) {
+ daemon = true;
+#endif
+ } else if (strcmp(argv[i], "--capacity") == 0 ||
+ strcmp(argv[i], "-c") == 0) {
+ capacity = atoi(argv[i + 1]);
+ i++;
+ } else if (strcmp(argv[i], "--log") == 0) {
+ // XXX _setLogLevel(logLevelArray, argv[i + 1]);
+ i++;
+ } else if (strcmp(argv[i], "--log-file") == 0) {
+ if (logfile) {
+ // error cannot repeat
+ fprintf(stderr, "Cannot specify --log-file more than once\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ logfile = strndup(argv[i + 1], strlen(argv[i + 1]));
+ i++;
+ } else {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ // set restrictive umask, in case we create any files
+ umask(027);
+
+#ifndef _WIN32
+ if (daemon && (logfile == NULL)) {
+ fprintf(stderr, "Must specify a logfile when running in daemon mode\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* In daemon mode, parent will exit and child will continue */
+ if (daemon && daemonize() < 0) {
+ ERROR("Could not daemonize process");
+ exit(EXIT_FAILURE);
+ }
+#endif
+
+#if 0 // XXX use hicn own logging
+ Logger *logger = NULL;
+ if (logfile) {
+ logger = _createLogfile(logfile);
+ parcMemory_Deallocate((void **)&logfile);
+ } else {
+ PARCLogReporter *stdoutReporter = parcLogReporterTextStdout_Create();
+ logger = logger_Create(stdoutReporter, parcClock_Wallclock());
+ parcLogReporter_Release(&stdoutReporter);
+ }
+
+ for (int i = 0; i < LoggerFacility_END; i++) {
+ if (logLevelArray[i] > -1) {
+ logger_SetLogLevel(logger, i, logLevelArray[i]);
+ }
+ }
+#endif
+
+ /*
+ * The loop should be created before the forwarder instance as it is needed
+ * for timers
+ */
+ MAIN_LOOP = loop_create();
+
+ forwarder_t * forwarder = forwarder_create();
+ if (!forwarder) {
+ ERROR("Forwarder initialization failed. Are you running it with sudo privileges?");
+ return -1;
+ }
+
+ configuration_t * configuration = forwarder_get_configuration(forwarder);
+ if (capacity > -1) {
+ configuration_cs_set_size(configuration, capacity);
+ }
+
+ forwarder_setup_local_listeners(forwarder, port);
+ if (fn_config) {
+ forwarder_read_config(forwarder, fn_config);
+ }
+
+ INFO("%s running port %d configuration-port %d", argv[0], port,
+ configurationPort);
+
+ /* Main loop */
+ if (loop_dispatch(MAIN_LOOP) < 0) {
+ ERROR("Failed to run main loop");
+ return EXIT_FAILURE;
+ }
+
+ INFO("%s exiting port %d", argv[0], port);
+
+ if (loop_undispatch(MAIN_LOOP) < 0) {
+ ERROR("Failed to terminate main loop");
+ return EXIT_FAILURE;
+ }
+
+ forwarder_free(forwarder);
+
+ loop_free(MAIN_LOOP);
+ MAIN_LOOP = NULL;
+
+#ifdef _WIN32
+ WSACleanup(); // XXX why is this needed here ?
+#endif
+
+ return 0;
+}
diff --git a/hicn-light/src/hicn/cli/hicns.c b/hicn-light/src/hicn/cli/hicns.c
new file mode 100644
index 000000000..03e1bd54c
--- /dev/null
+++ b/hicn-light/src/hicn/cli/hicns.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <limits.h> // LONG_MAX, LONG_MIN
+#include <hicn/ctrl.h>
+
+#ifndef _WIN32
+#include <getopt.h>
+#endif
+
+#include "logo.h"
+#include "../config/parse.h"
+
+#define PORT 9695
+
+static
+struct option longFormOptions[] = {
+ {"help", no_argument, 0, 'h'},
+ {"server", required_argument, 0, 'S'},
+ {"port", required_argument, 0, 'P'},
+ {0, 0, 0, 0}};
+
+static
+void
+usage(char *prog) {
+ printf("%s: interactive shell for hicn-light\n", prog);
+ printf("\n");
+ printf("Usage: %s", prog);
+ printf("\n");
+ printf(" %s -h This help screen.\n", prog);
+ printf("\n");
+}
+
+void
+prompt(void)
+{
+ fputs("hicn> ", stdout);
+ fflush(stdout);
+}
+
+int
+shell(hc_sock_t * s)
+{
+ char *line = NULL;
+ size_t len = 0;
+ hc_data_t * data = NULL;
+ ssize_t nread;
+
+ prompt();
+ while ((nread = getline(&line, &len, stdin)) != -1) {
+ hc_command_t command;
+
+ char * pos;
+ if ((pos=strchr(line, '\n')) != NULL)
+ *pos = '\0';
+
+ if (strlen(line) == 0)
+ goto CONTINUE;
+
+ if (strcmp(line, "exit") == 0)
+ break;
+ if (strcmp(line, "quit") == 0)
+ break;
+
+
+ if (parse(line, &command) < 0) {
+ fprintf(stderr, "Unknown command '%s'\n", line);
+ goto CONTINUE;
+ }
+
+ /* XXX connection list */
+ if (hc_connection_list(s, &data) < 0) {
+ fprintf(stderr, "Error running command.\n");
+ goto CONTINUE;
+ }
+
+ char buf[MAXSZ_HC_CONNECTION]; // XXX
+ foreach_connection(c, data) {
+ /* XXX connection print */
+ int rc = hc_connection_snprintf(buf, MAXSZ_HC_CONNECTION, c);
+ if (rc < 0) {
+ strncpy(buf, "(Error)", MAXSZ_HC_CONNECTION);
+ } else if (rc >= MAXSZ_HC_CONNECTION) {
+ buf[MAXSZ_HC_CONNECTION-1] = '\0';
+ buf[MAXSZ_HC_CONNECTION-2] = '.';
+ buf[MAXSZ_HC_CONNECTION-3] = '.';
+ buf[MAXSZ_HC_CONNECTION-4] = '.';
+ }
+ printf("%s\n", buf);
+ }
+
+ hc_data_free(data);
+CONTINUE:
+ prompt();
+ }
+
+ return 0;
+}
+
+int
+main(int argc, char * const * argv)
+{
+ logo();
+ printf("Type 'help' for a list of available commands\n");
+ printf("\n");
+ printf("\n");
+
+ /* Parse commandline */
+ char *server_ip = NULL;
+ uint16_t server_port = 0;
+
+ for(;;) {
+ // getopt_long stores the option index here.
+ int optind = 0;
+
+ int c = getopt_long(argc, argv, "hS:P:", longFormOptions, &optind);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'S':
+ server_ip = optarg;
+ break;
+
+ case 'P':
+ {
+ char *endptr;
+ long val = strtol(optarg, &endptr, 10);
+
+ errno = 0; /* To distinguish success/failure after call */
+
+ if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
+ || (errno != 0 && val == 0)) {
+ perror("strtol");
+ exit(EXIT_FAILURE);
+ }
+
+ if (endptr == optarg) {
+ fprintf(stderr, "No digits were found.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (*endptr != '\0') {
+ fprintf(stderr, "Spurious characters after number: %s.\n", endptr);
+ exit(EXIT_FAILURE);
+ }
+
+ if ((val < 1) || (val > 65535)) {
+ fprintf(stderr, "Invalid port number: %ld.\n", val);
+ exit(EXIT_FAILURE);
+ }
+
+ server_port = (uint16_t)val;
+ break;
+ }
+
+ case 'h':
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+
+ default:
+ fprintf(stderr, "Invalid argument.\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (optind != argc) {
+ fprintf(stderr, "Invalid parameters.\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+
+ hc_sock_t * s;
+ if (server_ip) {
+ if (server_port == 0)
+ server_port = PORT;
+#define BUFSIZE 255
+ char url[BUFSIZE];
+ snprintf(url, BUFSIZE, "tcp://%s:%d/", server_ip, server_port);
+ s = hc_sock_create_url(url);
+ } else {
+ s = hc_sock_create();
+ }
+ if (!s) {
+ fprintf(stderr, "Could not create socket.\n");
+ goto ERR_SOCK;
+ }
+
+ if (hc_sock_connect(s) < 0) {
+ fprintf(stderr, "Could not establish connection to forwarder.\n");
+ goto ERR_CONNECT;
+ }
+
+ int rc = shell(s);
+
+ exit((rc < 0) ? EXIT_FAILURE : EXIT_SUCCESS);
+
+ERR_CONNECT:
+ hc_sock_free(s);
+ERR_SOCK:
+ exit(EXIT_FAILURE);
+}
diff --git a/hicn-light/src/hicn/cli/logo.h b/hicn-light/src/hicn/cli/logo.h
new file mode 100644
index 000000000..1aff32837
--- /dev/null
+++ b/hicn-light/src/hicn/cli/logo.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HICNLIGHT_LOGO
+#define HICNLIGHT_LOGO
+
+#include "color.h"
+
+static
+void
+logo(void)
+{
+ printfc(COLOR_RED, " ____ ___ _ ");
+ printfc(COLOR_WHITE, " __ _ __ _ __ __\n");
+ printfc(COLOR_RED, " / __// _ \\ (_)___ ");
+ printfc(COLOR_WHITE, " / / (_)____ ___ ____/ /(_)___ _ / / / /_\n");
+ printfc(COLOR_RED, " / _/ / // /_ / // _ \\ ");
+ printfc(COLOR_WHITE, " / _ \\ / // __// _ \\___/ // // _ `// _ \\/ __/\n");
+ printfc(COLOR_RED, "/_/ /____/(_)/_/ \\___/ ");
+ printfc(COLOR_WHITE, "/_//_//_/ \\__//_//_/ /_//_/ \\_, //_//_/\\__/\n");
+ printfc(COLOR_WHITE,
+ " /___/ "
+ "\n");
+ printf("\n");
+}
+
+#endif /* HICNLIGHT_LOGO */
diff --git a/hicn-light/src/hicn/command_line/CMakeLists.txt b/hicn-light/src/hicn/command_line/CMakeLists.txt
deleted file mode 100644
index 217e00fd3..000000000
--- a/hicn-light/src/hicn/command_line/CMakeLists.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-#add_subdirectory(controller)
-add_subdirectory(daemon)
diff --git a/hicn-light/src/hicn/command_line/controller/CMakeLists.txt b/hicn-light/src/hicn/command_line/controller/CMakeLists.txt
deleted file mode 100644
index 26d4c0b63..000000000
--- a/hicn-light/src/hicn/command_line/controller/CMakeLists.txt
+++ /dev/null
@@ -1,25 +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.
-
-list(APPEND CONTROLLER_SRC
-hicnLightControl_main.c
-)
-if (NOT DISABLE_EXECUTABLES)
- build_executable(${HICN_LIGHT_CONTROL}
- SOURCES ${CONTROLLER_SRC}
- LINK_LIBRARIES ${HICN_LIGHT_LINK_LIBRARIES}
- DEPENDS ${LIBHICN_LIGHT_STATIC}
- COMPONENT ${HICN_LIGHT}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- )
-endif ()
diff --git a/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c b/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c
deleted file mode 100644
index cc91e5a70..000000000
--- a/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c
+++ /dev/null
@@ -1,375 +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 <hicn/hicn-light/config.h>
-#include <hicn/utils/utils.h>
-
-#ifndef _WIN32
-#include <arpa/inet.h>
-#include <getopt.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#endif
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <string.h>
-
-#include <parc/security/parc_IdentityFile.h>
-#include <parc/security/parc_Security.h>
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_List.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_SafeMemory.h>
-
-#include <hicn/core/forwarder.h>
-
-#include <errno.h>
-#include <hicn/config/controlRoot.h>
-#include <hicn/config/controlState.h>
-
-#include <hicn/utils/commands.h>
-
-
-
-size_t commandOutputLen = 0; // preserve the number of structs composing
- // payload in case on not interactive call.
-
-// REMINDER: when a new_command is added, the following array has to be updated
-// with the sizeof(new_command). It allows to allocate the buffer for receiving
-// the payload of the DAEMON RESPONSE after the header has beed read. Each
-// command identifier (typedef enum command_id) corresponds to a position in the
-// following array.
-static int payloadLengthController[LAST_COMMAND_VALUE] = {
- sizeof(add_listener_command),
- sizeof(add_connection_command),
- sizeof(list_connections_command), // needed when get response from FWD
- sizeof(add_route_command),
- sizeof(list_routes_command), // needed when get response from FWD
- sizeof(remove_connection_command),
- sizeof(remove_listener_command),
- sizeof(remove_route_command),
- sizeof(cache_store_command),
- sizeof(cache_serve_command),
- 0, // cache clear
- sizeof(set_strategy_command),
- sizeof(set_wldr_command),
- sizeof(add_punting_command),
- sizeof(list_listeners_command), // needed when get response from FWD
- sizeof(mapme_activator_command),
- sizeof(mapme_activator_command),
- sizeof(mapme_timing_command),
- sizeof(mapme_timing_command),
- sizeof(mapme_send_update_command),
- sizeof(connection_set_admin_state_command),
-#ifdef WITH_POLICY
- sizeof(add_policy_command),
- sizeof(list_policies_command),
- sizeof(remove_policy_command),
- sizeof(update_connection_command),
- sizeof(connection_set_priority_command),
- sizeof(connection_set_tags_command),
-#endif
-};
-
-typedef struct controller_main_state {
- ControlState *controlState;
-} ControlMainState;
-
-static void _printRed(const char *output) {
-#ifndef _WIN32
- printf("\033[0;31m%s", output);
-#else
- HANDLE hConsole = NULL;
- WORD currentConsoleAttr;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
- if (GetConsoleScreenBufferInfo(hConsole, &csbi))
- currentConsoleAttr = csbi.wAttributes;
- SetConsoleTextAttribute(hConsole, 4);
- printf("%s", output);
- SetConsoleTextAttribute(hConsole, currentConsoleAttr);
-#endif
-}
-
-static void _printWhite(const char *output) {
-#ifndef _WIN32
- printf("\033[0m%s", output);
-#else
- HANDLE hConsole = NULL;
- WORD currentConsoleAttr;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
- if (GetConsoleScreenBufferInfo(hConsole, &csbi))
- currentConsoleAttr = csbi.wAttributes;
- SetConsoleTextAttribute(hConsole, 7);
- printf("%s", output);
- SetConsoleTextAttribute(hConsole, currentConsoleAttr);
-#endif
-}
-
-static void _displayForwarderLogo(void) {
- _printRed(" ____ ___ _ ");
- _printWhite(" __ _ __ _ __ __\n");
- _printRed(" / __// _ \\ (_)___ ");
- _printWhite(" / / (_)____ ___ ____/ /(_)___ _ / / / /_\n");
- _printRed(" / _/ / // /_ / // _ \\ ");
- _printWhite(" / _ \\ / // __// _ \\___/ // // _ `// _ \\/ __/\n");
- _printRed("/_/ /____/(_)/_/ \\___/ ");
- _printWhite("/_//_//_/ \\__//_//_/ /_//_/ \\_, //_//_/\\__/\n");
- _printWhite(
- " /___/ "
- "\n");
- printf("\n");
-}
-
-static void _displayUsage(char *programName) {
- printf("Usage: %s -h\n", programName);
- printf(
- "hicn-light is the 1.0 source, which runs on each end system and as a "
- "software source\n");
- printf(
- "on intermediate systems. controller is the program to configure the "
- "source, daemon.\n");
- printf("\n");
- printf("Options:\n");
- printf("-h = This help screen\n");
- printf(
- "commands = configuration line to send to hicn-light (use 'help' "
- "for list)\n");
- printf("\n");
-}
-
-static int _parseArgs(int argc, char *argv[], char **server_ip,
- uint16_t *server_port, PARCList *commandList){
- static struct option longFormOptions[] = {
- {"help", no_argument, 0, 'h'},
- {"server", required_argument, 0, 'S'},
- {"port", required_argument, 0, 'P'},
- {0, 0, 0, 0}};
-
- int c;
-
- while (1) {
- // getopt_long stores the option index here.
- int optionIndex = 0;
-
- c = getopt_long(argc, argv, "hS:P:", longFormOptions, &optionIndex);
-
- // Detect the end of the options.
- if (c == -1) {
- break;
- }
-
- switch (c) {
- case 'S':
- {
- *server_ip = optarg;
- struct sockaddr_in sa;
- int result = inet_pton(AF_INET, *server_ip, &(sa.sin_addr));
- //inet_pton() returns 1 on success
- if(result != 1){
- return 0;
- }
- break;
- }
- case 'P':
- {
- char * port_str = optarg;
- if(utils_IsNumber(port_str)){
- *server_port = (uint16_t) strtol(port_str, NULL, 10);
- } else {
- return 0;
- }
- break;
- }
- case 'h':
- default:
- return 0;
- }
- }
-
- if (optind < argc) {
- while (optind < argc) {
- parcList_Add(commandList, argv[optind]);
- optind++;
- }
- }
-
- return 1;
-}
-
-struct iovec *_writeAndReadMessage(ControlState *state, struct iovec *msg) {
- parcAssertNotNull(msg, "Parameter msg must be non-null");
- int sockfd = controlState_GetSockfd(state);
-
- // check if request has a payload
- if (((header_control_message *)msg[0].iov_base)->length >
- 0) { // command with payload
- // write header + payload (compatibility issue: two write needed instead of
- // the writev)
-#ifndef _WIN32
- if (write(sockfd, msg[0].iov_base, (unsigned int)msg[0].iov_len) < 0 ||
- write(sockfd, msg[1].iov_base, (unsigned int)msg[1].iov_len) < 0) {
-#else
- if (send(sockfd, msg[0].iov_base, (int)msg[0].iov_len, 0) == SOCKET_ERROR ||
- send(sockfd, msg[1].iov_base, (int)msg[1].iov_len, 0) == SOCKET_ERROR) {
-#endif
- printf("\nError while sending the Message: cannot write on socket \n");
- exit(EXIT_FAILURE);
- }
- parcMemory_Deallocate(&msg[1].iov_base);
- } else { // command without payload, e.g. 'list'
- // write header only
-#ifndef _WIN32
- if (write(sockfd, msg[0].iov_base, msg[0].iov_len) < 0) {
-#else
- int result = send(sockfd, msg[0].iov_base, (int)msg[0].iov_len, 0);
- if (result == SOCKET_ERROR) {
-#endif
- printf("\nError while sending the Message: cannot write on socket \n");
- exit(EXIT_FAILURE);
- }
- }
- parcMemory_Deallocate(&msg[0].iov_base);
-
- // ======= RECEIVE =======
-
- header_control_message *headerResponse =
- (header_control_message *)parcMemory_AllocateAndClear(
- sizeof(header_control_message));
- if (recv(sockfd, (char *)headerResponse, sizeof(header_control_message), 0) <
- 0) {
- printf("\nError in Receiving the Message \n");
- exit(EXIT_FAILURE);
- }
-
- if (headerResponse->messageType < RESPONSE_LIGHT ||
- headerResponse->messageType >= LAST_MSG_TYPE_VALUE) {
- char *checkFinMsg = parcMemory_Reallocate(headerResponse, 32);
-#ifndef _WIN32
- if (recv(sockfd, checkFinMsg, sizeof(checkFinMsg),
- MSG_PEEK | MSG_DONTWAIT) == 0) {
-#else
- if (recv(sockfd, checkFinMsg, sizeof(checkFinMsg), MSG_PEEK) == 0) {
-#endif
- // if recv returns zero, that means the connection has been closed:
- close(sockfd);
- printf("\nConnection terminated by the Daemon. Exiting... \n");
- exit(EXIT_SUCCESS);
- } else {
- printf("\nError: Unrecognized message type received \n");
- exit(EXIT_FAILURE);
- }
- }
-
- void *payloadResponse = NULL;
-
- if ((commandOutputLen = headerResponse->length) > 0) {
- payloadResponse = parcMemory_AllocateAndClear(
- payloadLengthController[headerResponse->commandID] *
- headerResponse->length);
-
- if (recv(sockfd, payloadResponse,
- payloadLengthController[headerResponse->commandID] *
- headerResponse->length,
- 0) < 0) {
- printf("\nError in Receiving the Message \n");
- exit(EXIT_FAILURE);
- }
- }
-
- struct iovec *response =
- parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
-
- response[0].iov_base = headerResponse;
- response[0].iov_len = sizeof(header_control_message);
- response[1].iov_base = payloadResponse;
- response[1].iov_len = payloadLengthController[headerResponse->commandID] *
- headerResponse->length;
-
- return response;
-}
-
-int main(int argc, char *argv[]) {
- _displayForwarderLogo();
-
-#ifdef _WIN32
- WSADATA wsaData;
- WSAStartup(MAKEWORD(2, 2), &wsaData);
-#endif
-
- if (argc == 2 && strcmp("-h", argv[1]) == 0) {
- _displayUsage(argv[0]);
- exit(EXIT_SUCCESS);
- }
-
- PARCList *commands =
- parcList(parcArrayList_Create(NULL), PARCArrayListAsPARCList);
-
- char *server_ip = SRV_CTRL_IP;
- uint16_t server_port = SRV_CTRL_PORT;
- if (!_parseArgs(argc, argv, &server_ip,
- &server_port, commands)) {
- _displayUsage(argv[0]);
- parcList_Release(&commands);
- exit(EXIT_FAILURE);
- }
-
- ControlMainState mainState;
- mainState.controlState =
- controlState_Create(&mainState, _writeAndReadMessage, true,
- server_ip, server_port);
-
- controlState_RegisterCommand(mainState.controlState,
- controlRoot_HelpCreate(mainState.controlState));
- controlState_RegisterCommand(mainState.controlState,
- controlRoot_Create(mainState.controlState));
-
- if (parcList_Size(commands) > 0) {
- controlState_SetInteractiveFlag(mainState.controlState, false);
- controlState_DispatchCommand(mainState.controlState, commands);
- char **commandOutputMain =
- controlState_GetCommandOutput(mainState.controlState);
- if (commandOutputMain != NULL && commandOutputLen > 0) {
-#if 0
- for (size_t j = 0; j < commandOutputLen; j++) {
- printf("Output %zu: %s \n", j, commandOutputMain[j]);
- }
-#endif
- controlState_ReleaseCommandOutput(mainState.controlState,
- commandOutputMain, commandOutputLen);
- }
- // release
-
- } else {
- controlState_Interactive(mainState.controlState);
- }
-
- parcList_Release(&commands);
-
- controlState_Destroy(&mainState.controlState);
-#ifdef _WIN32
- WSACleanup();
-#endif
- return EXIT_SUCCESS;
-}
diff --git a/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt b/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt
deleted file mode 100644
index 8606c8f89..000000000
--- a/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt
+++ /dev/null
@@ -1,25 +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.
-
-list(APPEND DAEMON_SRC
- hicnLightDaemon_main.c
-)
-if (NOT DISABLE_EXECUTABLES)
- build_executable(${HICN_LIGHT_DAEMON}
- SOURCES ${DAEMON_SRC}
- LINK_LIBRARIES ${LIBHICN_LIGHT_STATIC}
- DEPENDS ${LIBHICN_LIGHT_STATIC}
- COMPONENT ${HICN_LIGHT}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- )
-endif ()
diff --git a/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c b/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c
deleted file mode 100644
index c743de743..000000000
--- a/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c
+++ /dev/null
@@ -1,423 +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 _WIN32
-#include <unistd.h>
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include <hicn/hicn-light/config.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/util/log.h>
-#include <hicn/base/loop.h>
-
-static void _printRed(const char *output) {
-#ifndef _WIN32
- printf("\033[0;31m%s", output);
-#else
- HANDLE hConsole = NULL;
- WORD currentConsoleAttr;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
- if (GetConsoleScreenBufferInfo(hConsole, &csbi))
- currentConsoleAttr = csbi.wAttributes;
- SetConsoleTextAttribute(hConsole, 4);
- printf("%s", output);
- SetConsoleTextAttribute(hConsole, currentConsoleAttr);
-#endif
-}
-
-static void _printWhite(const char *output) {
-#ifndef _WIN32
- printf("\033[0m%s", output);
-#else
- HANDLE hConsole = NULL;
- WORD currentConsoleAttr;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
- if (GetConsoleScreenBufferInfo(hConsole, &csbi))
- currentConsoleAttr = csbi.wAttributes;
- SetConsoleTextAttribute(hConsole, 7);
- printf("%s", output);
- SetConsoleTextAttribute(hConsole, currentConsoleAttr);
-#endif
-}
-
-static void _displayForwarderLogo(void) {
- _printRed(" ____ ___ _ ");
- _printWhite(" __ _ __ _ __ __\n");
- _printRed(" / __// _ \\ (_)___ ");
- _printWhite(" / / (_)____ ___ ____/ /(_)___ _ / / / /_\n");
- _printRed(" / _/ / // /_ / // _ \\ ");
- _printWhite(" / _ \\ / // __// _ \\___/ // // _ `// _ \\/ __/\n");
- _printRed("/_/ /____/(_)/_/ \\___/ ");
- _printWhite("/_//_//_/ \\__//_//_/ /_//_/ \\_, //_//_/\\__/\n");
- _printWhite(
- " /___/ "
- "\n");
- printf("\n");
-}
-
-static void _usage(int exitCode) {
-#ifndef _WIN32
- printf(
- "Usage: hicn-light-daemon [--port port] [--capacity objectStoreSize] "
- "[--log facility=level] [--log-file filename] [--config file]\n");
-#else
- printf(
- "Usage: hicn-light-daemon.exe [--port port] [--daemon] [--capacity objectStoreSize] "
- "[--log facility=level] [--log-file filename] [--config file]\n");
-#endif
- printf("\n");
- printf(
- "hicn-light run as a daemon is the program to launch the forwarder, "
- "either as a console program\n");
- printf(
- "or a background daemon (detatched from console). Once running, use the "
- "program controller to\n");
- printf("configure hicn-light.\n");
- printf("\n");
- printf(
- "The configuration file contains configuration lines as per "
- "controller\n");
- printf(
- "If logging level or content store capacity is set in the configuraiton "
- "file, it overrides the command_line\n");
- printf(
- "When a configuration file is specified, no default listeners on 'port' "
- "are setup. Only 'add listener' lines\n");
- printf("in the configuration file matter.\n");
- printf("\n");
- printf(
- "If no configuration file is specified, daemon will listen on TCP and "
- "UDP ports specified by\n");
- printf(
- "the --port flag (or default port). It will listen on both IPv4 and "
- "IPv6 if available.\n");
- printf("\n");
- printf("Options:\n");
- printf("--port = tcp port for in-bound connections\n");
-#ifndef _WIN32
- printf("--daemon = start as daemon process\n");
-#endif
- printf("--objectStoreSize = maximum number of content objects to cache\n");
- printf(
- "--log = sets a facility to a given log level. You can have "
- "multiple of these.\n");
- printf(
- " facilities: all, config, core, io, message, "
- "processor\n");
- printf(
- " levels: debug, info, notice, warning, error, "
- "critical, alert, off\n");
- printf(" example: daemon --log io=debug --log core=off\n");
- printf(
- "--log-file = file to write log messages to (required in daemon "
- "mode)\n");
- printf("--config = configuration filename\n");
- printf("\n");
- exit(exitCode);
-}
-
-#if 0
-static void _setLogLevelToLevel(int logLevelArray[LoggerFacility_END],
- LoggerFacility facility,
- const char *levelString) {
- PARCLogLevel level = parcLogLevel_FromString(levelString);
-
- if (level < PARCLogLevel_All) {
- // we have a good facility and level
- logLevelArray[facility] = level;
- } else {
- printf("Invalid log level string %s\n", levelString);
- _usage(EXIT_FAILURE);
- }
-}
-
-/**
- * string: "facility=level"
- * Set the right thing in the logger
- */
-static void _setLogLevel(int logLevelArray[LoggerFacility_END],
- const char *string) {
- char *tofree = parcMemory_StringDuplicate(string, strlen(string));
- char *p = tofree;
-
- char *facilityString = strtok(p, "=");
- if (facilityString) {
- char *levelString = strtok(NULL, "=");
-
- if (strcasecmp(facilityString, "all") == 0) {
- for (LoggerFacility facility = 0; facility < LoggerFacility_END;
- facility++) {
- _setLogLevelToLevel(logLevelArray, facility, levelString);
- }
- } else {
- LoggerFacility facility;
- for (facility = 0; facility < LoggerFacility_END; facility++) {
- if (strcasecmp(facilityString, logger_FacilityString(facility)) == 0) {
- break;
- }
- }
-
- if (facility < LoggerFacility_END) {
- _setLogLevelToLevel(logLevelArray, facility, levelString);
- } else {
- printf("Invalid facility string %s\n", facilityString);
- _usage(EXIT_FAILURE);
- }
- }
- }
-
- parcMemory_Deallocate((void **)&tofree);
-}
-#endif
-
-#ifndef _WIN32
-static void _daemonize(void) {
- if (getppid() == 1) {
- // already a daemon
- return;
- }
-
- int forkReturn = fork();
- assert(forkReturn >= 0);
-
- if (forkReturn > 0) {
- // parent exits
- exit(EXIT_SUCCESS);
- }
-
- // Child daemon detaches
- printf("child continuing, pid = %u\n", getpid());
-
- // get a new process group independent from old parent
- setsid();
-
- /* close all descriptors */
-#ifdef __ANDROID__
- for (int i = sysconf(_SC_OPEN_MAX); i >= 0; --i) {
- close(i);
- }
-#else
- for (int i = getdtablesize(); i >= 0; --i) {
- close(i);
- }
-#endif
- // reset errno because it might be seg to EBADF from the close calls above
- errno = 0;
-
- // Redirect stdin and stdout and stderr to /dev/null
- const char *devnull = "/dev/null";
- int nullfile = open(devnull, O_RDWR);
- assert(nullfile >= 0);
-
- int ret;
- ret = dup(nullfile);
- assert(ret == 1);
- ret = dup(nullfile);
- assert(ret == 2);
- (void)ret; /* UNUSED */
-
- // forwarder will capture signals
-}
-#endif
-
-#if 0
-static Logger *_createLogfile(const char *logfile) {
-#ifndef _WIN32
- int logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, S_IWUSR | S_IRUSR);
-#else
- int logfd =
- _open(logfile, _O_WRONLY | _O_APPEND | _O_CREAT, _S_IWRITE | _S_IREAD);
-#endif
- if (logfd < 0) {
- fprintf(stderr, "Error opening %s for writing: (%d) %s\n", logfile, errno,
- strerror(errno));
- exit(EXIT_FAILURE);
- }
-
-#ifndef _WIN32
- chmod(logfile, S_IRWXU);
-#endif
-
- PARCFileOutputStream *fos = parcFileOutputStream_Create(logfd);
- PARCOutputStream *pos = parcFileOutputStream_AsOutputStream(fos);
- PARCLogReporter *reporter = parcLogReporterFile_Create(pos);
-
- Logger *logger = logger_Create(reporter, parcClock_Wallclock());
-
- parcOutputStream_Release(&pos);
- parcLogReporter_Release(&reporter);
-
- return logger;
-}
-#endif
-
-int main(int argc, const char *argv[]) {
- _displayForwarderLogo();
-#ifndef _WIN32
- bool daemon = false;
-#else
- WSADATA wsaData = {0};
- WSAStartup(MAKEWORD(2, 2), &wsaData);
-#endif
-
- uint16_t port = PORT_NUMBER;
- uint16_t configurationPort = 2001;
- int capacity = -1;
- const char *configFileName = NULL;
-
- char *logfile = NULL;
-
- if (argc == 2 && strcasecmp(argv[1], "-h") == 0) {
- _usage(EXIT_SUCCESS);
- }
-
-#if 0
- int logLevelArray[LoggerFacility_END];
- for (int i = 0; i < LoggerFacility_END; i++) {
- logLevelArray[i] = -1;
- }
-#endif
-
- for (int i = 0; i < argc; i++) {
- if (argv[i][0] == '-') {
- if (strcmp(argv[i], "--config") == 0) {
- configFileName = argv[i + 1];
- i++;
- } else if (strcmp(argv[i], "--port") == 0) {
- port = atoi(argv[i + 1]);
- i++;
-#ifndef _WIN32
- } else if (strcmp(argv[i], "--daemon") == 0) {
- daemon = true;
-#endif
- } else if (strcmp(argv[i], "--capacity") == 0 ||
- strcmp(argv[i], "-c") == 0) {
- capacity = atoi(argv[i + 1]);
- i++;
-#if 0
- } else if (strcmp(argv[i], "--log") == 0) {
- _setLogLevel(logLevelArray, argv[i + 1]);
- i++;
- } else if (strcmp(argv[i], "--log-file") == 0) {
- if (logfile) {
- // error cannot repeat
- fprintf(stderr, "Cannot specify --log-file more than once\n");
- _usage(EXIT_FAILURE);
- }
-
- logfile = parcMemory_StringDuplicate(argv[i + 1], strlen(argv[i + 1]));
- i++;
-#endif
- } else {
- _usage(EXIT_FAILURE);
- }
- }
- }
-
- // set restrictive umask, in case we create any files
- umask(027);
-
-#ifndef _WIN32
- if (daemon && (logfile == NULL)) {
- fprintf(stderr, "Must specify a logfile when running in daemon mode\n");
- _usage(EXIT_FAILURE);
- }
-
- if (daemon) {
- // inside this call, parent will EXIT_SUCCESS and child will continue
- _daemonize();
- }
-#endif
-
-#if 0
- Logger *logger = NULL;
- if (logfile) {
- logger = _createLogfile(logfile);
- parcMemory_Deallocate((void **)&logfile);
- } else {
- PARCLogReporter *stdoutReporter = parcLogReporterTextStdout_Create();
- logger = logger_Create(stdoutReporter, parcClock_Wallclock());
- parcLogReporter_Release(&stdoutReporter);
- }
-
- for (int i = 0; i < LoggerFacility_END; i++) {
- if (logLevelArray[i] > -1) {
- logger_SetLogLevel(logger, i, logLevelArray[i]);
- }
- }
-#endif
-
- /*
- * The loop should be created before the forwarder instance as it is needed
- * for timers
- */
- MAIN_LOOP = loop_create();
-
- forwarder_t * forwarder = forwarder_create();
- if (!forwarder) {
- ERROR("Forwarder initialization failed. Are you running it with sudo privileges?");
- return -1;
- }
-
- configuration_t * configuration = forwarder_get_configuration(forwarder);
- if (capacity > -1) {
- configuration_cs_set_size(configuration, capacity);
- }
-
- forwarder_setup_local_listeners(forwarder, port);
- if (configFileName) {
- forwarder_read_config(forwarder, configFileName);
- }
-
- INFO("hicn-light running port %d configuration-port %d", port,
- configurationPort);
-
- /* Main loop */
- if (loop_dispatch(MAIN_LOOP) < 0) {
- ERROR("Failed to run main loop");
- return EXIT_FAILURE;
- }
-
- INFO("hicn-light exiting port %d", port);
-
- if (loop_undispatch(MAIN_LOOP) < 0) {
- ERROR("Failed to terminate main loop");
- return EXIT_FAILURE;
- }
-
- forwarder_free(forwarder);
-
- loop_free(MAIN_LOOP);
- MAIN_LOOP = NULL;
-
-#ifndef _WIN32
- sleep(2);
-#else
- Sleep(2000);
- WSACleanup();
-#endif
-
- return 0;
-}
diff --git a/hicn-light/src/hicn/config/CMakeLists.txt b/hicn-light/src/hicn/config/CMakeLists.txt
index 9db413867..ebb1d57d3 100644
--- a/hicn-light/src/hicn/config/CMakeLists.txt
+++ b/hicn-light/src/hicn/config/CMakeLists.txt
@@ -14,93 +14,24 @@
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
list(APPEND HEADER_FILES
-# ${CMAKE_CURRENT_SOURCE_DIR}/commandOps.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/commandParser.h
-${CMAKE_CURRENT_SOURCE_DIR}/configuration.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/commandReturn.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/symbolicNameTable.h
-#${CMAKE_CURRENT_SOURCE_DIR}/controlState.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRoot.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddConnection.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlAdd.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/configuration_file.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddRoute.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPolicy.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddListener.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlListConnections.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlList.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlListListeners.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlListRoutes.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlListPolicies.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlQuit.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveListener.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePolicy.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlSet.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlUnset.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlSetDebug.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlUnsetDebug.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMe.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeEnable.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeDiscovery.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeTimescale.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheServe.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheStore.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheClear.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlCache.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlSetStrategy.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlSetWldr.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPunting.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePunting.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdate.h
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdateConnection.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/configuration.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/command.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/parse.h
)
list(APPEND SOURCE_FILES
-# ${CMAKE_CURRENT_SOURCE_DIR}/commandOps.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/commandParser.c
- ${CMAKE_CURRENT_SOURCE_DIR}/configuration.c
- ${CMAKE_CURRENT_SOURCE_DIR}/configuration_file.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlState.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/symbolicNameTable.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlAdd.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddConnection.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddRoute.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPolicy.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddListener.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlList.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlListConnections.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlListListeners.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlListRoutes.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlListPolicies.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlQuit.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveListener.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePolicy.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRoot.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlSet.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlSetDebug.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlUnset.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlUnsetDebug.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMe.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeEnable.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeDiscovery.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeTimescale.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeRetx.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheServe.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheStore.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheClear.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlCache.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlSetStrategy.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlSetWldr.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPunting.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePunting.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdate.c
-# ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdateConnection.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/configuration.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/configuration_file.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_connection.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_face.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_listener.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_mapme.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_policy.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_punting.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_route.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_strategy.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/parse.c
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/hicn-light/src/hicn/config/command.c b/hicn-light/src/hicn/config/command.c
new file mode 100644
index 000000000..4c89d6680
--- /dev/null
+++ b/hicn-light/src/hicn/config/command.c
@@ -0,0 +1,61 @@
+
+/**
+ * @file command.c
+ * @brief Implementation of commands.
+ */
+
+#include <search.h> /* tfind, tdestroy, twalk */
+#include <stdio.h>
+
+#include "command.h"
+
+/* Commands are registered in the following tree. */
+static void * commands_root = NULL; /**< Tree ordered by name */
+
+static void nothing_to_free() {}
+
+#ifdef __linux__
+__attribute__((destructor))
+static
+void
+command_clear()
+{
+ tdestroy(commands_root, nothing_to_free);
+}
+#endif /* __linux__ */
+
+static
+int
+_command_compare(const command_parser_t * c1,
+ const command_parser_t * c2)
+{
+ if (c1->action != c2->action)
+ return c2->action - c1->action;
+ if (c1->object != c2->object)
+ return c2->object - c1->object;
+ if (c1->nparams != c2->nparams)
+ return c2->nparams - c1->nparams;
+ return 0;
+}
+
+#define command_compare (int (*)(const void *, const void *))(_command_compare)
+
+void
+command_register(const command_parser_t * command)
+{
+ // Insert the command in the tree if the keys does not exist yet
+ tsearch(command, &commands_root, command_compare);
+}
+
+const command_parser_t *
+command_search(hc_action_t action, hc_object_type_t object, unsigned nparams)
+{
+ command_parser_t ** command, search;
+
+ search.action = action;
+ search.object = object;
+ search.nparams = nparams;
+ command = tfind(&search, &commands_root, command_compare);
+
+ return command ? *command : NULL;
+}
diff --git a/hicn-light/src/hicn/config/command.h b/hicn-light/src/hicn/config/command.h
new file mode 100644
index 000000000..c0e3e66e8
--- /dev/null
+++ b/hicn-light/src/hicn/config/command.h
@@ -0,0 +1,163 @@
+#ifndef HICNLIGHT_CONFIG_COMMAND
+#define HICNLIGHT_CONFIG_COMMAND
+
+/**
+ * @file command.h
+ * @brief Commands.
+ */
+
+#include <stddef.h> // offsetof
+#include <hicn/util/ip_address.h>
+
+#include <hicn/ctrl/api.h>
+
+/* Update sscanf accordingly in parse_cmd.c */
+#define MAX_PARAMETERS 10
+
+typedef int (*parser_hook_t)(void * arg);
+
+typedef enum {
+ TYPENAME_UNDEFINED,
+ TYPENAME_INT,
+ TYPENAME_UINT,
+ TYPENAME_STR,
+ TYPENAME_SYMBOLIC,
+ TYPENAME_SYMBOLIC_OR_ID,
+ TYPENAME_IP_ADDRESS,
+ TYPENAME_IP_PREFIX,
+ TYPENAME_ENUM,
+ TYPENAME_POLICY_STATE,
+} parser_typename_t;
+
+typedef struct {
+ parser_typename_t name;
+ union {
+ struct {
+ size_t max_size;
+ } str;
+ struct {
+ int min;
+ int max;
+ } sint;
+ struct {
+ int min;
+ int max;
+ } uint;
+ struct {
+ int (*from_str)(const char * str);
+ } enum_;
+ struct {
+ policy_tag_t tag;
+ } policy_state;
+ };
+} parser_type_t;
+
+typedef struct {
+ const char * name;
+ const char * help;
+ parser_type_t type;
+ size_t offset;
+ /*
+ * quick hack to let the functions update two or more parameters, like for
+ * IP_ADDRESS or IP_PREFIX types
+ */
+ size_t offset2;
+ size_t offset3;
+} command_parameter_t;
+
+typedef struct {
+ hc_action_t action;
+ hc_object_type_t object;
+ unsigned nparams;
+ command_parameter_t parameters[MAX_PARAMETERS];
+ parser_hook_t post_hook;
+} command_parser_t;
+
+#define TYPE_STRN(N) (parser_type_t) { \
+ .name = TYPENAME_STR, \
+ .str = { \
+ .max_size = 0, \
+ }, \
+}
+#define TYPE_FMT_STRN(N) "%s"
+
+#define TYPE_INT(MIN, MAX) (parser_type_t) { \
+ .name = TYPENAME_INT, \
+ .sint = { \
+ .min = (MIN), \
+ .max = (MAX), \
+ }, \
+}
+#define TYPE_FMT_INT "%d"
+
+#define TYPE_UINT(min, max) (parser_type_t) { \
+ .name = TYPENAME_INT, \
+ .uint = { \
+ .min = min, \
+ .max = max, \
+ }, \
+}
+#define TYPE_FMT_UINT "%u"
+
+#define TYPE_STR TYPE_STRN(0)
+#define TYPE_FMT_STR "%s"
+
+#define TYPE_SYMBOLIC TYPE_STRN(NAME_LEN)
+#define TYPE_FMT_SYMBOLIC "%s"
+
+#define TYPE_SYMBOLIC_OR_ID TYPE_STRN(NAME_LEN)
+#define TYPE_FMT_SYMBOLIC_OR_ID "%s"
+
+#define TYPE_IP_ADDRESS (parser_type_t) { \
+ .name = TYPENAME_IP_ADDRESS, \
+}
+#define TYPE_FMT_IP_ADDRESS "%s"
+
+#define TYPE_IP_PREFIX (parser_type_t) { \
+ .name = TYPENAME_IP_PREFIX, \
+}
+#define TYPE_FMT_IP_PREFIX "%s"
+
+#define TYPE_ENUM(x) (parser_type_t) { \
+ .name = TYPENAME_ENUM, \
+ .enum_ = { \
+ .from_str = (int(*)(const char *)) x ## _from_str, \
+ }, \
+}
+/* We need to allocate room for the intermediate string */
+#define TYPE_FMT_ENUM "%ms"
+
+#define TYPE_POLICY_STATE(TAG) (parser_type_t) { \
+ .name = TYPENAME_POLICY_STATE, \
+ .policy_state = { \
+ .tag = TAG, \
+ }, \
+}
+/* We need to allocate room for the intermediate string */
+#define TYPE_FMT_POLICY_STATE "%ms"
+
+/**
+ * \brief Register a protocol
+ * \param protocol Pointer to a protocol_t structure describing the protocol to register
+ * \return None
+ */
+
+void command_register(const command_parser_t * command);
+
+/**
+ * \brief Search a registered protocol in the library according to its name
+ * \param[in] action The action of the command.
+ * \param[in] object The object of the command.
+ * \param[in] nparams The number of parameters expected in the command.
+ * \return A pointer to the corresponding command if any, NULL othewise
+ */
+const command_parser_t * command_search(hc_action_t action, hc_object_type_t object,
+ unsigned nparams);
+
+#define COMMAND_REGISTER(MOD) \
+static void __init_ ## MOD (void) __attribute__ ((constructor)); \
+static void __init_ ## MOD (void) { \
+ command_register(&MOD); \
+}
+
+#endif /* HICNLIGHT_CONFIG_COMMAND */
diff --git a/hicn-light/src/hicn/config/command_connection.c b/hicn-light/src/hicn/config/command_connection.c
new file mode 100644
index 000000000..14926f5d5
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_connection.c
@@ -0,0 +1,113 @@
+#include <math.h>
+#include "command.h"
+
+/* Parameters */
+
+static const command_parameter_t type_hicn = {
+ .name = "type",
+ .help = "connection type (hICN)",
+ .type = TYPE_ENUM(connection_type),
+ .offset = offsetof(hc_connection_t, type),
+};
+
+static const command_parameter_t type_tcp_udp = {
+ .name = "type",
+ .help = "connection type [tcp | udp]",
+ .type = TYPE_ENUM(connection_type),
+ .offset = offsetof(hc_connection_t, type),
+};
+
+static const command_parameter_t symbolic = {
+ .name = "symbolic",
+ .help = "symbolic name, e.g. 'conn1' (must be unique, start with alpha)",
+ .type = TYPE_SYMBOLIC,
+ .offset = offsetof(hc_connection_t, name),
+};
+
+static const command_parameter_t local_address = {
+ .name = "local_addr",
+ .help = "local IP address on which to bind.", // XXX optional
+ .type = TYPE_IP_ADDRESS,
+ .offset = offsetof(hc_connection_t, local_addr),
+ .offset2 = offsetof(hc_connection_t, family),
+};
+
+static const command_parameter_t local_port = {
+ .name = "local_port",
+ .help = "Local port.",
+ .type = TYPE_INT(1, pow(2, 16) - 1),
+ .offset = offsetof(hc_connection_t, local_port),
+};
+
+static const command_parameter_t remote_address = {
+ .name = "remote_address",
+ .help = "The IPv4 or IPv6 or hostname of the remote system.",
+ .type = TYPE_IP_ADDRESS,
+ .offset = offsetof(hc_connection_t, remote_addr),
+ .offset2 = offsetof(hc_connection_t, family),
+};
+
+static const command_parameter_t remote_port = {
+ .name = "remote_port",
+ .help = "Remote port.",
+ .type = TYPE_INT(1, pow(2, 16) - 1),
+ .offset = offsetof(hc_connection_t, remote_port),
+};
+
+static const command_parameter_t interface = {
+ .name = "interface",
+ .help = "Interface on which to bind", // optional ?
+ .type = TYPE_STRN(IFNAMSIZ),
+ .offset = offsetof(hc_connection_t, interface_name),
+};
+
+static const command_parameter_t symbolic_or_id = {
+ .name = "symbolic",
+ .help = "The connection symbolic name or id",
+ .type = TYPE_SYMBOLIC_OR_ID,
+ .offset = offsetof(hc_connection_t, name),
+};
+
+/* Commands */
+
+int
+on_connection_create(hc_connection_t * connection)
+{
+ connection->admin_state = FACE_STATE_UP;
+ return 0;
+}
+
+static const command_parser_t command_connection_create4 = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_CONNECTION,
+ .nparams = 5,
+ .parameters = { type_hicn, symbolic, local_address, remote_address,
+ interface },
+ .post_hook = (parser_hook_t)on_connection_create,
+};
+COMMAND_REGISTER(command_connection_create4);
+
+static const command_parser_t command_connection_create6 = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_CONNECTION,
+ .nparams = 7,
+ .parameters = { type_tcp_udp, symbolic, remote_address, remote_port,
+ local_address, local_port, interface },
+ .post_hook = (parser_hook_t)on_connection_create,
+};
+COMMAND_REGISTER(command_connection_create6);
+
+static const command_parser_t command_connection_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_CONNECTION,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_connection_list);
+
+static const command_parser_t command_connection_remove = {
+ .action = ACTION_DELETE,
+ .object = OBJECT_CONNECTION,
+ .nparams = 1,
+ .parameters = { symbolic_or_id },
+};
+COMMAND_REGISTER(command_connection_remove);
diff --git a/hicn-light/src/hicn/config/command_face.c b/hicn-light/src/hicn/config/command_face.c
new file mode 100644
index 000000000..d42dc59d9
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_face.c
@@ -0,0 +1,14 @@
+#include "command.h"
+
+/* Parameters */
+
+/* Commands */
+
+// XXX missing add
+
+static const command_parser_t command_face_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_FACE,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_face_list);
diff --git a/hicn-light/src/hicn/config/command_listener.c b/hicn-light/src/hicn/config/command_listener.c
new file mode 100644
index 000000000..9b0d3ce1a
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_listener.c
@@ -0,0 +1,87 @@
+#include <math.h>
+#include "command.h"
+
+/* Parameters */
+
+static const command_parameter_t protocol_hicn = {
+ .name = "protocol",
+ .help = "Protocol [hicn].",
+ .type = TYPE_ENUM(connection_type),
+ .offset = offsetof(hc_listener_t, type),
+};
+
+static const command_parameter_t protocol_tcp_udp = {
+ .name = "protocol",
+ .help = "Protocol [tcp | udp]",
+ .type = TYPE_ENUM(connection_type),
+ .offset = offsetof(hc_listener_t, type),
+};
+
+static const command_parameter_t symbolic = {
+ .name = "symbolic",
+ .help = "User defined name for listener, must start with alpha and be alphanum",
+ .type = TYPE_SYMBOLIC,
+ .offset = offsetof(hc_listener_t, name),
+};
+
+static const command_parameter_t local_address = {
+ .name = "local_addr",
+ .help = "IPv4 or IPv6 address (or prefix protocol = hicn) assigend to the local interface",
+ .type = TYPE_IP_ADDRESS,
+ .offset = offsetof(hc_listener_t, local_addr),
+ .offset2 = offsetof(hc_listener_t, family),
+};
+
+static const command_parameter_t local_port = {
+ .name = "local_port",
+ .help = "Local port.",
+ .type = TYPE_INT(1, pow(2, 16) - 1),
+ .offset = offsetof(hc_listener_t, local_port),
+};
+
+static const command_parameter_t interface = {
+ .name = "interface",
+ .help = "Interface on which to bind", // optional ?
+ .type = TYPE_STRN(IFNAMSIZ),
+ .offset = offsetof(hc_listener_t, interface_name),
+};
+
+static const command_parameter_t symbolic_or_id = {
+ .name = "symbolic",
+ .help = "The listener symbolic name or id",
+ .type = TYPE_SYMBOLIC_OR_ID,
+ .offset = offsetof(hc_listener_t, name),
+};
+
+/* Commands */
+
+static const command_parser_t command_listener_create4 = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_LISTENER,
+ .nparams = 4,
+ .parameters = { protocol_hicn, symbolic, local_address, interface },
+};
+COMMAND_REGISTER(command_listener_create4);
+
+static const command_parser_t command_listener_create6 = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_LISTENER,
+ .nparams = 5,
+ .parameters = { protocol_tcp_udp, symbolic, local_address, local_port, interface }
+};
+COMMAND_REGISTER(command_listener_create6);
+
+static const command_parser_t command_listener_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_LISTENER,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_listener_list);
+
+static const command_parser_t command_listener_remove = {
+ .action = ACTION_DELETE,
+ .object = OBJECT_LISTENER,
+ .nparams = 1,
+ .parameters = { symbolic_or_id },
+};
+COMMAND_REGISTER(command_listener_remove);
diff --git a/hicn-light/src/hicn/config/command_mapme.c b/hicn-light/src/hicn/config/command_mapme.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_mapme.c
diff --git a/hicn-light/src/hicn/config/command_policy.c b/hicn-light/src/hicn/config/command_policy.c
new file mode 100644
index 000000000..81c0be59d
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_policy.c
@@ -0,0 +1,53 @@
+#include <hicn/policy.h>
+
+#include "command.h"
+
+/* Parameters */
+
+static const command_parameter_t prefix = {
+ .name = "prefix",
+ .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).",
+ .type = TYPE_IP_PREFIX,
+ .offset = offsetof(hc_policy_t, remote_addr),
+ .offset2 = offsetof(hc_policy_t, len),
+ .offset3 = offsetof(hc_policy_t, family),
+};
+
+static const command_parameter_t app_name = {
+ .name = "app_name",
+ .help = "The application name associated to this policy",
+ .type = TYPE_STR,
+ .offset = offsetof(hc_policy_t, policy.app_name),
+};
+
+
+#define _(x, y) \
+static const command_parameter_t flag_ ## x = { \
+ .name = "flag:" #x, \
+ .help = "A value among [neutral|require|prefer|avoid|prohibit] with an optional '!' character prefix for disabling changes", \
+ .type = TYPE_POLICY_STATE(POLICY_TAG_ ## x), \
+ .offset = offsetof(hc_policy_t, policy.tags), \
+};
+ foreach_policy_tag
+#undef _
+
+/* Commands */
+
+static const command_parser_t command_policy_create = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_POLICY,
+ .nparams = 2 + POLICY_TAG_N,
+ .parameters = { prefix, app_name,
+#define _(x, y) flag_ ## x,
+ foreach_policy_tag
+#undef _
+ },
+};
+COMMAND_REGISTER(command_policy_create);
+
+static const command_parser_t command_policy_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_POLICY,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_policy_list);
diff --git a/hicn-light/src/hicn/config/command_punting.c b/hicn-light/src/hicn/config/command_punting.c
new file mode 100644
index 000000000..ad969e3d2
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_punting.c
@@ -0,0 +1,36 @@
+#include "command.h"
+
+/* Parameters */
+
+static const command_parameter_t symbolic_or_id = {
+ .name = "symbolic_or_id",
+ .help = "The symbolic name for an egress, or the egress punting id (see 'help list puntings')",
+ .type = TYPE_SYMBOLIC_OR_ID,
+ .offset = offsetof(hc_punting_t, face_id),
+};
+
+static const command_parameter_t prefix = {
+ .name = "prefix",
+ .help = "Prefix to add as a punting rule. (example 1234::0/64)",
+ .type = TYPE_IP_PREFIX,
+ .offset = offsetof(hc_punting_t, prefix),
+ .offset2 = offsetof(hc_punting_t, prefix_len),
+ .offset3 = offsetof(hc_punting_t, family),
+};
+
+/* Commands */
+
+static const command_parser_t command_punting_create = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_PUNTING,
+ .nparams = 2,
+ .parameters = { symbolic_or_id, prefix },
+};
+COMMAND_REGISTER(command_punting_create);
+
+static const command_parser_t command_punting_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_PUNTING,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_punting_list);
diff --git a/hicn-light/src/hicn/config/command_route.c b/hicn-light/src/hicn/config/command_route.c
new file mode 100644
index 000000000..b357cb036
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_route.c
@@ -0,0 +1,51 @@
+#include "command.h"
+
+/* Parameters */
+
+static const command_parameter_t symbolic_or_id = {
+ .name = "symbolic_or_id",
+ .help = "The symbolic name for an egress, or the egress route id (see 'help list routes')",
+ .type = TYPE_SYMBOLIC_OR_ID,
+ .offset = offsetof(hc_route_t, face_id),
+};
+
+static const command_parameter_t prefix = {
+ .name = "prefix",
+ .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).",
+ .type = TYPE_IP_PREFIX,
+ .offset = offsetof(hc_route_t, remote_addr),
+ .offset2 = offsetof(hc_route_t, len),
+ .offset3 = offsetof(hc_route_t, family),
+};
+
+static const command_parameter_t cost = {
+ .name = "cost",
+ .help = "Positive integer representing cost.",
+ .type = TYPE_INT(1, 255),
+ .offset = offsetof(hc_route_t, cost),
+};
+
+/* Commands */
+
+static const command_parser_t command_route_create = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_ROUTE,
+ .nparams = 3,
+ .parameters = { symbolic_or_id, prefix, cost },
+};
+COMMAND_REGISTER(command_route_create);
+
+static const command_parser_t command_route_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_ROUTE,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_route_list);
+
+static const command_parser_t command_route_remove = {
+ .action = ACTION_DELETE,
+ .object = OBJECT_ROUTE,
+ .nparams = 2,
+ .parameters = { symbolic_or_id, prefix },
+};
+COMMAND_REGISTER(command_route_remove);
diff --git a/hicn-light/src/hicn/config/command_strategy.c b/hicn-light/src/hicn/config/command_strategy.c
new file mode 100644
index 000000000..e3a11959c
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_strategy.c
@@ -0,0 +1,12 @@
+#include "command.h"
+
+/* Parameters */
+
+/* Commands */
+
+static const command_parser_t command_strategy_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_STRATEGY,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_strategy_list);
diff --git a/hicn-light/src/hicn/config/parse.c b/hicn-light/src/hicn/config/parse.c
new file mode 100644
index 000000000..4959b7cde
--- /dev/null
+++ b/hicn-light/src/hicn/config/parse.c
@@ -0,0 +1,354 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <hicn/ctrl/cli.h>
+#include <hicn/util/log.h>
+
+#include "parse.h"
+
+// help add [done]
+// help list
+// help quit
+// help remove
+// help set
+// help unset
+// help cache
+// help mapme
+// help update
+//
+// add connection hicn <symbolic> <remote_ip> <local_ip>
+// <symbolic> : symbolic name, e.g. 'conn1' (must be unique, start with alpha)
+// <remote_ip> : the IPv4 or IPv6 or hostname of the remote system
+// <local_ip> : optional local IP address to bind to
+
+/*
+ * As there is no portable way to generate a va_list to use with sscanf to
+ * support a variable number of arguments, and no way to use a variable array
+ * initialize in a nested struct, we use a fixed maximum number of parameters
+ *
+ * NOTE: update sscanf accordingly
+ */
+
+#include "command.h"
+
+static void * sscanf_params[MAX_PARAMETERS];
+
+const char * action_str[] = {
+#define _(x) [ACTION_ ## x] = #x,
+ foreach_action
+#undef _
+};
+
+#define action_str(x) action_str[x]
+
+hc_action_t
+action_from_str(const char * action_str)
+{
+#define _(x) \
+ if (strcasecmp(action_str, # x) == 0) \
+ return ACTION_ ## x; \
+ else
+ foreach_action
+#undef _
+ if (strcasecmp(action_str, "add") == 0)
+ return ACTION_CREATE;
+ else
+ if (strcasecmp(action_str, "remove") == 0)
+ return ACTION_DELETE;
+ else
+ return ACTION_UNDEFINED;
+}
+
+const char * object_str[] = {
+#define _(x) [OBJECT_ ## x] = #x,
+ foreach_object
+#undef _
+};
+
+#define object_str(x) object_str[x]
+
+hc_object_type_t
+object_from_str(const char * object_str)
+{
+#define _(x) \
+ if (strcasecmp(object_str, # x) == 0) \
+ return OBJECT_ ## x; \
+ else
+ foreach_object
+#undef _
+ return OBJECT_UNDEFINED;
+}
+
+const char *
+parser_type_fmt(const parser_type_t * type)
+{
+ switch(type->name) {
+ case TYPENAME_INT:
+ return TYPE_FMT_INT;
+ case TYPENAME_UINT:
+ return TYPE_FMT_UINT;
+ case TYPENAME_STR:
+ return (type->str.max_size > 0)
+ ? TYPE_FMT_STRN(type->str.max_size)
+ : TYPE_FMT_STR;
+ case TYPENAME_SYMBOLIC:
+ return TYPE_FMT_SYMBOLIC;
+ case TYPENAME_SYMBOLIC_OR_ID:
+ return TYPE_FMT_SYMBOLIC_OR_ID;
+ case TYPENAME_IP_ADDRESS:
+ return TYPE_FMT_IP_ADDRESS;
+ case TYPENAME_IP_PREFIX:
+ return TYPE_FMT_IP_PREFIX;
+ case TYPENAME_ENUM:
+ return TYPE_FMT_ENUM;
+ case TYPENAME_POLICY_STATE:
+ return TYPE_FMT_POLICY_STATE;
+ case TYPENAME_UNDEFINED:
+ default:
+ return NULL;
+ }
+}
+
+int
+parser_type_func(const parser_type_t * type, void * src, void *dst, void * dst2, void * dst3)
+{
+ switch(type->name) {
+ case TYPENAME_INT:
+ *(int*)dst = *(int*)src;
+ break;
+ case TYPENAME_UINT:
+ *(unsigned*)dst = *(unsigned*)src;
+ break;
+ case TYPENAME_STR:
+ if (type->str.max_size > 0) {
+ strncpy(dst, src, type->str.max_size);
+ } else {
+ strcpy(dst, src);
+ }
+ break;
+ case TYPENAME_SYMBOLIC:
+ break;
+ case TYPENAME_SYMBOLIC_OR_ID:
+ break;
+ case TYPENAME_IP_ADDRESS:
+ *(ip_address_t*)dst = IP_ADDRESS_EMPTY; // XXX
+ *(int*)dst2 = AF_INET;
+ break;
+ case TYPENAME_IP_PREFIX:
+ *(ip_address_t*)dst = IP_ADDRESS_EMPTY; // XXX
+ *(int*)dst2 = 128;
+ *(int*)dst3 = AF_INET;
+ break;
+ case TYPENAME_ENUM:
+ /* Enum index from string */
+ assert(type->enum_.from_str);
+ const char * str = *(const char **)src;
+ *(int*)dst = type->enum_.from_str(str);
+ break;
+ case TYPENAME_POLICY_STATE:
+ {
+ assert(IS_VALID_POLICY_TAG(type->policy_state.tag));
+ policy_tag_t tag = type->policy_state.tag;
+ /* Format string is "%ms" */
+ const char * str = *(const char **)src;
+ policy_tag_state_t *pts = ((policy_tag_state_t*)dst);
+ pts[tag].disabled = (str[0] == '!') ? 1 : 0;
+ pts[tag].state = policy_state_from_str(str + pts[tag].disabled);
+ break;
+ }
+ case TYPENAME_UNDEFINED:
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int
+parse_params(const command_parser_t * parser, const char * params_s,
+ hc_command_t * command)
+{
+ char fmt[1024];
+ int n;
+ size_t size = 0;
+
+ char * pos = fmt;
+
+ int must_free[MAX_PARAMETERS];
+
+ unsigned count = 0;
+ for (unsigned i = 0; i < parser->nparams; i++) {
+ const command_parameter_t * p = &parser->parameters[i];
+ const char * fmt = parser_type_fmt(&p->type);
+ if (!fmt) {
+ WARN("Ignored parameter %s with unknown type formatter", p->name);
+ continue;
+ }
+ must_free[count] = (strcmp(fmt, "%ms") == 0),
+
+ n = snprintf(pos, 1024 - size, "%s", fmt);
+ pos += n;
+
+ *pos = ' ';
+ pos++;
+
+ size += n + 1;
+ count++;
+ }
+ *pos = '\0';
+
+ void ** sp = sscanf_params;
+ /* Update MAX_PARAMETERS accordingly in command.h */
+ sscanf(params_s, fmt, &sp[0], &sp[1], &sp[2], &sp[3], &sp[4], &sp[5],
+ &sp[6], &sp[7], &sp[8], &sp[9]);
+
+ for (unsigned i = 0; i < count; i++) {
+ const command_parameter_t * p = &parser->parameters[i];
+ if (parser_type_func(&p->type, &sp[i], &command->object.as_uint8 + p->offset,
+ &command->object.as_uint8 + p->offset2,
+ &command->object.as_uint8 + p->offset3) < 0) {
+ ERROR("Error during parsing of parameter '%s' value\n", p->name);
+ goto ERR;
+ }
+ if (must_free[i])
+ free(sp[i]);
+ }
+ return 0;
+
+ERR:
+ return -1;
+}
+
+int
+parse(const char * cmd, hc_command_t * command)
+{
+ int nparams = 0;
+ char * action_s = NULL;
+ char * object_s = NULL;
+ char * params_s = NULL;
+
+ errno = 0;
+ // XXX broken with zero parameters
+ int n = sscanf(cmd, "%ms %ms%m[^\n]s", &action_s, &object_s, &params_s);
+ if ((n < 2) || (n > 3)) {
+ if (errno != 0)
+ perror("scanf");
+ return -1;
+ }
+
+ command->action = action_from_str(action_s);
+ command->object.type = object_from_str(object_s);
+
+ if (params_s) { //strlen(params_s) > 0) {
+ for (char *ptr = params_s; (ptr = strchr(ptr, ' ')) != NULL; ptr++)
+ nparams++;
+ }
+
+ /*
+ * This checks is important even with 0 parameters as it checks whether the
+ * command exists.
+ */
+ const command_parser_t * parser = command_search(command->action, command->object.type, nparams);
+ if (!parser) {
+ ERROR("Could not find parser for command '%s %s'", action_s, object_s);
+ goto ERR;
+ }
+
+ if (params_s) {
+ if (parse_params(parser, params_s, command) < 0) {
+ ERROR("Could not parse '%s %s' command", action_s, object_s);
+ goto ERR;
+ }
+ }
+
+ if (parser->post_hook)
+ parser->post_hook(&command->object.as_uint8);
+
+ /* LIST commands with 0 parameters do not expect an output */
+ if (params_s) {
+ char buf[MAXSZ_OBJECT];
+ int rc = hc_object_snprintf(buf, MAXSZ_OBJECT, &command->object);
+ if (rc < 0)
+ snprintf(buf, MAXSZ_OBJECT, "%s", "[hc_snprintf_error]");
+ else if (rc >= MAXSZ_OBJECT) {
+ buf[MAXSZ_OBJECT-1] = '\0';
+ buf[MAXSZ_OBJECT-2] = '.';
+ buf[MAXSZ_OBJECT-3] = '.';
+ buf[MAXSZ_OBJECT-4] = '.';
+ }
+
+ DEBUG("%s %s <%s>", action_s, object_s, buf);
+ } else {
+ DEBUG("%s %s <No parameters>", action_s, object_s);
+ }
+
+ free(action_s);
+ free(object_s);
+ free(params_s);
+
+ return 0;
+
+ERR:
+ free(action_s);
+ free(object_s);
+ free(params_s);
+ return -1;
+}
+
+#if 0 // tests
+/* For the tests, we will need to test all non-compliant inputs */
+const char * cmds[] = {
+ "add connection hicn conn1 8.8.8.8 127.0.0.1 eth0",
+ "add connection udp <symbolic> <remote_ip> <port> <local_ip> <port> eth0",
+ "add listener udp lst1 127.0.0.1 9695 eth0",
+ //"add face",
+ "add route 3 b001::/16 1",
+ //"add punting",
+ //"add strategy",
+ "add policy b001::/16 webex require avoid prohibit !prohibit neutral !require prefer",
+ "list connection", // need pluralize
+ "list listener",
+ "list face",
+ "list route",
+ "list punting",
+ "list strategy",
+ "list policy",
+ "remove connection 1",
+ "remove listener 1",
+ //"remove face",
+ "remove route 1 b001::/16",
+ //"remove punting",
+ //"remove policy",
+ "set debug",
+ "unset debug",
+ "set strategy b001::/16 random", // related prefixes (10 max) ?
+ "set strategy b001::/16 load_balancer",
+ "set strategy b001::/16 low_latency",
+ "set wldr <on|off> <connection_id>", // on-off vs unset
+ "cache clear",
+ "cache store on/off", // set/unset
+ "cache serve on/off",
+ "mapme enable on/off",
+ "mapme discovery on/off",
+ "mapme timescale 500ms",
+ "mapme retx 500ms",
+ "update connection conn1 WT",
+};
+
+#define array_size(x) sizeof(x) / sizeof(typeof(x[0]))
+int main()
+{
+ for (unsigned i = 0; i < array_size(cmds); i++) {
+ printf("PARSING [%d] %s\n", i, cmds[i]);
+ if (parse(cmds[i]) < 0) {
+ ERROR("Could not parse command: %s\n", cmds[i]);
+ continue;
+ }
+ }
+ exit(EXIT_SUCCESS);
+
+ERR:
+ exit(EXIT_FAILURE);
+}
+#endif
diff --git a/hicn-light/src/hicn/config/parse.h b/hicn-light/src/hicn/config/parse.h
new file mode 100644
index 000000000..4c3bacd9a
--- /dev/null
+++ b/hicn-light/src/hicn/config/parse.h
@@ -0,0 +1,6 @@
+#ifndef HICNLIGHT_PARSE_CMD
+#define HICNLIGHT_PARSE_CMD
+
+int parse(const char * cmd, hc_command_t * command);
+
+#endif /* HICNLIGHT_PARSE_CMD */
diff --git a/hicn-light/src/hicn/core/CMakeLists.txt b/hicn-light/src/hicn/core/CMakeLists.txt
index f877717aa..32b546400 100644
--- a/hicn-light/src/hicn/core/CMakeLists.txt
+++ b/hicn-light/src/hicn/core/CMakeLists.txt
@@ -75,3 +75,7 @@ set(TO_INSTALL_HEADER_FILES
${HEADER_FILES}
PARENT_SCOPE
)
+
+if (BUILD_TESTS)
+ add_subdirectory(test)
+endif() \ No newline at end of file
diff --git a/hicn-light/src/hicn/core/address_pair.h b/hicn-light/src/hicn/core/address_pair.h
index 4dfdfd9de..09800aa62 100644
--- a/hicn-light/src/hicn/core/address_pair.h
+++ b/hicn-light/src/hicn/core/address_pair.h
@@ -21,9 +21,10 @@
#ifndef HICNLIGHT_ADDRESS_PAIR_H
#define HICNLIGHT_ADDRESS_PAIR_H
-#include <hicn/core/address.h>
#include <hicn/util/ip_address.h>
+#include "address.h"
+
typedef struct {
address_t local;
address_t remote;
diff --git a/hicn-light/src/hicn/core/connection.h b/hicn-light/src/hicn/core/connection.h
index d9ef817d2..186cad5c3 100644
--- a/hicn-light/src/hicn/core/connection.h
+++ b/hicn-light/src/hicn/core/connection.h
@@ -21,11 +21,12 @@
#ifndef HICNLIGHT_CONNECTION_H
#define HICNLIGHT_CONNECTION_H
-#include <hicn/core/address_pair.h>
-#include <hicn/core/listener.h>
-#include <hicn/core/msgbuf.h>
#include <hicn/face.h>
+#include "address_pair.h"
+#include "listener.h"
+#include "msgbuf.h"
+
#ifdef WITH_POLICY
#include <hicn/policy.h>
#endif /* WITH_POLICY */
diff --git a/hicn-light/src/hicn/core/connection_table.h b/hicn-light/src/hicn/core/connection_table.h
index 8a9342f45..d32a5fee8 100644
--- a/hicn-light/src/hicn/core/connection_table.h
+++ b/hicn-light/src/hicn/core/connection_table.h
@@ -30,11 +30,11 @@
#ifndef HICNLIGHT_CONNECTION_TABLE_H
#define HICNLIGHT_CONNECTION_TABLE_H
-#include <hicn/core/address_pair.h>
-#include <hicn/core/connection.h>
-#include <hicn/base/hash.h>
-#include <hicn/base/khash.h>
-#include <hicn/base/pool.h>
+#include "address_pair.h"
+#include "connection.h"
+#include "../base/hash.h"
+#include "../base/khash.h"
+#include "../base/pool.h"
#define _ct_var(x) _ct_var_##x
diff --git a/hicn-light/src/hicn/core/content_store.c b/hicn-light/src/hicn/core/content_store.c
index 74b675224..cf1fe3af9 100644
--- a/hicn-light/src/hicn/core/content_store.c
+++ b/hicn-light/src/hicn/core/content_store.c
@@ -112,11 +112,10 @@ void cs_clear(cs_t * cs)
}
off_t
-cs_match(cs_t * cs, off_t msgbuf_id, uint64_t now)
+cs_match(cs_t * cs, msgbuf_pool_t * msgbuf_pool, off_t msgbuf_id, uint64_t now)
{
assert(cs);
- const msgbuf_pool_t * msgbuf_pool = cs_get_msgbuf_pool(cs);
const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
assert(msgbuf);
@@ -133,7 +132,7 @@ cs_match(cs_t * cs, off_t msgbuf_id, uint64_t now)
if (cs_entry_has_expiry_time(entry) &&
cs_entry_get_expiry_time(entry) < now) {
// the entry is expired, we can remove it
- cs_remove_entry(cs, entry);
+ cs_remove_entry(cs, msgbuf_pool, entry);
goto NOT_FOUND;
}
@@ -160,7 +159,7 @@ NOT_FOUND:
#define msgbuf_acquire(x) (x)
cs_entry_t *
-cs_add(cs_t * cs, off_t msgbuf_id, uint64_t now)
+cs_add(cs_t * cs, msgbuf_pool_t * msgbuf_pool, off_t msgbuf_id, uint64_t now)
{
assert(cs);
assert(msgbuf_id_is_valid(msgbuf_id));
@@ -235,7 +234,7 @@ ERR_ENTRY:
}
int
-cs_remove_entry(cs_t * cs, cs_entry_t * entry)
+cs_remove_entry(cs_t * cs, msgbuf_pool_t * msgbuf_pool, cs_entry_t * entry)
{
assert(cs);
assert(entry);
@@ -245,7 +244,6 @@ cs_remove_entry(cs_t * cs, cs_entry_t * entry)
off_t msgbuf_id = cs_entry_get_msgbuf_id(entry);
- const msgbuf_pool_t * msgbuf_pool = cs_get_msgbuf_pool(cs);
const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
khiter_t k = kh_get_cs_name(cs->index_by_name, msgbuf_get_name(msgbuf));
@@ -263,7 +261,7 @@ cs_remove_entry(cs_t * cs, cs_entry_t * entry)
//
// XXX TODO what is the difference between purge and remove ?
bool
-cs_remove(cs_t * cs, msgbuf_t * msgbuf)
+cs_remove(cs_t * cs, msgbuf_pool_t * msgbuf_pool, msgbuf_t * msgbuf)
{
assert(cs);
assert(msgbuf);
@@ -277,7 +275,7 @@ cs_remove(cs_t * cs, msgbuf_t * msgbuf)
cs_entry_t * entry = cs->entries + kh_val(cs->index_by_name, k);
assert(entry);
- cs_remove_entry(cs, entry);
+ cs_remove_entry(cs, msgbuf_pool, entry);
return true;
}
diff --git a/hicn-light/src/hicn/core/content_store.h b/hicn-light/src/hicn/core/content_store.h
index 2973b3955..95b0a1d0a 100644
--- a/hicn-light/src/hicn/core/content_store.h
+++ b/hicn-light/src/hicn/core/content_store.h
@@ -58,7 +58,6 @@ typedef struct {
void * index_by_expiry_time;
#endif
- const msgbuf_pool_t * msgbuf_pool;
void * data; // per cs type data
void * options;
@@ -96,13 +95,13 @@ void cs_free(cs_t * cs);
void cs_clear(cs_t * cs);
-off_t cs_match(cs_t * cs, off_t msgbuf_id, uint64_t now);
+off_t cs_match(cs_t * cs, msgbuf_pool_t * msgbuf_pool, off_t msgbuf_id, uint64_t now);
-cs_entry_t * cs_add(cs_t * cs, off_t msgbuf_id, uint64_t now);
+cs_entry_t * cs_add(cs_t * cs, msgbuf_pool_t * msgbuf_pool, off_t msgbuf_id, uint64_t now);
-int cs_remove_entry(cs_t * cs, cs_entry_t * entry);
+int cs_remove_entry(cs_t * cs, msgbuf_pool_t * msgbuf_pool, cs_entry_t * entry);
-bool cs_remove(cs_t * cs, msgbuf_t * msgbuf);
+bool cs_remove(cs_t * cs, msgbuf_pool_t * msgbuf_pool, msgbuf_t * msgbuf);
#define cs_size(content_store) (pool_len(cs->entries))
@@ -112,13 +111,6 @@ void cs_purge_entry(cs_t * cs, cs_entry_t * entry);
#define cs_entry_at(cs, id) (&(cs)->entries[id])
-static inline
-const msgbuf_pool_t *
-cs_get_msgbuf_pool(const cs_t * cs)
-{
- return cs->msgbuf_pool;
-}
-
typedef struct {
const char * name;
diff --git a/hicn-light/src/hicn/core/fib.h b/hicn-light/src/hicn/core/fib.h
index f60a42cae..2b9925b61 100644
--- a/hicn-light/src/hicn/core/fib.h
+++ b/hicn-light/src/hicn/core/fib.h
@@ -12,12 +12,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef fib_h
-#define fib_h
-#include <hicn/core/msgbuf.h>
-#include <hicn/core/name.h>
-#include <hicn/core/fib_entry.h>
+#ifndef HICNLIGHT_FIB_H
+#define HICNLIGHT_FIB_H
+
+#include "fib_entry.h"
+#include "msgbuf.h"
+#include "name.h"
#define _fib_var(x) _fib_ ## x
@@ -57,4 +58,4 @@ do {
free(_fib_var(array)); \
} while(0)
-#endif // fib_h
+#endif /* HICNLIGHT_FIB_H */
diff --git a/hicn-light/src/hicn/core/fib_entry.h b/hicn-light/src/hicn/core/fib_entry.h
index 94d283d0f..5ec0f29de 100644
--- a/hicn-light/src/hicn/core/fib_entry.h
+++ b/hicn-light/src/hicn/core/fib_entry.h
@@ -37,17 +37,12 @@
#ifndef fib_entry_h
#define fib_entry_h
-#include <hicn/core/name.h>
-#include <hicn/core/strategy.h>
-#include <hicn/core/msgbuf.h>
-#include <hicn/core/nexthops.h>
-#include <hicn/core/prefix_stats.h>
-#include <hicn/utils/commands.h> // strategy type
-
-#ifdef WITH_MAPME
-//#include <parc/algol/parc_EventTimer.h>
-//#include <parc/algol/parc_Iterator.h>
-#endif /* WITH_MAPME */
+#include "name.h"
+#include "strategy.h"
+#include "msgbuf.h"
+#include "nexthops.h"
+#include "prefix_stats.h"
+//#include "../utils/commands.h" // strategy type
typedef struct {
Name *name;
diff --git a/hicn-light/src/hicn/core/forwarder.c b/hicn-light/src/hicn/core/forwarder.c
index 543fc99e4..4a31075f6 100644
--- a/hicn-light/src/hicn/core/forwarder.c
+++ b/hicn-light/src/hicn/core/forwarder.c
@@ -658,7 +658,7 @@ _satisfy_from_cs(forwarder_t * forwarder, off_t msgbuf_id)
assert(forwarder);
assert(msgbuf_id_is_valid(msgbuf_id));
- const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
@@ -670,14 +670,14 @@ _satisfy_from_cs(forwarder_t * forwarder, off_t msgbuf_id)
return false;
// See if there's a match in the store.
- off_t data_msgbuf_id = cs_match(forwarder_get_cs(forwarder), msgbuf_id,
+ off_t data_msgbuf_id = cs_match(forwarder_get_cs(forwarder), msgbuf_pool, msgbuf_id,
ticks_now());
if (msgbuf_id_is_valid(data_msgbuf_id))
return false;
// Remove it from the PIT. nexthops is allocated, so need to destroy
- nexthops_t * nexthops = pit_on_data(forwarder->pit, data_msgbuf_id);
+ nexthops_t * nexthops = pit_on_data(forwarder->pit, msgbuf_pool, data_msgbuf_id);
assert(nexthops); // Illegal state: got a null nexthops for an interest we just inserted
// send message in reply, then done
@@ -711,7 +711,7 @@ forwarder_process_interest(forwarder_t * forwarder, off_t msgbuf_id)
assert(forwarder);
assert(msgbuf_id_is_valid(msgbuf_id));
- const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
@@ -726,7 +726,7 @@ forwarder_process_interest(forwarder_t * forwarder, off_t msgbuf_id)
// (1) Try to aggregate in PIT
- pit_verdict_t verdict = pit_on_interest(forwarder->pit, msgbuf_id);
+ pit_verdict_t verdict = pit_on_interest(forwarder->pit, msgbuf_pool, msgbuf_id);
switch(verdict) {
case PIT_VERDICT_AGGREGATE:
forwarder->stats.countInterestsAggregated++;
@@ -781,7 +781,7 @@ static
ssize_t
forwarder_process_data(forwarder_t * forwarder, off_t msgbuf_id)
{
- const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
char *nameString = name_ToString(msgbuf_get_name(msgbuf));
@@ -792,7 +792,7 @@ forwarder_process_data(forwarder_t * forwarder, off_t msgbuf_id)
forwarder->stats.countReceived++;
forwarder->stats.countObjectsReceived++;
- nexthops_t * ingressSetUnion = pit_on_data(forwarder->pit, msgbuf_id);
+ nexthops_t * ingressSetUnion = pit_on_data(forwarder->pit, msgbuf_pool, msgbuf_id);
if (!ingressSetUnion) {
// (1) If it does not match anything in the PIT, drop it
forwarder->stats.countDroppedNoReversePath++;
@@ -822,7 +822,7 @@ forwarder_process_data(forwarder_t * forwarder, off_t msgbuf_id)
const connection_t * conn = connection_table_get_by_id(table, msgbuf_get_connection_id(msgbuf));
if (forwarder->store_in_cs && connection_is_local(conn)) {
- cs_add(forwarder->cs, msgbuf_id, ticks_now());
+ cs_add(forwarder->cs, msgbuf_pool, msgbuf_id, ticks_now());
DEBUG("Message %p store in CS anyway", msgbuf);
}
@@ -831,7 +831,7 @@ forwarder_process_data(forwarder_t * forwarder, off_t msgbuf_id)
// (2) Add to Content Store. Store may remove expired content, if necessary,
// depending on store policy.
if (forwarder->store_in_cs) {
- cs_add(forwarder->cs, msgbuf_id, ticks_now());
+ cs_add(forwarder->cs, msgbuf_pool, msgbuf_id, ticks_now());
}
// (3) Reverse path forward via PIT entries
return forwarder_forward_to_nexthops(forwarder, msgbuf_id, ingressSetUnion);
@@ -1123,7 +1123,7 @@ forwarder_receive(forwarder_t * forwarder, listener_t * listener,
assert(msgbuf_id_is_valid(msgbuf_id));
assert(pair);
- const msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_pool_t * msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
assert(msgbuf);
diff --git a/hicn-light/src/hicn/core/forwarder.h b/hicn-light/src/hicn/core/forwarder.h
index a76e36530..f5ac375da 100644
--- a/hicn-light/src/hicn/core/forwarder.h
+++ b/hicn-light/src/hicn/core/forwarder.h
@@ -29,23 +29,22 @@
#include <stdlib.h>
#include <sys/socket.h> // struct mmsghdr
-#include <hicn/core/msgbuf.h>
-#include <hicn/core/content_store.h>
-#include <hicn/core/connection.h>
-#include <hicn/core/connection_table.h>
-#include <hicn/core/listener_table.h>
-#include <hicn/core/msgbuf_pool.h>
-
-#include <hicn/config/configuration.h>
+#include "connection.h"
+#include "connection_table.h"
+#include "content_store.h"
+#include "listener_table.h"
+#include "msgbuf.h"
+#include "msgbuf_pool.h"
+#include "../config/configuration.h"
#ifdef WITH_MAPME
-#include <hicn/core/fib.h>
+#include "fib.h"
#endif /* WITH_MAPME */
#define PORT_NUMBER 9695
#define PORT_NUMBER_AS_STRING "9695"
-#include <hicn/utils/commands.h>
+//#include <hicn/utils/commands.h>
// ==============================================
diff --git a/hicn-light/src/hicn/core/listener.c b/hicn-light/src/hicn/core/listener.c
index d24fafba0..de078b889 100644
--- a/hicn-light/src/hicn/core/listener.c
+++ b/hicn-light/src/hicn/core/listener.c
@@ -216,7 +216,7 @@ listener_read_single(listener_t * listener)
for (;;) {
msgbuf_t * msgbuf = NULL;
- off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, msgbuf);
+ off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf);
if (!msgbuf_id_is_valid(msgbuf_id))
return 0;
diff --git a/hicn-light/src/hicn/core/listener.h b/hicn-light/src/hicn/core/listener.h
index eb1ec6893..79aefef51 100644
--- a/hicn-light/src/hicn/core/listener.h
+++ b/hicn-light/src/hicn/core/listener.h
@@ -21,9 +21,9 @@
#ifndef HICNLIGHT_LISTENER_H
#define HICNLIGHT_LISTENER_H
-#include <hicn/core/address_pair.h>
#include <hicn/face.h>
+#include "address_pair.h"
#include "msgbuf.h"
#include "../base/loop.h"
diff --git a/hicn-light/src/hicn/core/listener_table.h b/hicn-light/src/hicn/core/listener_table.h
index 70cd8bbbf..5824f0551 100644
--- a/hicn-light/src/hicn/core/listener_table.h
+++ b/hicn-light/src/hicn/core/listener_table.h
@@ -30,12 +30,12 @@
#ifndef HICNLIGHT_LISTENER_TABLE_H
#define HICNLIGHT_LISTENER_TABLE_H
-#include <hicn/core/address.h>
-#include <hicn/base/common.h>
-#include <hicn/base/hash.h>
-#include <hicn/base/khash.h>
-#include <hicn/core/listener.h>
-#include <hicn/base/pool.h>
+#include "address.h"
+#include "listener.h"
+#include "../base/common.h"
+#include "../base/hash.h"
+#include "../base/khash.h"
+#include "../base/pool.h"
#define _lt_var(x) _lt_var_##x
diff --git a/hicn-light/src/hicn/core/messageHandler.h b/hicn-light/src/hicn/core/messageHandler.h
index bc7ecf597..1df511a5c 100644
--- a/hicn-light/src/hicn/core/messageHandler.h
+++ b/hicn-light/src/hicn/core/messageHandler.h
@@ -551,7 +551,7 @@ static inline uint8_t * messageHandler_CreateProbePacket(hicn_format_t format,
size_t header_length;
hicn_packet_get_header_length_from_format(format, &header_length);
- uint8_t *pkt = calloc(header_length, 1);
+ uint8_t *pkt = (uint8_t *) calloc(header_length, 1);
hicn_packet_init_header(format, (hicn_header_t *) pkt);
@@ -584,7 +584,7 @@ static inline void messageHandler_CreateProbeReply(uint8_t * probe,
}
static inline hicn_name_t * messageHandler_CreateProbeName(const ip_prefix_t *address){
- hicn_name_t * name = calloc(sizeof(hicn_name_t), 1);
+ hicn_name_t * name = (hicn_name_t *) calloc(sizeof(hicn_name_t), 1);
hicn_name_create_from_ip_prefix(address, 0, name);
return name;
}
diff --git a/hicn-light/src/hicn/core/msgbuf_pool.c b/hicn-light/src/hicn/core/msgbuf_pool.c
index 597123a7a..137d9bb99 100644
--- a/hicn-light/src/hicn/core/msgbuf_pool.c
+++ b/hicn-light/src/hicn/core/msgbuf_pool.c
@@ -43,11 +43,10 @@ msgbuf_pool_free(msgbuf_pool_t * msgbuf_pool)
free(msgbuf_pool);
}
-int
-msgbuf_pool_get(msgbuf_pool_t * msgbuf_pool, msgbuf_t * msgbuf)
+off_t
+msgbuf_pool_get(msgbuf_pool_t * msgbuf_pool, msgbuf_t ** msgbuf)
{
- pool_get(msgbuf_pool->buffers, msgbuf);
- return 0;
+ return pool_get(msgbuf_pool->buffers, *msgbuf);
}
void
@@ -60,15 +59,16 @@ int
msgbuf_pool_getn(msgbuf_pool_t * msgbuf_pool, msgbuf_t ** msgbuf, size_t n)
{
for (unsigned i = 0; i < n; i++) {
- if (!msgbuf_pool_get(msgbuf_pool, msgbuf[i])) {
+ // If not able to get the msgbuf
+ if (msgbuf_pool_get(msgbuf_pool, &msgbuf[i]) < 0) {
+ // Release all the msgbufs retrieved so far
for (unsigned j = 0; j < i; j++) {
msgbuf_pool_put(msgbuf_pool, msgbuf[j]);
- return 0;
}
- break;
+ return -1;
}
}
- return -1;
+ return 0;
}
off_t
diff --git a/hicn-light/src/hicn/core/msgbuf_pool.h b/hicn-light/src/hicn/core/msgbuf_pool.h
index 2ada9fa14..a5c0248bc 100644
--- a/hicn-light/src/hicn/core/msgbuf_pool.h
+++ b/hicn-light/src/hicn/core/msgbuf_pool.h
@@ -17,7 +17,7 @@
* @file msgbuf_pool.h
* @brief hICN msgbuf pool.
*
- * THe msgbuf pool is used to store packet payloads while the packets are in
+ * The msgbuf pool is used to store packet payloads while the packets are in
* transit, as well as holding them into the packet cache (PIT, CSS), WLDR,
* mapme, etc.
*
@@ -46,20 +46,80 @@ typedef struct {
msgbuf_t * buffers;
} msgbuf_pool_t;
-// 0 for init size means a default value (of 1024)
-// 0 for max_size means no limit
+/**
+ * @brief Allocate and initialize a msgbuf pool structure (helper).
+ *
+ * @param[in] init_size Number of buffers that can be stored in msgbuf pool.
+ * @param[in] max_size Maximum size.
+ * @return msgbuf_pool_t* Pointer to the msgbuf pool created.
+ *
+ * @note
+ * - 0 for init size means a default value (of 1024)
+ * - 0 for max_size means no limit
+ */
msgbuf_pool_t * _msgbuf_pool_create(size_t init_size, size_t max_size);
+/**
+ * @brief Allocate and initialize a msgbuf pool data structure.
+ *
+ * @return msgbuf_pool_t* Pointer to the msgbuf pool created.
+ */
#define msgbuf_pool_create() _msgbuf_pool_create(0, 0)
+/**
+ * @brief Free a msgbuf pool data structure.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to free.
+ */
void msgbuf_pool_free(msgbuf_pool_t * msgbuf_pool);
-int msgbuf_pool_get(msgbuf_pool_t * msgbuf_pool, msgbuf_t * msgbuf);
+/**
+ * @brief Get a free msgbuf from the msgbuf pool data structure.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use.
+ * @param[in, out] msgbuf Empty msgbuf that will be used to return the
+ * allocated one from the msgbuf pool.
+ * @return off_t ID of the msgbuf requested.
+ */
+off_t msgbuf_pool_get(msgbuf_pool_t * msgbuf_pool, msgbuf_t ** msgbuf);
+/**
+ * @brief Release a msgbuf previously obtained, making it available to the msgbuf pool.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use.
+ * @param[in] msgbuf Pointer to the msgbuf to release.
+ */
+void msgbuf_pool_put(msgbuf_pool_t * msgbuf_pool, msgbuf_t * msgbuf);
+
+
+/**
+ * @brief Get multiple free msgbufs from the msgbuf pool data structure.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use.
+ * @param[in, out] msgbuf Pointer to the first empty msgbuf that will be used to
+ * allocate the msgbufs.
+ * @param[in] n Number of msgbufs requested.
+ * @retval 0 Success.
+ * @retval -1 Error.
+ */
int msgbuf_pool_getn(msgbuf_pool_t * msgbuf_pool, msgbuf_t ** msgbuf, size_t n);
+/**
+ * @brief Get the ID corresponding to the msgbuf requested.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use.
+ * @param[in] msgbuf Pointer to the msgbuf to retrieve the ID for.
+ * @return off_t ID of the msgbuf requested.
+ */
off_t msgbuf_pool_get_id(msgbuf_pool_t * msgbuf_pool, msgbuf_t * msgbuf);
+/**
+ * @brief Get the msgbuf corresponding to the ID requested.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use.
+ * @param[in] id Index of the msgbuf to retrieve.
+ * @return msgbuf_t* Pointer to the msgbuf corresponding to the ID requested.
+ */
msgbuf_t * msgbuf_pool_at(const msgbuf_pool_t * msgbuf_pool, off_t id);
#endif /* HICNLIGHT_MSGBUF_POOL_H */
diff --git a/hicn-light/src/hicn/core/nameBitvector.h b/hicn-light/src/hicn/core/nameBitvector.h
index 256af68a0..d5977f5c0 100644
--- a/hicn-light/src/hicn/core/nameBitvector.h
+++ b/hicn-light/src/hicn/core/nameBitvector.h
@@ -20,7 +20,7 @@
#include <stdint.h>
#include <stdlib.h>
-#include <hicn/core/address.h>
+#include "address.h"
struct name_bitvector;
typedef struct name_bitvector NameBitvector;
diff --git a/hicn-light/src/hicn/core/nexthops.h b/hicn-light/src/hicn/core/nexthops.h
index 8e4878b45..e144fcdc4 100644
--- a/hicn-light/src/hicn/core/nexthops.h
+++ b/hicn-light/src/hicn/core/nexthops.h
@@ -25,7 +25,7 @@
#include <stdbool.h>
#include <stdlib.h>
-#include <hicn/core/strategy.h>
+#include "strategy.h"
#define _nexthops_var(x) _nexthops_##x
diff --git a/hicn-light/src/hicn/core/pit.c b/hicn-light/src/hicn/core/pit.c
index e80d895ec..36ec8aed1 100644
--- a/hicn-light/src/hicn/core/pit.c
+++ b/hicn-light/src/hicn/core/pit.c
@@ -96,12 +96,11 @@ pit_free(pit_t * pit)
}
pit_verdict_t
-pit_on_interest(pit_t * pit, off_t msgbuf_id)
+pit_on_interest(pit_t * pit, msgbuf_pool_t * msgbuf_pool, off_t msgbuf_id)
{
assert(pit);
assert(msgbuf_id_is_valid(msgbuf_id));
- const msgbuf_pool_t * msgbuf_pool = pit_get_msgbuf_pool(pit);
const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
@@ -175,12 +174,11 @@ NOT_FOUND:
}
nexthops_t *
-pit_on_data(pit_t * pit, off_t msgbuf_id)
+pit_on_data(pit_t * pit, msgbuf_pool_t * msgbuf_pool, off_t msgbuf_id)
{
assert(pit);
assert(msgbuf_id_is_valid(msgbuf_id));
- const msgbuf_pool_t * msgbuf_pool = pit_get_msgbuf_pool(pit);
const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA);
@@ -219,12 +217,11 @@ NOT_FOUND:
}
void
-pit_remove(pit_t * pit, off_t msgbuf_id)
+pit_remove(pit_t * pit, msgbuf_pool_t * msgbuf_pool, off_t msgbuf_id)
{
assert(pit);
assert(msgbuf_id_is_valid(msgbuf_id));
- const msgbuf_pool_t * msgbuf_pool = pit_get_msgbuf_pool(pit);
const msgbuf_t * msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
assert(msgbuf);
diff --git a/hicn-light/src/hicn/core/pit.h b/hicn-light/src/hicn/core/pit.h
index 5607827fe..85958f88e 100644
--- a/hicn-light/src/hicn/core/pit.h
+++ b/hicn-light/src/hicn/core/pit.h
@@ -69,7 +69,6 @@ typedef enum {
KHASH_INIT(pit_name, const Name *, unsigned, 0, name_hash, name_hash_eq);
typedef struct {
- msgbuf_pool_t * msgbuf_pool;
size_t max_size;
pit_entry_t * entries; // pool
kh_pit_name_t * index_by_name;
@@ -77,17 +76,17 @@ typedef struct {
/**
* @brief Allocate a new PIT data structure (extended parameters)
- *
+ *
* @param init_size Initial size (0 = default)
* @param max_size Maximum size (0 = unbounded)
- *
+ *
* @return pit_t* Newly allocated PIT data structure
*/
pit_t * _pit_create(size_t init_size, size_t max_size);
/**
* @brief Allocate a new PIT data structure
- *
+ *
* @return pit_t* Newly allocated PIT data structure
*/
#define pit_create() _pit_create(0, 0)
@@ -108,14 +107,12 @@ do {
#define pit_at(pit, i) (pit->entries + i)
-pit_verdict_t pit_on_interest(pit_t * pit, off_t msgbuf_id);
+pit_verdict_t pit_on_interest(pit_t * pit, msgbuf_pool_t * msgbuf_pool, off_t msgbuf_id);
-nexthops_t * pit_on_data(pit_t * pit, off_t msgbuf_id);
+nexthops_t * pit_on_data(pit_t * pit, msgbuf_pool_t * msgbuf_pool, off_t msgbuf_id);
-void pit_remove(pit_t * pit, off_t msgbuf_id);
+void pit_remove(pit_t * pit, msgbuf_pool_t * msgbuf_pool, off_t msgbuf_id);
pit_entry_t * pit_lookup(const pit_t * pit, const msgbuf_t * msgbuf);
-#define pit_get_msgbuf_pool(pit) (pit->msgbuf_pool)
-
#endif /* HICNLIGHT_PIT_H */
diff --git a/hicn-light/src/hicn/core/prefix_stats.h b/hicn-light/src/hicn/core/prefix_stats.h
index 4d441203e..deedda793 100644
--- a/hicn-light/src/hicn/core/prefix_stats.h
+++ b/hicn-light/src/hicn/core/prefix_stats.h
@@ -4,7 +4,7 @@
#ifdef WITH_PREFIX_STATS
-#include <hicn/base/loop.h>
+#include "../base/loop.h"
typedef struct prefix_stats_mgr_s {
void * forwarder;
diff --git a/hicn-light/src/hicn/core/test/CMakeLists.txt b/hicn-light/src/hicn/core/test/CMakeLists.txt
new file mode 100644
index 000000000..1043ce580
--- /dev/null
+++ b/hicn-light/src/hicn/core/test/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+
+include(BuildMacros)
+
+list(APPEND TESTS
+ test-msgbuf_pool
+)
+
+foreach(test ${TESTS})
+ build_executable(${test}
+ NO_INSTALL
+ SOURCES ${test}.cc
+ LINK_LIBRARIES ${LIBHICN_LIGHT_SHARED} ${LIBHICNCTRL_SHARED} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
+ INCLUDE_DIRS ${HICN_LIGHT_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
+ DEPENDS gtest ${LIBHICNCTRL_SHARED} ${LIBHICN_LIGHT_SHARED}
+ COMPONENT ${HICN_LIGHT}
+ DEFINITIONS "${COMPILER_DEFINITIONS}"
+ )
+
+ if(${CMAKE_VERSION} VERSION_GREATER "3.10.0")
+ gtest_discover_tests(${test}-bin TEST_PREFIX new:)
+ else()
+ add_test(NAME ${test}-bin COMMAND ${test})
+ endif()
+endforeach()
diff --git a/hicn-light/src/hicn/core/test/test-msgbuf_pool.cc b/hicn-light/src/hicn/core/test/test-msgbuf_pool.cc
new file mode 100644
index 000000000..027f16ac9
--- /dev/null
+++ b/hicn-light/src/hicn/core/test/test-msgbuf_pool.cc
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <netinet/in.h>
+
+extern "C" {
+#define WITH_TESTS
+#include <hicn/core/msgbuf_pool.h>
+#include <hicn/base/pool.h> // TODO: remove this line
+}
+
+#define PACKET_POOL_DEFAULT_INIT_SIZE 1024
+
+class MsgbufPoolTest : public ::testing::Test {
+protected:
+ MsgbufPoolTest() {
+ msgbuf_pool = msgbuf_pool_create();
+ }
+ virtual ~MsgbufPoolTest() {
+ msgbuf_pool_free(msgbuf_pool);
+ }
+
+ msgbuf_pool_t *msgbuf_pool;
+};
+
+TEST_F(MsgbufPoolTest, Create)
+{
+ /* Check msgbuf_pool allocation */
+ EXPECT_NE(msgbuf_pool, nullptr);
+
+ /* Check msgbuf_pool size */
+ size_t msgbuf_pool_size = pool_hdr(msgbuf_pool->buffers)->alloc_size;
+ EXPECT_EQ(msgbuf_pool_size, (size_t) PACKET_POOL_DEFAULT_INIT_SIZE);
+}
+
+TEST_F(MsgbufPoolTest, GetMsgbuf)
+{
+ msgbuf_t *msgbuf = NULL;
+
+ /* Get valid msgbuf from msgbuf_pool */
+ off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf);
+ EXPECT_NE(msgbuf, nullptr);
+ EXPECT_NE(msgbuf_id_is_valid((unsigned long) msgbuf_id), 0);
+
+ /* Check if the returned id is correct */
+ off_t id = msgbuf_pool_get_id(msgbuf_pool, msgbuf);
+ EXPECT_EQ(id, msgbuf_id);
+
+ /* Check if the returned msgbuf is correct */
+ msgbuf_t *msgbuf_retrieved = msgbuf_pool_at(msgbuf_pool, id);
+ EXPECT_EQ(msgbuf_retrieved, msgbuf);
+}
+
+TEST_F(MsgbufPoolTest, PutMsgbuf)
+{
+ /* Check that asking a msgbuf right after releasing another one
+ returns the same msgbuf */
+
+ msgbuf_t *msgbuf = NULL;
+
+ off_t id1 = msgbuf_pool_get(msgbuf_pool, &msgbuf);
+ EXPECT_NE(msgbuf, nullptr);
+
+ msgbuf_pool_put(msgbuf_pool, msgbuf);
+
+ off_t id2 = msgbuf_pool_get(msgbuf_pool, &msgbuf);
+ EXPECT_NE(msgbuf, nullptr);
+
+ EXPECT_EQ(id2, id1);
+}
+
+TEST_F(MsgbufPoolTest, GetMultipleMsgbufs)
+{
+ const int NUM_MSG = 3;
+ msgbuf_t *msgbufs[NUM_MSG];
+
+ /* Check if successful allocation */
+ int ret = msgbuf_pool_getn(msgbuf_pool, msgbufs, NUM_MSG);
+ EXPECT_EQ(ret, 0);
+
+ /* Check if all msgbufs are valid */
+ for (unsigned i = 0; i < NUM_MSG; i++) {
+ msgbuf_pool_get_id(msgbuf_pool, msgbufs[i]);
+ EXPECT_NE(msgbufs[i], nullptr) << "Invalid index: " << i;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/hicn-light/src/hicn/utils/commands.h b/hicn-light/src/hicn/utils/commands.h
index 358f94d48..ede6177f4 100644
--- a/hicn-light/src/hicn/utils/commands.h
+++ b/hicn-light/src/hicn/utils/commands.h
@@ -31,11 +31,12 @@
#include <stdint.h>
#include <stdlib.h>
-#include <hicn/core/strategy.h> // to be moved in libhicn
-#include <hicn/util/ip_address.h>
#ifdef WITH_POLICY
#include <hicn/policy.h>
#endif /* WITH_POLICY */
+#include <hicn/util/ip_address.h>
+
+#include "../core/strategy.h" // to be moved in libhicn
#define SYMBOLIC_NAME_LEN 16
diff --git a/lib/includes/hicn/policy.h b/lib/includes/hicn/policy.h
index 1fe0dd766..5a9a44467 100644
--- a/lib/includes/hicn/policy.h
+++ b/lib/includes/hicn/policy.h
@@ -49,6 +49,8 @@ foreach_policy_tag
POLICY_TAG_N
} policy_tag_t;
+#define IS_VALID_POLICY_TAG(x) (x != POLICY_TAG_N)
+
#define MAXSZ_POLICY_TAG_ 11
#define MAXSZ_POLICY_TAG MAXSZ_POLICY_TAG_ + 1
@@ -134,6 +136,9 @@ foreach_policy_state
extern const char * policy_state_str[];
+#define policy_state_str(x) policy_state_str[x]
+
+policy_state_t policy_state_from_str(const char * str);
/* POLICY TAG STATE */
diff --git a/lib/includes/hicn/protocol/ipv6.h b/lib/includes/hicn/protocol/ipv6.h
index 5a83abcae..0b5525aba 100644
--- a/lib/includes/hicn/protocol/ipv6.h
+++ b/lib/includes/hicn/protocol/ipv6.h
@@ -23,21 +23,32 @@
*/
#define EXPECTED_IPV6_HDRLEN 40
+// typedef struct
+// {
+// union
+// {
+// struct
+// {
+// u32 version_class_flow; /* version, traffic class and 20 bits of flow-ID */
+// u16 len; /* payload length */
+// u8 nxt; /* next header */
+// u8 hlim; /* hop limit */
+// };
+// u8 vfc; /* 4 bits version, top 4 bits class */
+// };
+// ip6_address_t saddr; /* source address */
+// ip6_address_t daddr; /* destination address */
+// } _ipv6_header_t;
+
+// TODO: temporary fix
typedef struct
{
- union
- {
- struct
- {
- u32 version_class_flow; /* version, traffic class and 20 bits of flow-ID */
- u16 len; /* payload length */
- u8 nxt; /* next header */
- u8 hlim; /* hop limit */
- };
- u8 vfc; /* 4 bits version, top 4 bits class */
- };
- ip6_address_t saddr; /* source address */
- ip6_address_t daddr; /* destination address */
+ u32 version_class_flow; /* version, traffic class and 20 bits of flow-ID */
+ u16 len; /* payload length */
+ u8 nxt; /* next header */
+ u8 hlim; /* hop limit */
+ ip6_address_t saddr; /* source address */
+ ip6_address_t daddr; /* destination address */
} _ipv6_header_t;
#define IPV6_HDRLEN sizeof(_ipv6_header_t)
diff --git a/lib/src/policy.c b/lib/src/policy.c
index 694f0ea5e..8f317bc11 100644
--- a/lib/src/policy.c
+++ b/lib/src/policy.c
@@ -39,6 +39,18 @@ const char * policy_state_str[] = {
#undef _
};
+policy_state_t
+policy_state_from_str(const char * str)
+{
+#define _(x) \
+ if (strcasecmp(str, #x) == 0) \
+ return POLICY_STATE_ ## x; \
+ else
+ foreach_policy_state
+#undef _
+ return POLICY_STATE_N;
+}
+
int
policy_tag_state_snprintf(char * s, size_t size, const policy_tag_state_t * tag_state)
{
diff --git a/scripts/build-extras.sh b/scripts/build-extras.sh
index 4112298a8..78a6ac98e 100644
--- a/scripts/build-extras.sh
+++ b/scripts/build-extras.sh
@@ -15,143 +15,48 @@
set -euxo pipefail
SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE}")" ; pwd -P )
-APT_PATH=`which apt-get` || true
-apt_get=${APT_PATH:-"/usr/local/bin/apt-get"}
+source ${SCRIPT_PATH}/functions.sh
-PACKAGECLOUD_RELEASE_REPO_DEB="https://packagecloud.io/install/repositories/fdio/release/script.deb.sh"
-PACKAGECLOUD_RELEASE_REPO_RPM="https://packagecloud.io/install/repositories/fdio/release/script.rpm.sh"
+# Libparc and libmemif are still not available in Ubuntu 20, so
+# we remove it from the list for now.
+# TODO Remove it as soon as they are available.
+DEPS_UBUNTU=(${DEPS_UBUNTU[@]/"libmemif-dev"})
+DEPS_UBUNTU=(${DEPS_UBUNTU[@]/"libmemif"})
+DEPS_UBUNTU=(${DEPS_UBUNTU[@]/"libparc-dev"})
-VPP_GIT_REPO="https://git.fd.io/vpp"
-VPP_BRANCH="stable/2001"
+DEPS_CENTOS=(${DEPS_CENTOS[@]/"libmemif-devel"})
+DEPS_CENTOS=(${DEPS_CENTOS[@]/"libmemif"})
+DEPS_CENTOS=(${DEPS_CENTOS[@]/"libparc-devel"})
-VPP_VERSION_DEB="20.01-release"
-VPP_VERSION_RPM="20.01-release.x86_64"
-
-BUILD_TOOLS_UBUNTU="build-essential doxygen"
-LIBSSL_LIBEVENT_UBUNTU="libevent-dev libssl-dev"
-DEPS_UBUNTU="libvppinfra=${VPP_VERSION_DEB} \
- libvppinfra-dev=${VPP_VERSION_DEB} \
- vpp=${VPP_VERSION_DEB} \
- vpp-dev=${VPP_VERSION_DEB} \
- vpp-plugin-core=${VPP_VERSION_DEB}"
-
-# BUILD_TOOLS_GROUP_CENTOS="'Development Tools'"
-DEPS_CENTOS="vpp-devel-${VPP_VERSION_RPM} \
- vpp-lib-${VPP_VERSION_RPM} \
- centos-release-scl \
- devtoolset-7"
-
-LATEST_EPEL_REPO="http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm"
-
-install_cmake() {
- if ! grep -q "8.8.8.8" /etc/resolv.conf; then
- echo "nameserver 8.8.8.8" | sudo tee -a /etc/resolv.conf
- fi
-
- cat /etc/resolv.conf
-
- CMAKE_INSTALL_SCRIPT_URL="https://cmake.org/files/v3.8/cmake-3.8.0-Linux-x86_64.sh"
- CMAKE_INSTALL_SCRIPT="/tmp/install_cmake.sh"
- curl ${CMAKE_INSTALL_SCRIPT_URL} > ${CMAKE_INSTALL_SCRIPT}
-
- sudo mkdir -p /opt/cmake
- sudo bash ${CMAKE_INSTALL_SCRIPT} --skip-license --prefix=/opt/cmake
- export PATH=/opt/cmake/bin:${PATH}
-}
-
-# Parameters:
-# $1 = Distribution id
-# $2 = Distribution codename
-#
-setup_fdio_repo() {
- DISTRIB_ID=${1}
-
- if [ "${DISTRIB_ID}" == "ubuntu" ]; then
- curl -s ${PACKAGECLOUD_RELEASE_REPO_DEB} | sudo bash
- elif [ "${DISTRIB_ID}" == "centos" ]; then
- curl -s ${PACKAGECLOUD_RELEASE_REPO_RPM} | sudo bash
- curl ${LATEST_EPEL_REPO} > epel-release-latest-7.noarch.rpm
- rpm -ivh epel-release-latest-7.noarch.rpm || true
- rm epel-release-latest-7.noarch.rpm
- else
- echo "Distribution ${DISTRIB_ID} is not supported"
- exit -1
- fi
-}
-
-setup() {
- # Figure out what system we are running on
- if [ -f /etc/os-release ]; then
- . /etc/os-release
- else
- echo "ERROR: System configuration not recognized. Build failed"
- exit -1
- fi
-
- DISTRIB_ID=${ID}
-
- echo DISTRIBUTION: ${PRETTY_NAME}
- echo ARCHITECTURE: $(uname -m)
-
- ARCH=`uname -m`
- if [ "$ARCH" == "x86_64" ] || [ "$ARCH" == "x86" ]; then
- install_cmake
- fi
- setup_fdio_repo ${DISTRIB_ID}
-
- if [ "${DISTRIB_ID}" == "ubuntu" ]; then
- sudo ${apt_get} update || true
- fi
-
- # Install dependencies
- if [ ${DISTRIB_ID} == "ubuntu" ]; then
- echo ${BUILD_TOOLS_UBUNTU} ${DEPS_UBUNTU} | xargs sudo ${apt_get} install -y --allow-unauthenticated --no-install-recommends
- sudo ${apt_get} clean && sudo ${apt_get} update
- sudo ${apt_get} install -y --allow-unauthenticated --no-install-recommends libpcre3-dev
- elif [ ${DISTRIB_ID} == "centos" ]; then
- # echo ${BUILD_TOOLS_GROUP_CENTOS} | xargs sudo yum groupinstall -y --nogpgcheck
- echo ${DEPS_CENTOS} | xargs sudo yum install -y --nogpgcheck
- sudo yum install devtoolset-7 pcre-devel
-
- CXX_COMPILER="/opt/rh/devtoolset-7/root/usr/bin/c++"
- CC_COMPILER="/opt/rh/devtoolset-7/root/usr/bin/cc"
-
- ${CXX_COMPILER} --version
- ${CC_COMPILER} --version
-
- export CC=${CC_COMPILER} CXX=${CXX_COMPILER}
- fi
-}
# Parameters:
# $1 = Package name
#
-build_package() {
+function build_package() {
setup
- echo "*******************************************************************"
- echo "********************* STARTING PACKAGE BUILD **********************"
- echo "*******************************************************************"
+ echo "**************************************************************************"
+ echo "********************* STARTING PACKAGE EXTRAS BUILD **********************"
+ echo "**************************************************************************"
mkdir -p build && pushd build
-
- rm -rf *
- cmake -DCMAKE_INSTALL_PREFIX=/usr \
- -DBUILD_LIBHICN=OFF \
- -DBUILD_UTILS=OFF \
- -DBUILD_HICNPLUGIN=OFF \
- -DBUILD_HICNLIGHT=OFF \
- -DBUILD_LIBTRANSPORT=OFF \
- -DBUILD_APPS=OFF \
- -DBUILD_CTRL=OFF \
- -DBUILD_SYSREPOPLUGIN=OFF \
- -DBUILD_EXTRAS=ON \
- ${SCRIPT_PATH}/..
- make package
-
- find . -type d -iname '_CPack_Packages' -print0 | xargs -0 rm -rf -- || true
- find . -iname '*Unspecified*' -print0 | xargs -0 rm -rf -- || true
-
+ rm -rf *
+ cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/usr \
+ -DBUILD_LIBHICN=OFF \
+ -DBUILD_UTILS=OFF \
+ -DBUILD_HICNPLUGIN=OFF \
+ -DBUILD_HICNLIGHT=OFF \
+ -DBUILD_LIBTRANSPORT=OFF \
+ -DBUILD_APPS=OFF \
+ -DBUILD_CTRL=OFF \
+ -DBUILD_SYSREPOPLUGIN=OFF \
+ -DBUILD_EXTRAS=ON \
+ ${SCRIPT_PATH}/..
+ ninja
+
+ find . -type f '(' -name '*.deb' -o -name '*.rpm' ')' -exec mv {} . \;
+ find . -not -name '*.deb' -not -name '*.rpm' -print0 | xargs -0 rm -rf -- || true
+ rm *Unspecified* || true
popd
echo "*******************************************************************"
diff --git a/scripts/build-packages.sh b/scripts/build-packages.sh
index 77c1b94ab..efc1b6717 100644
--- a/scripts/build-packages.sh
+++ b/scripts/build-packages.sh
@@ -15,193 +15,12 @@
set -euxo pipefail
SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE}")" ; pwd -P )
-APT_PATH=`which apt-get` || true
-apt_get=${APT_PATH:-"/usr/local/bin/apt-get"}
-
-PACKAGECLOUD_RELEASE_REPO_DEB="https://packagecloud.io/install/repositories/fdio/release/script.deb.sh"
-PACKAGECLOUD_RELEASE_REPO_RPM="https://packagecloud.io/install/repositories/fdio/release/script.rpm.sh"
-
-VPP_GIT_REPO="https://git.fd.io/vpp"
-VPP_BRANCH="stable/2001"
-
-VPP_VERSION_DEB="20.01-release"
-VPP_VERSION_RPM="20.01-release.x86_64"
-
-BUILD_TOOLS_UBUNTU="build-essential doxygen"
-LIBSSL_LIBEVENT_UBUNTU="libevent-dev libssl-dev"
-DEPS_UBUNTU="libparc-dev \
- libmemif-dev \
- libmemif \
- libasio-dev \
- libconfig-dev \
- libcurl4-openssl-dev \
- vpp=${VPP_VERSION_DEB} \
- vpp-dev=${VPP_VERSION_DEB} \
- libvppinfra=${VPP_VERSION_DEB} \
- libvppinfra-dev=${VPP_VERSION_DEB} \
- vpp-plugin-core=${VPP_VERSION_DEB} \
- python3-ply"
-
-
-DEPS_UBUNTU_NOVERSION="libparc-dev \
- libmemif-dev \
- libmemif \
- libasio-dev \
- libconfig-dev \
- libcurl4-openssl-dev \
- vpp \
- vpp-dev \
- libvppinfra \
- libvppinfra-dev \
- vpp-plugin-core \
- python3-ply \
- python3-setuptools \
- python3-pip"
-
-DEPS_CMAKE_UBUNTU="curl"
-
-# BUILD_TOOLS_GROUP_CENTOS="'Development Tools'"
-DEPS_CENTOS="vpp-devel-${VPP_VERSION_RPM} \
- vpp-lib-${VPP_VERSION_RPM} \
- libparc-devel \
- libmemif-devel \
- libmemif \
- libcurl-devel \
- asio-devel \
- libconfig-devel \
- centos-release-scl \
- libyang \
- sysrepo \
- devtoolset-7"
-
-DEPS_CENTOS_NOVERSION="vpp-devel \
- vpp-lib \
- libparc-devel \
- libcurl-devel \
- asio-devel \
- libmemif-devel \
- libmemif \
- centos-release-scl \
- devtoolset-7"
-
-LATEST_EPEL_REPO="http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm"
-
-install_cmake() {
- if [ "${DISTRIB_ID}" == "ubuntu" ]; then
- sudo apt update
- echo ${DEPS_CMAKE_UBUNTU} | xargs sudo ${apt_get} install -y --allow-unauthenticated --no-install-recommends
- fi
-
- if ! grep -q "8.8.8.8" /etc/resolv.conf; then
- echo "nameserver 8.8.8.8" | sudo tee -a /etc/resolv.conf
- fi
-
- cat /etc/resolv.conf
-
- CMAKE_INSTALL_SCRIPT_URL="https://cmake.org/files/v3.8/cmake-3.8.0-Linux-x86_64.sh"
- CMAKE_INSTALL_SCRIPT="/tmp/install_cmake.sh"
- curl ${CMAKE_INSTALL_SCRIPT_URL} > ${CMAKE_INSTALL_SCRIPT}
-
- sudo mkdir -p /opt/cmake
- sudo bash ${CMAKE_INSTALL_SCRIPT} --skip-license --prefix=/opt/cmake
- export PATH=/opt/cmake/bin:${PATH}
-}
-
-# Parameters:
-# $1 = Distribution id
-# $2 = Distribution codename
-#
-setup_fdio_repo() {
- DISTRIB_ID=${1}
-
- if [ "${DISTRIB_ID}" == "ubuntu" ]; then
- rm -r /etc/apt/sources.list.d/*
- curl -s ${PACKAGECLOUD_RELEASE_REPO_DEB} | sudo bash
- elif [ "${DISTRIB_ID}" == "centos" ]; then
- curl -s ${PACKAGECLOUD_RELEASE_REPO_RPM} | sudo bash
- curl ${LATEST_EPEL_REPO} > epel-release-latest-7.noarch.rpm
- rpm -ivh epel-release-latest-7.noarch.rpm || true
- rm epel-release-latest-7.noarch.rpm
- else
- echo "Distribution ${DISTRIB_ID} is not supported"
- exit -1
- fi
-}
-
-setup() {
- # Figure out what system we are running on
- if [ -f /etc/os-release ]; then
- . /etc/os-release
- else
- echo "ERROR: System configuration not recognized. Build failed"
- exit -1
- fi
-
- DISTRIB_ID=${ID}
-
- echo DISTRIBUTION: ${PRETTY_NAME}
- echo ARCHITECTURE: $(uname -m)
-
- ARCH=`uname -m`
- if [ "$ARCH" == "x86_64" ] || [ "$ARCH" == "x86" ]; then
- install_cmake
- fi
- setup_fdio_repo ${DISTRIB_ID}
-
- if [ "${DISTRIB_ID}" == "ubuntu" ]; then
- sudo ${apt_get} update || true
- fi
-
- # Install dependencies
- if [ ${DISTRIB_ID} == "ubuntu" ]; then
- echo ${BUILD_TOOLS_UBUNTU} ${DEPS_UBUNTU_NOVERSION} | xargs sudo ${apt_get} install -y --allow-unauthenticated --no-install-recommends
- elif [ ${DISTRIB_ID} == "centos" ]; then
- # echo ${BUILD_TOOLS_GROUP_CENTOS} | xargs sudo yum groupinstall -y --nogpgcheck
- echo ${DEPS_CENTOS} | xargs sudo yum install -y --nogpgcheck
- sudo yum install devtoolset-7
-
- c++ --version
-
- CXX_COMPILER="/opt/rh/devtoolset-7/root/usr/bin/c++"
- CC_COMPILER="/opt/rh/devtoolset-7/root/usr/bin/cc"
-
- ${CXX_COMPILER} --version
- ${CC_COMPILER} --version
-
- export CC=${CC_COMPILER} CXX=${CXX_COMPILER}
- fi
-
- # do nothing but check compiler version
- c++ --version
-}
-
-
-install_collectd_headers() {
- if [ -f /etc/os-release ]; then
- . /etc/os-release
- else
- echo "ERROR: System configuration not recognized. Build failed"
- exit -1
- fi
-
- if [ "${DISTRIB_ID}" == "ubuntu" ]; then
- sudo apt-get install collectd-dev -y --allow-unauthenticated
-
- if [ "${VERSION_CODENAME}" == "xenial" ]; then
- awk '/config.h/ { print; print "#include \"collectd/liboconfig/oconfig.h\""; next }1' /usr/include/collectd/core/daemon/configfile.h | sudo tee /usr/include/collectd/core/daemon/configfile.h
- fi
- elif [ "${DISTRIB_ID}" == "centos" ]; then
- wget https://storage.googleapis.com/collectd-tarballs/collectd-5.9.2.tar.bz2
- tar -xf collectd-5.9.2.tar.bz2
- cd collectd-5.9.2 && ./configure && make && cd -
- export COLLECTD_HOME=${PWD}/collectd-5.9.2/src
- fi
-}
+source ${SCRIPT_PATH}/functions.sh
# Parameters:
# $1 = Package name
#
-build_package() {
+function build_package() {
setup
echo "*******************************************************************"
@@ -210,29 +29,12 @@ build_package() {
# Make the package
mkdir -p ${SCRIPT_PATH}/../build && pushd ${SCRIPT_PATH}/../build
-
- rm -rf *
- cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_APPS=ON ..
- make VERBOSE=1 -j8 package
-
- rm -rf libtransport ctrl/libhicnctrl
-
- install_collectd_headers
-
- cmake -DCMAKE_INSTALL_PREFIX=/usr \
- -DBUILD_HICNPLUGIN=ON \
- -DBUILD_LIBTRANSPORT=ON \
- -DBUILD_APPS=ON \
- -DBUILD_HICNLIGHT=OFF \
- -DBUILD_SYSREPOPLUGIN=ON \
- -DBUILD_TELEMETRY=ON \
- ${SCRIPT_PATH}/..
-
- make VERBOSE=1 -j8 package
-
- find . -not -name '*.deb' -not -name '*.rpm' -print0 | xargs -0 rm -rf -- || true
- rm *Unspecified* || true
-
+ rm -rf *
+ # First round
+ cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_APPS=ON ..
+ ninja -j8 package
+ find . -not -name '*.deb' -not -name '*.rpm' -print0 | xargs -0 rm -rf -- || true
+ rm *Unspecified* || true
popd
echo "*******************************************************************"
@@ -264,13 +66,13 @@ build_doxygen() {
mkdir -p ${SCRIPT_PATH}/../build-doxygen
pushd ${SCRIPT_PATH}/../build-doxygen
- cmake -DBUILD_HICNPLUGIN=OFF -DBUILD_HICNLIGHT=OFF -DBUILD_LIBTRANSPORT=OFF -DBUILD_UTILS=OFF -DBUILD_APPS=OFF -DBUILD_CTRL=OFF ..
+ cmake -DBUILD_HICNPLUGIN=On -DBUILD_HICNLIGHT=OFF -DBUILD_LIBTRANSPORT=OFF -DBUILD_UTILS=OFF -DBUILD_APPS=OFF -DBUILD_CTRL=OFF ..
make doc
popd
}
function usage() {
- echo "Usage: ${0} [doc|sphinx|doxygen]"
+ echo "Usage: ${0} [sphinx|doxygen|packages]"
exit 1
}
diff --git a/scripts/functions.sh b/scripts/functions.sh
new file mode 100644
index 000000000..7796935ef
--- /dev/null
+++ b/scripts/functions.sh
@@ -0,0 +1,144 @@
+# Copyright (c) 2020 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/bash
+set -euxo pipefail
+
+APT_PATH=`which apt-get` || true
+apt_get=${APT_PATH:-"/usr/local/bin/apt-get"}
+
+# Cmake executable
+CMAKE_INSTALL_DIR="/opt/cmake"
+export PATH=:${CMAKE_INSTALL_DIR}/bin:${PATH}
+
+PACKAGECLOUD_RELEASE_REPO_DEB="https://packagecloud.io/install/repositories/fdio/release/script.deb.sh"
+PACKAGECLOUD_RELEASE_REPO_RPM="https://packagecloud.io/install/repositories/fdio/release/script.rpm.sh"
+PACKAGECLOUD_HICN_REPO_DEB="https://packagecloud.io/install/repositories/fdio/hicn/script.deb.sh"
+PACKAGECLOUD_HICN_REPO_RPM="https://packagecloud.io/install/repositories/fdio/hicn/script.rpm.sh"
+
+VPP_GIT_REPO="https://github.com/FDio/vpp"
+VPP_BRANCH="stable/2005"
+
+ # Figure out what system we are running on
+if [ -f /etc/os-release ]; then
+ . /etc/os-release
+else
+ echo "ERROR: System configuration not recognized. Build failed"
+ exit 1
+fi
+
+VERSION_REGEX="s/v([0-9]+).([0-9]+)(.*)?-([0-9]+)-(g[0-9a-f]+)/\1.\2-release/g"
+VPP_VERSION_DEB=$(git describe --long --match "v*" | sed -E ${VERSION_REGEX})
+VPP_VERSION_RPM="${VPP_VERSION_DEB}.x86_64"
+
+DEPS_UBUNTU=("build-essential"
+ "doxygen"
+ "curl"
+ "libparc-dev"
+ "libmemif-dev"
+ "libmemif"
+ "libasio-dev"
+ "libconfig-dev"
+ "libcurl4-openssl-dev"
+ "libevent-dev"
+ "libssl-dev"
+ "ninja-build"
+ "python3-ply")
+
+# BUILD_TOOLS_GROUP_CENTOS="'Development Tools'"
+DEPS_CENTOS=("libparc-devel"
+ "curl"
+ "libmemif-devel"
+ "ninja-build"
+ "libmemif"
+ "libcurl-devel"
+ "asio-devel"
+ "libconfig-devel"
+ "dnf-plugins-core"
+ "bzip2"
+ "rpm-build")
+
+COLLECTD_SOURCE="https://github.com/collectd/collectd/releases/download/collectd-5.12.0/collectd-5.12.0.tar.bz2"
+
+function install_collectd_headers() {
+ curl -OL ${COLLECTD_SOURCE}
+ tar -xf collectd-5.12.0.tar.bz2
+
+ pushd collectd-5.12.0
+ ./configure && make -j$(nproc)
+ popd
+
+ export COLLECTD_HOME=${PWD}/collectd-5.12.0/src
+}
+
+function install_cmake() {
+ [[ $(uname --hardware-platform) = "x86_64" ]] || return 0
+ CMAKE_INSTALL_SCRIPT_URL="https://github.com/Kitware/CMake/releases/download/v3.18.4/cmake-3.18.4-Linux-x86_64.sh"
+ CMAKE_INSTALL_SCRIPT="/tmp/install_cmake.sh"
+ curl -L ${CMAKE_INSTALL_SCRIPT_URL} > ${CMAKE_INSTALL_SCRIPT}
+
+ sudo mkdir -p ${CMAKE_INSTALL_DIR}
+ sudo bash ${CMAKE_INSTALL_SCRIPT} --skip-license --prefix=${CMAKE_INSTALL_DIR}
+}
+
+function setup_fdio_repo() {
+ DISTRIB_ID=${ID}
+
+ if [ "${DISTRIB_ID}" == "ubuntu" ]; then
+ curl -s ${PACKAGECLOUD_RELEASE_REPO_DEB} | sudo bash
+ curl -s ${PACKAGECLOUD_HICN_REPO_DEB} | sudo bash
+ elif [ "${DISTRIB_ID}" == "centos" ]; then
+ curl -s ${PACKAGECLOUD_RELEASE_REPO_RPM} | sudo bash
+ curl -s ${PACKAGECLOUD_HICN_REPO_RPM} | sudo bash
+ else
+ echo "Distribution ${DISTRIB_ID} is not supported"
+ exit 1
+ fi
+}
+
+# Install dependencies
+function install_deps() {
+ DISTRIB_ID=${ID}
+
+ if [ ${DISTRIB_ID} == "ubuntu" ]; then
+ echo ${DEPS_UBUNTU[@]} | xargs sudo ${apt_get} install -y --allow-unauthenticated --no-install-recommends
+ elif [ ${DISTRIB_ID} == "centos" ]; then
+ yum config-manager --set-enabled powertools
+ # Temporary workaround until centos fixes the asio-devel package (https://forums.centos.org/viewtopic.php?t=73034)
+ curl -L http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/asio-devel-1.10.8-7.module_el8.1.0+217+4d875839.x86_64.rpm > /tmp/asio-devel-1.10.8-7.module_el8.1.0+217+4d875839.x86_64.rpm
+ yum localinstall -y --nogpgcheck /tmp/asio-devel-1.10.8-7.module_el8.1.0+217+4d875839.x86_64.rpm
+ echo ${DEPS_CENTOS[@]} | xargs sudo yum install -y --nogpgcheck
+ fi
+}
+
+# Call a function once
+function call_once() {
+ # OP_NAME is the name of the function
+ OP_NAME=${1}
+ # If function was already called return
+ [[ -f /tmp/${OP_NAME} ]] && return 0
+ # Otherwise call the function
+ ${@}
+ # And mark the function as called if no error occurred
+ echo ${OP_NAME} > /tmp/${OP_NAME}
+}
+
+function setup() {
+ echo DISTRIBUTION: ${PRETTY_NAME}
+ # export variables depending on the platform we are running
+
+ call_once setup_fdio_repo
+ call_once install_deps
+ call_once install_cmake
+ call_once install_collectd_headers
+}