aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichele Papalini <micpapal@cisco.com>2019-11-12 13:19:55 +0000
committerGerrit Code Review <gerrit@fd.io>2019-11-12 13:19:55 +0000
commit4f57ca72e8131e5cfb023b26417b924e774d5e73 (patch)
treea4ece77466921823c69dbfed4933d4659437f8b8
parent48fe930311724be0c0bc3bcc498d911a05e01134 (diff)
parent955e71001bd6d360805d2b33a9e6b9d6fd17397f (diff)
Merge "[HICN-376] Add manual connection/route setting to face manager"
-rw-r--r--ctrl/facemgr/CMakeLists.txt5
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/cfg.h62
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/facelet.h67
-rw-r--r--ctrl/facemgr/src/CMakeLists.txt4
-rw-r--r--ctrl/facemgr/src/api.c271
-rw-r--r--ctrl/facemgr/src/cfg.c75
-rw-r--r--ctrl/facemgr/src/cfg_file.c182
-rw-r--r--ctrl/facemgr/src/facelet.c191
-rw-r--r--ctrl/facemgr/src/facelet_array.c26
-rw-r--r--ctrl/facemgr/src/facelet_array.h29
-rw-r--r--ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c121
-rw-r--r--ctrl/facemgr/src/interfaces/netlink/netlink.c13
-rw-r--r--ctrl/facemgr/src/util/array.h199
-rw-r--r--ctrl/libhicnctrl/includes/CMakeLists.txt3
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h2
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/route.h46
-rw-r--r--ctrl/libhicnctrl/src/CMakeLists.txt1
-rw-r--r--ctrl/libhicnctrl/src/api.c96
-rw-r--r--ctrl/libhicnctrl/src/route.c98
-rw-r--r--lib/includes/hicn/util/ip_address.h2
-rw-r--r--lib/src/util/ip_address.c29
21 files changed, 1317 insertions, 205 deletions
diff --git a/ctrl/facemgr/CMakeLists.txt b/ctrl/facemgr/CMakeLists.txt
index 377773c2d..a560be36a 100644
--- a/ctrl/facemgr/CMakeLists.txt
+++ b/ctrl/facemgr/CMakeLists.txt
@@ -41,6 +41,11 @@ if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
+if(CMAKE_BUILD_TYPE MATCHES Debug)
+message("IN DEBUG MODE")
+set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3")
+endif()
+
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules"
diff --git a/ctrl/facemgr/includes/hicn/facemgr/cfg.h b/ctrl/facemgr/includes/hicn/facemgr/cfg.h
index 525e1a9e3..9d227f30a 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/cfg.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/cfg.h
@@ -21,64 +21,9 @@
#define FACEMGR_CFG_H
#include <hicn/ctrl/face.h>
+#include <hicn/facemgr/facelet.h>
#include <hicn/util/log.h>
-/* Face type */
-
-#define foreach_face_type_layer \
- _(UNDEFINED) \
- _(3) \
- _(4) \
- _(N)
-
-typedef enum {
-#define _(x) FACE_TYPE_LAYER_ ## x,
- foreach_face_type_layer
-#undef _
-} face_type_layer_t;
-
-#define foreach_face_type_encap \
- _(UNDEFINED) \
- _(TCP) \
- _(UDP) \
- _(N)
-
-typedef enum {
-#define _(x) FACE_TYPE_ENCAP_ ## x,
- foreach_face_type_encap
-#undef _
-} face_type_encap_t;
-
-typedef struct {
- face_type_layer_t layer;
- face_type_encap_t encap;
-} facemgr_face_type_t;
-
-#define FACEMGR_FACE_TYPE_UNDEFINED (facemgr_face_type_t) { \
- .layer = FACE_TYPE_LAYER_UNDEFINED, \
- .encap = FACE_TYPE_ENCAP_UNDEFINED, \
-}
-
-#define FACEMGR_FACE_TYPE_NATIVE_UDP (facemgr_face_type_t) { \
- .layer = FACE_TYPE_LAYER_3, \
- .encap = FACE_TYPE_ENCAP_UDP, \
-}
-
-#define FACEMGR_FACE_TYPE_NATIVE_TCP (facemgr_face_type_t) { \
- .layer = FACE_TYPE_LAYER_3, \
- .encap = FACE_TYPE_ENCAP_TCP, \
-}
-
-#define FACEMGR_FACE_TYPE_OVERLAY_UDP (facemgr_face_type_t) { \
- .layer = FACE_TYPE_LAYER_4, \
- .encap = FACE_TYPE_ENCAP_UDP, \
-}
-
-#define FACEMGR_FACE_TYPE_OVERLAY_TCP (facemgr_face_type_t) { \
- .layer = FACE_TYPE_LAYER_4, \
- .encap = FACE_TYPE_ENCAP_TCP, \
-}
-
/* Face manager configuration */
#ifdef __ANDROID__
@@ -194,4 +139,9 @@ int facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t * cfg,
const netdevice_t * netdevice, netdevice_type_t netdevice_type,
int family, u16 * port);
+int facemgr_cfg_add_static_facelet(facemgr_cfg_t * cfg, facelet_t * facelet);
+int facemgr_cfg_remove_static_facelet(facemgr_cfg_t * cfg, facelet_t * facelet,
+ facelet_t ** removed_facelet);
+int facemgr_cfg_get_static_facelet_array(const facemgr_cfg_t * cfg, facelet_t *** array);
+
#endif /* FACEMGR_CFG_H */
diff --git a/ctrl/facemgr/includes/hicn/facemgr/facelet.h b/ctrl/facemgr/includes/hicn/facemgr/facelet.h
index 7fc2745f1..476858eff 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/facelet.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/facelet.h
@@ -29,7 +29,7 @@
#include <stdbool.h>
#include <hicn/ctrl/face.h>
-#include <hicn/facemgr/cfg.h>
+#include <hicn/ctrl/route.h>
#define MAXSZ_FACELET 1024
@@ -38,6 +38,63 @@
typedef struct facelet_s facelet_t;
+/* Face type */
+
+#define foreach_face_type_layer \
+ _(UNDEFINED) \
+ _(3) \
+ _(4) \
+ _(N)
+
+typedef enum {
+#define _(x) FACE_TYPE_LAYER_ ## x,
+ foreach_face_type_layer
+#undef _
+} face_type_layer_t;
+
+#define foreach_face_type_encap \
+ _(UNDEFINED) \
+ _(TCP) \
+ _(UDP) \
+ _(N)
+
+typedef enum {
+#define _(x) FACE_TYPE_ENCAP_ ## x,
+ foreach_face_type_encap
+#undef _
+} face_type_encap_t;
+
+typedef struct {
+ face_type_layer_t layer;
+ face_type_encap_t encap;
+} facemgr_face_type_t;
+
+#define FACEMGR_FACE_TYPE_UNDEFINED (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_UNDEFINED, \
+ .encap = FACE_TYPE_ENCAP_UNDEFINED, \
+}
+
+#define FACEMGR_FACE_TYPE_NATIVE_UDP (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_3, \
+ .encap = FACE_TYPE_ENCAP_UDP, \
+}
+
+#define FACEMGR_FACE_TYPE_NATIVE_TCP (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_3, \
+ .encap = FACE_TYPE_ENCAP_TCP, \
+}
+
+#define FACEMGR_FACE_TYPE_OVERLAY_UDP (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_4, \
+ .encap = FACE_TYPE_ENCAP_UDP, \
+}
+
+#define FACEMGR_FACE_TYPE_OVERLAY_TCP (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_4, \
+ .encap = FACE_TYPE_ENCAP_TCP, \
+}
+
+
/* Facelet status */
#define foreach_facelet_status \
_(UNDEFINED) \
@@ -133,6 +190,8 @@ facelet_t * facelet_create();
facelet_t * facelet_create_from_netdevice(netdevice_t * netdevice);
+void facelet_set_id(facelet_t * facelet, unsigned id);
+
int facelet_validate_face(const facelet_t * facelet);
facelet_t * facelet_create_from_face(face_t * face);
@@ -143,6 +202,8 @@ facelet_t * facelet_dup(const facelet_t * current_facelet);
int facelet_cmp(const facelet_t * f1, const facelet_t * f2);
+bool facelet_equals(const facelet_t * facelet1, const facelet_t * facelet2);
+
/* NOTE: only clean attributes are matched */
bool facelet_match(const facelet_t * facelet, const facelet_t * facelet_match);
@@ -185,6 +246,10 @@ bool facelet_is_au_done(const facelet_t * facelet);
facelet_event_t facelet_get_event(const facelet_t * facelet);
void facelet_set_event(facelet_t * facelet, facelet_event_t event);
+int facelet_add_route(facelet_t * facelet, hicn_route_t * route);
+int facelet_remove_route(facelet_t * facelet, hicn_route_t * route, hicn_route_t ** route_removed);
+int facelet_get_route_array(const facelet_t * facelet, hicn_route_t *** route_array);
+
int facelet_snprintf(char * buf, size_t size, const facelet_t * facelet);
#define DUMP_FACELET(msg, facelet) do { \
diff --git a/ctrl/facemgr/src/CMakeLists.txt b/ctrl/facemgr/src/CMakeLists.txt
index 47390cb60..7069d1fdc 100644
--- a/ctrl/facemgr/src/CMakeLists.txt
+++ b/ctrl/facemgr/src/CMakeLists.txt
@@ -22,9 +22,11 @@ set(COMPILER_DEFINITIONS
set(HEADER_FILES
common.h
error.h
+ facelet_array.h
interface.h
loop.h
util/hash.h
+ util/array.h
util/map.h
util/set.h
)
@@ -35,6 +37,7 @@ set(SOURCE_FILES
cfg_file.c
error.c
facelet.c
+ facelet_array.c
interface.c
util/log.c
)
@@ -63,6 +66,7 @@ set(INCLUDE_DIRS
)
set(LIBRARIES
+ m
${HICN_LIBRARIES}
${LIBHICNCTRL_LIBRARIES}
${CONFIG_LIBRARY}
diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c
index 5cd6f1a33..373e55422 100644
--- a/ctrl/facemgr/src/api.c
+++ b/ctrl/facemgr/src/api.c
@@ -28,6 +28,7 @@
#include <hicn/facemgr/api.h>
#include <hicn/facemgr/cfg.h>
+#include <hicn/facemgr/facelet.h>
#include <hicn/util/log.h>
#ifdef __APPLE__
@@ -45,6 +46,7 @@
#include <hicn/ctrl/face.h>
#include <hicn/facemgr/facelet.h>
#include "common.h"
+#include "facelet_array.h"
#include "interface.h"
#include "util/map.h"
#include "util/set.h"
@@ -62,8 +64,8 @@ typedef struct {
size_t num_fds;
} interface_map_data_t;
-TYPEDEF_SET_H(facelet_cache, facelet_t *);
-TYPEDEF_SET(facelet_cache, facelet_t *, facelet_cmp, facelet_snprintf);
+TYPEDEF_SET_H(facelet_set, facelet_t *);
+TYPEDEF_SET(facelet_set, facelet_t *, facelet_cmp, facelet_snprintf);
TYPEDEF_MAP_H(interface_map, const char *, interface_map_data_t *);
TYPEDEF_MAP(interface_map, const char *, interface_map_data_t *, strcmp, string_snprintf, generic_snprintf);
@@ -120,10 +122,13 @@ struct facemgr_s {
/* Internal data structures */
/* Map of interfaces index by name */
- interface_map_t interface_map;
+ interface_map_t * interface_map;
/* Faces under construction */
- facelet_cache_t facelet_cache;
+ facelet_set_t * facelet_cache;
+
+ /* Static facelets */
+ facelet_array_t * static_facelets;
/********************************************************/
/* Interfaces - Those should be fully replaced by a map */
@@ -145,7 +150,7 @@ struct facemgr_s {
* We maintain a map of dynamically created bonjour interfaces, one for each
* found netdevice
*/
- bonjour_map_t bonjour_map;
+ bonjour_map_t * bonjour_map;
#endif /* __linux__ */
#ifdef WITH_EXAMPLE_DUMMY
@@ -160,25 +165,37 @@ struct facemgr_s {
int
facemgr_initialize(facemgr_t * facemgr)
{
- int rc;
-
- rc = interface_map_initialize(&facemgr->interface_map);
- if (rc < 0)
+ facemgr->interface_map = interface_map_create();
+ if (!facemgr->interface_map) {
+ ERROR("[facemgr_initialize] Error creating interface map");
goto ERR_INTERFACE_MAP;
+ }
- rc = facelet_cache_initialize(&facemgr->facelet_cache);
- if (rc < 0)
+ facemgr->facelet_cache = facelet_set_create();
+ if (!facemgr->facelet_cache) {
+ ERROR("[facemgr_initialize] Error creating interface map");
goto ERR_FACE_CACHE_PENDING;
+ }
+
+ facemgr->static_facelets = facelet_array_create();
+ if (!facemgr->static_facelets) {
+ ERROR("[facemgr_initialize] Error creating interface map");
+ goto ERR_STATIC;
+ }
#ifdef __linux__
- rc = bonjour_map_initialize(&facemgr->bonjour_map);
- if (rc < 0)
+ facemgr->bonjour_map = bonjour_map_create();
+ if (!facemgr->bonjour_map) {
+ ERROR("[facemgr_initialize] Error creating bonjour map");
goto ERR_BJ;
+ }
#endif /* __linux */
facemgr->cfg = facemgr_cfg_create();
- if (!facemgr->cfg)
+ if (!facemgr->cfg) {
+ ERROR("[facemgr_initialize] Error creating face manager configuration");
goto ERR_CFG;
+ }
facemgr->timer_fd = 0;
@@ -186,12 +203,14 @@ facemgr_initialize(facemgr_t * facemgr)
ERR_CFG:
#ifdef __linux__
- bonjour_map_finalize(&facemgr->bonjour_map);
+ bonjour_map_free(facemgr->bonjour_map);
ERR_BJ:
#endif /* __linux__ */
- facelet_cache_finalize(&facemgr->facelet_cache);
+ facelet_array_free(facemgr->static_facelets);
+ERR_STATIC:
+ facelet_set_free(facemgr->facelet_cache);
ERR_FACE_CACHE_PENDING:
- interface_map_finalize(&facemgr->interface_map);
+ interface_map_free(facemgr->interface_map);
ERR_INTERFACE_MAP:
return -1;
}
@@ -212,21 +231,17 @@ facemgr_finalize(facemgr_t * facemgr)
facemgr->timer_fd = 0;
}
- rc = interface_map_finalize(&facemgr->interface_map);
- if (rc < 0) {
- ERROR("[facemgr_finalize] Could not finalize interface_map");
- ret = -1;
- }
+ interface_map_free(facemgr->interface_map);
/* Free all facelets from cache */
facelet_t ** facelet_array;
- int n = facelet_cache_get_array(&facemgr->facelet_cache, &facelet_array);
+ int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
if (n < 0) {
ERROR("[facemgr_finalize] Could not retrieve facelets in cache");
} else {
for (unsigned i = 0; i < n; i++) {
facelet_t * facelet = facelet_array[i];
- if (facelet_cache_remove(&facemgr->facelet_cache, facelet, NULL)) {
+ if (facelet_set_remove(facemgr->facelet_cache, facelet, NULL)) {
ERROR("[facemgr_finalize] Could not purge facelet from cache");
}
facelet_free(facelet);
@@ -234,14 +249,25 @@ facemgr_finalize(facemgr_t * facemgr)
free(facelet_array);
}
- rc = facelet_cache_finalize(&facemgr->facelet_cache);
- if (rc < 0)
- ret = -1;
+ facelet_set_free(facemgr->facelet_cache);
+
+ /* Free all facelets from static array */
+ for (unsigned i = 0; i < facelet_array_len(facemgr->static_facelets); i++) {
+ facelet_t * facelet;
+ if (facelet_array_get_index(facemgr->static_facelets, i, &facelet) < 0) {
+ ERROR("[facemgr_cfg_finalize] Error getting facelet in array");
+ continue;
+ }
+ if (facelet_array_remove_index(facemgr->static_facelets, i, NULL) < 0) {
+ ERROR("[facemgr_finalize] Could not purge facelet from static array");
+ }
+ facelet_free(facelet);
+ }
+
+ facelet_array_free(facemgr->static_facelets);
#ifdef __linux__
- rc = bonjour_map_finalize(&facemgr->bonjour_map);
- if (rc < 0)
- ret = -1;
+ bonjour_map_free(facemgr->bonjour_map);
#endif /* __linux__ */
interface_unregister_all();
@@ -258,6 +284,22 @@ facemgr_set_config(facemgr_t * facemgr, facemgr_cfg_t * cfg)
facemgr_cfg_free(facemgr->cfg);
}
facemgr->cfg = cfg;
+
+ /* Populate the initial list of static facelets */
+ facelet_t ** facelet_array;
+ int n = facemgr_cfg_get_static_facelet_array(cfg, &facelet_array);
+ if (n < 0) {
+ ERROR("[facemgr_finalize] Could not retrieve static facelets from cfg");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ facelet_t * facelet = facelet_dup(facelet_array[i]);
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ if (facelet_array_add(facemgr->static_facelets, facelet)) {
+ ERROR("[facemgr_finalize] Could not add static facelet to face manager");
+ }
+ }
+ }
+
return 0;
}
@@ -358,7 +400,7 @@ facemgr_create_interface(facemgr_t * facemgr, const char * name, const char * ty
.num_fds = 0,
};
- if (interface_map_add(&facemgr->interface_map, interface->name, interface_map_data) < 0)
+ if (interface_map_add(facemgr->interface_map, interface->name, interface_map_data) < 0)
goto ERR_MAP_ADD;
/*
@@ -395,7 +437,7 @@ facemgr_delete_interface(facemgr_t * facemgr, interface_t * interface)
interface_map_data_t * interface_map_data = NULL;
DEBUG("Removing interface %s", interface->name);
- rc = interface_map_remove(&facemgr->interface_map, interface->name, &interface_map_data);
+ rc = interface_map_remove(facemgr->interface_map, interface->name, &interface_map_data);
if (rc < 0)
return -1;
@@ -428,7 +470,7 @@ int facemgr_query_bonjour(facemgr_t * facemgr, netdevice_t * netdevice)
{
interface_t * bj = NULL;
- int rc = bonjour_map_get(&facemgr->bonjour_map, netdevice, &bj);
+ int rc = bonjour_map_get(facemgr->bonjour_map, netdevice, &bj);
if (rc < 0)
return rc;
@@ -488,16 +530,17 @@ ERR_MALLOC:
* value), or -1 in case of error.
*/
int
-facelet_cache_lookup(const facelet_cache_t * facelet_cache, facelet_t * facelet,
+facelet_cache_lookup(const facelet_set_t * facelet_cache, facelet_t * facelet,
facelet_t ***cached_facelets)
{
+#if 0 // key is no more sufficient now that we support multiple faces per interface
/*
* If the facelet is uniquely identified by its key, it is used to perform
* an efficient lookup directly...
*/
if (facelet_has_key(facelet)) {
facelet_t * found = NULL;
- if (facelet_cache_get(facelet_cache, facelet, &found) < 0) {
+ if (facelet_set_get(facelet_cache, facelet, &found) < 0) {
ERROR("[facelet_cache_lookup] Error during cache lookup");
return -1;
}
@@ -507,12 +550,13 @@ facelet_cache_lookup(const facelet_cache_t * facelet_cache, facelet_t * facelet,
*cached_facelets[0] = found;
return 1;
}
+#endif
/* ...otherwise, we iterate over the facelet
* cache to find matching elements.
*/
facelet_t ** facelet_array;
- int n = facelet_cache_get_array(facelet_cache, &facelet_array);
+ int n = facelet_set_get_array(facelet_cache, &facelet_array);
if (n < 0) {
ERROR("[facelet_cache_lookup] Error during cache match");
return -1;
@@ -521,10 +565,6 @@ facelet_cache_lookup(const facelet_cache_t * facelet_cache, facelet_t * facelet,
int num_match = 0;
for (unsigned i = 0; i < n; i++) {
- char buf[128];
- facelet_snprintf(buf, 128, facelet_array[i]);
- facelet_snprintf(buf, 128, facelet);
-
if (!facelet_match(facelet_array[i], facelet)) {
continue;
}
@@ -781,6 +821,7 @@ facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet)
return -1;
}
+#if 0 /* Wrong if we need to complement local addr / port */
bool discovery_needed = (face_type.layer == FACE_TYPE_LAYER_4) &&
((!facelet_has_remote_addr(facelet)) || (!facelet_has_remote_port(facelet)));
@@ -788,6 +829,7 @@ facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet)
DEBUG("manual settings not considered as no discovery is needed");
return -2;
}
+#endif
if (discovery && !facelet_is_bj_done(facelet)) {
DEBUG("manual settings not considered as discovery is enabled and Bonjour has not yet been done");
@@ -874,6 +916,7 @@ facemgr_complement_facelet(facemgr_t * facemgr, facelet_t * facelet)
return rc;
#endif /* WITH_ANDROID_UTILITY */
+#if 0
if (!facelet_has_netdevice_type(facelet)) {
netdevice_t netdevice = NETDEVICE_EMPTY;
rc = facelet_get_netdevice(facelet, &netdevice);
@@ -883,6 +926,7 @@ facemgr_complement_facelet(facemgr_t * facemgr, facelet_t * facelet)
}
facelet_set_netdevice_type(facelet, facemgr_get_netdevice_type(facemgr, netdevice.name));
}
+#endif
/* We continue only if the current call was not applicable. In the current
* setting we have no interface that can be requested in parallel, and no
@@ -1073,7 +1117,7 @@ facemgr_reattempt_timeout(facemgr_t * facemgr, int fd, void * data)
/* Free all facelets from cache */
facelet_t ** facelet_array;
- int n = facelet_cache_get_array(&facemgr->facelet_cache, &facelet_array);
+ int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
if (n < 0) {
ERROR("[facemgr_reattempt_timeout] Could not retrieve facelets in cache");
} else {
@@ -1200,7 +1244,7 @@ facemgr_process_facelet_get(facemgr_t * facemgr, facelet_t * facelet)
if (!IS_VALID_NETDEVICE(netdevice))
return -2;
facelet_set_status(facelet, FACELET_STATUS_CLEAN);
- return facelet_cache_add(&facemgr->facelet_cache, facelet);
+ return facelet_set_add(facemgr->facelet_cache, facelet);
}
return -2;
}
@@ -1293,6 +1337,30 @@ facemgr_process_facelet_delete(facemgr_t * facemgr, facelet_t * facelet)
return 0;
}
+int facemgr_process_facelet_first_time(facemgr_t * facemgr, facelet_t * facelet)
+{
+ facelet_set_status(facelet, FACELET_STATUS_UNCERTAIN);
+
+ if (facelet_set_add(facemgr->facelet_cache, facelet) < 0) {
+ ERROR("[facemgr_process_facelet_first_time] Error adding facelet to cache");
+ goto ERR_CACHE;
+ }
+
+ if (facemgr_process_facelet_create(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_facelet_first_time] Error processing facelet CREATE event");
+ goto ERR_CREATE;
+ }
+
+ return 0;
+
+ERR_CREATE:
+ if (facelet_set_remove(facemgr->facelet_cache, facelet, NULL) < 0) {
+ ERROR("[facemgr_process_facelet_first_time] Error removing failed facelet from cache");
+ }
+ERR_CACHE:
+ return -1;
+}
+
/**
* \brief Process incoming events from interfaces
*
@@ -1313,7 +1381,7 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
DEBUG("EVENT %s", facelet_s);
facelet_t ** cached_facelets = NULL;
- int n = facelet_cache_lookup(&facemgr->facelet_cache, facelet_in, &cached_facelets);
+ int n = facelet_cache_lookup(facemgr->facelet_cache, facelet_in, &cached_facelets);
if (n < 0) {
ERROR("[facemgr_on_event] Error during cache lookup");
free(facelet_in);
@@ -1323,24 +1391,105 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
/* This is a new facelet... we expect a CREATE event. */
switch(facelet_get_event(facelet_in)) {
case FACELET_EVENT_CREATE:
+ {
+ /*
+ * This is the first time we hear about a facelet, it will
+ * likely not have an address family
+ *
+ * Assumption: we should always see the link before the address
+ * assignment
+ */
+ assert(!facelet_has_family(facelet_in));
+
+ if (!facelet_has_netdevice_type(facelet_in)) {
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ rc = facelet_get_netdevice(facelet_in, &netdevice);
+ if (rc < 0) {
+ ERROR("[facemgr_complement_facelet] Error retrieving netdevice from facelet");
+ return -1;
+ }
+ facelet_set_netdevice_type(facelet_in, facemgr_get_netdevice_type(facemgr, netdevice.name));
+ }
- facelet_set_status(facelet_in, FACELET_STATUS_UNCERTAIN);
- if (facelet_cache_add(&facemgr->facelet_cache, facelet_in) < 0) {
- ERROR("[facemgr_on_event] Error adding facelet to cache");
- free(facelet_in);
- free(cached_facelets);
- return -1;
+ /* Create default v4 and v6 facelets */
+ facelet_t * facelet_v4 = facelet_dup(facelet_in);
+ if (!facelet_v4) {
+ ERROR("[facemgr_on_event] Error allocating default IPv4 face");
+ facelet_free(facelet_v4);
+ } else {
+ facelet_set_family(facelet_v4, AF_INET);
+ facelet_set_status(facelet_v4, FACELET_STATUS_CLEAN);
+ if (facemgr_process_facelet_first_time(facemgr, facelet_v4) < 0) {
+ ERROR("[facemgr_on_event] Error creating default IPv4 face");
+ facelet_free(facelet_v4);
+ }
}
- remove_facelet = false;
+ facelet_t * facelet_v6 = facelet_dup(facelet_in);
+ if (!facelet_v6) {
+ ERROR("[facemgr_on_event] Error allocating default IPv6 face");
+ facelet_free(facelet_v4);
+ } else {
+ facelet_set_family(facelet_v6, AF_INET6);
+ facelet_set_status(facelet_v6, FACELET_STATUS_CLEAN);
+ if (facemgr_process_facelet_first_time(facemgr, facelet_v6) < 0) {
+ ERROR("[facemgr_on_event] Error creating default IPv6 face");
+ facelet_free(facelet_v6);
+ }
+ }
- if (facemgr_process_facelet_create(facemgr, facelet_in) < 0) {
- ERROR("[facemgr_on_event] Error processing facelet CREATE event");
- ret = -1;
- goto ERR;
+ /* Create additional connections
+ *
+ * This is where we spawn multiple facelets based on the
+ * configured "static routes" in addition to the default
+ * routes managed by the face manager.
+ */
+ for (unsigned i = 0; i < facelet_array_len(facemgr->static_facelets); i++) {
+ facelet_t * static_facelet;
+ if (facelet_array_get_index(facemgr->static_facelets, i, &static_facelet) < 0) {
+ ERROR("[facemgr_on_event] Error getting static facelet");
+ goto ERR;
+ }
+
+ /*
+ * We don't enforce any present or absent fields. A match
+ * operation will be performed deciding whether to create
+ * the facelet (if it bring additional information to the
+ * ingress one) or not.
+ */
+ /* We try to apply static_facelet over facelet_in */
+ if (!facelet_match(facelet_in, static_facelet)) {
+ continue;
+ }
+
+ facelet_t * facelet_new = facelet_dup(facelet_in);
+ if (!facelet_new) {
+ ERROR("[facemgr_on_event] Error allocating static facelet");
+ goto ERR;
+ } else {
+ if (facelet_merge(facelet_new, static_facelet) < 0) {
+ ERROR("[facemgr_on_event] Error merging facelets");
+ continue;
+ }
+ /* The id must be different than 0 */
+ facelet_set_id(facelet_new, i+1);
+ facelet_set_status(facelet_new, FACELET_STATUS_CLEAN);
+
+ char buf[MAXSZ_FACELET];
+ facelet_snprintf(buf, MAXSZ_FACELET, facelet_new);
+ if (facemgr_process_facelet_first_time(facemgr, facelet_new) < 0) {
+ ERROR("[facemgr_on_event] Error creating default IPv6 face");
+ facelet_free(facelet_v6);
+ }
+ }
}
+ /*
+ * We always remove the original facelet here, no need to
+ * preserve it
+ */
break;
+ }
case FACELET_EVENT_GET:
/* Insert new facelet in cached */
@@ -1445,7 +1594,7 @@ ERR:
DUMP_CACHE:
#if 1
DEBUG(" <CACHE>");
- facelet_cache_dump(&facemgr->facelet_cache);
+ facelet_set_dump(facemgr->facelet_cache);
DEBUG(" </CACHE>");
DEBUG("</EVENT ret=%d>", ret);
DEBUG("----------------------------------");
@@ -1475,7 +1624,7 @@ int facemgr_callback(facemgr_t * facemgr, interface_cb_type_t type, void * data)
interface_t * interface = (interface_t*)(fd_callback_data->owner);
interface_map_data_t * interface_map_data = NULL;
- if (interface_map_get(&facemgr->interface_map, interface->name, &interface_map_data) < 0) {
+ if (interface_map_get(facemgr->interface_map, interface->name, &interface_map_data) < 0) {
ERROR("[facemgr_callback] Error getting interface map data");
return -1;
}
@@ -1495,7 +1644,7 @@ int facemgr_callback(facemgr_t * facemgr, interface_cb_type_t type, void * data)
interface_t * interface = (interface_t*)(fd_callback_data->owner);
interface_map_data_t * interface_map_data = NULL;
- if (interface_map_get(&facemgr->interface_map, interface->name, &interface_map_data) < 0) {
+ if (interface_map_get(facemgr->interface_map, interface->name, &interface_map_data) < 0) {
ERROR("[facemgr_callback] Error getting interface map data");
return -1;
}
@@ -1668,10 +1817,10 @@ void facemgr_stop(facemgr_t * facemgr)
/* Delete all bonjour interfaces */
interface_t ** bonjour_array = NULL;
- int n = bonjour_map_get_value_array(&facemgr->bonjour_map, &bonjour_array);
+ int n = bonjour_map_get_value_array(facemgr->bonjour_map, &bonjour_array);
if (n >= 0) {
netdevice_t ** netdevice_array = NULL;
- int m = bonjour_map_get_key_array(&facemgr->bonjour_map, &netdevice_array);
+ int m = bonjour_map_get_key_array(facemgr->bonjour_map, &netdevice_array);
if (m >= 0) {
assert(m == n);
for (int i = 0; i < n; i++) { /* Fail silently */
@@ -1719,7 +1868,7 @@ void facemgr_list_facelets(const facemgr_t * facemgr, facemgr_list_facelets_cb_t
facelet_t ** facelet_array;
if (!cb)
return;
- int n = facelet_cache_get_array(&facemgr->facelet_cache, &facelet_array);
+ int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
if (n < 0) {
ERROR("[facemgr_list_facelets] Could not retrieve facelets in cache");
return;
@@ -1739,7 +1888,7 @@ facemgr_list_facelets_json(const facemgr_t * facemgr, char ** buffer)
int rc;
facelet_t ** facelet_array;
- int n = facelet_cache_get_array(&facemgr->facelet_cache, &facelet_array);
+ int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
if (n < 0) {
ERROR("[facemgr_list_facelets_json] Could not retrieve facelets in cache");
return -1;
diff --git a/ctrl/facemgr/src/cfg.c b/ctrl/facemgr/src/cfg.c
index bf47e5570..20c8d8332 100644
--- a/ctrl/facemgr/src/cfg.c
+++ b/ctrl/facemgr/src/cfg.c
@@ -8,6 +8,7 @@
#include <hicn/facemgr/cfg.h>
#include <hicn/policy.h>
#include <hicn/util/ip_address.h>
+#include "facelet_array.h"
#include "util/set.h"
/* Overlay */
@@ -443,22 +444,30 @@ TYPEDEF_SET(facemgr_cfg_rule_set, facemgr_cfg_rule_t *, facemgr_cfg_rule_cmp, ge
struct facemgr_cfg_s {
facemgr_cfg_override_t global;
facemgr_cfg_rule_set_t * rule_set;
+ facelet_array_t * static_facelets;
//log_cfg_t log;
};
facemgr_cfg_t * facemgr_cfg_create()
{
facemgr_cfg_t * cfg = malloc(sizeof(facemgr_cfg_t));
- if (!cfg)
- return NULL;
+ if (!cfg) {
+ ERROR("[facemgr_cfg_create] Error allocating face manager configuration");
+ goto ERR_MALLOC;
+ }
int rc = facemgr_cfg_initialize(cfg);
if (rc < 0) {
- free(cfg);
- return NULL;
+ ERROR("[facemgr_cfg_create] Error initializing face manager configuration");
+ goto ERR_INIT;
}
return cfg;
+
+ERR_INIT:
+ free(cfg);
+ERR_MALLOC:
+ return NULL;
}
void facemgr_cfg_free(facemgr_cfg_t * cfg)
@@ -471,15 +480,27 @@ int
facemgr_cfg_initialize(facemgr_cfg_t * cfg)
{
int rc = facemgr_cfg_override_initialize(&cfg->global);
- if (rc < 0)
+ if (rc < 0) {
+ ERROR("[facemgr_cfg_initialize] Error initializing global values");
goto ERR_OVERRIDE;
+ }
cfg->rule_set = facemgr_cfg_rule_set_create();
- if (!cfg->rule_set)
+ if (!cfg->rule_set) {
+ ERROR("[facemgr_cfg_initialize] Error creating rule set");
goto ERR_RULE_SET;
+ }
+
+ cfg->static_facelets = facelet_array_create(cfg->static_facelets);
+ if (!cfg->static_facelets) {
+ ERROR("[facemgr_cfg_initialize] Error creating static facelet set");
+ goto ERR_STATIC;
+ }
return 0;
+ERR_STATIC:
+ facemgr_cfg_rule_set_free(cfg->rule_set);
ERR_RULE_SET:
facemgr_cfg_override_finalize(&cfg->global);
ERR_OVERRIDE:
@@ -505,6 +526,22 @@ facemgr_cfg_finalize(facemgr_cfg_t * cfg)
free(rule_array);
}
facemgr_cfg_rule_set_free(cfg->rule_set);
+
+ /* Free all facelets from static array */
+ for (unsigned i = 0; i < facelet_array_len(cfg->static_facelets); i++) {
+ facelet_t * facelet;
+ if (facelet_array_get_index(cfg->static_facelets, i, &facelet) < 0) {
+ ERROR("[facemgr_cfg_finalize] Error getting facelet in array");
+ continue;
+ }
+ if (facelet_array_remove_index(cfg->static_facelets, i, NULL)) {
+ ERROR("[facemgr_cfg_finalize] Could not purge facelet from static set");
+ }
+ facelet_free(facelet);
+ }
+
+ facelet_array_free(cfg->static_facelets);
+
return facemgr_cfg_override_finalize(&cfg->global);
}
@@ -1038,3 +1075,29 @@ facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t * cfg,
*port = HICN_DEFAULT_PORT;
return 0;
}
+
+int
+facemgr_cfg_add_static_facelet(facemgr_cfg_t * cfg, facelet_t * facelet)
+{
+ char buf[MAXSZ_FACELET];
+ facelet_snprintf(buf, MAXSZ_FACELET, facelet);
+ DEBUG("STATIC FACELET: %s", buf);
+ return facelet_array_add(cfg->static_facelets, facelet);
+}
+
+int
+facemgr_cfg_remove_static_facelet(facemgr_cfg_t * cfg, facelet_t * facelet,
+ facelet_t ** removed_facelet)
+{
+ return facelet_array_remove(cfg->static_facelets, facelet, removed_facelet);
+}
+
+int
+facemgr_cfg_get_static_facelet_array(const facemgr_cfg_t * cfg, facelet_t *** array)
+{
+ if (facelet_array_get_elements(cfg->static_facelets, array) < 0) {
+ ERROR("[facemgr_cfg_get_static_facelet_array] Error getting array elements");
+ return -1;
+ }
+ return facelet_array_len(cfg->static_facelets);
+}
diff --git a/ctrl/facemgr/src/cfg_file.c b/ctrl/facemgr/src/cfg_file.c
index 5c187e0a2..cb1ded1c9 100644
--- a/ctrl/facemgr/src/cfg_file.c
+++ b/ctrl/facemgr/src/cfg_file.c
@@ -20,6 +20,9 @@
#include <unistd.h> // access
#include <libconfig.h>
+
+#include <hicn/ctrl/route.h>
+
#include "cfg_file.h"
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*x))
@@ -464,6 +467,178 @@ ERR_CHECK:
return -1;
}
+int parse_config_static_facelets(facemgr_cfg_t * cfg, config_setting_t * setting)
+{
+ int count = config_setting_length(setting);
+ for (unsigned i = 0; i < count; ++i) {
+ config_setting_t * static_setting = config_setting_get_elem(setting, i);
+
+ const char *face_type_str;
+ facemgr_face_type_t face_type;
+ const char * family_str;
+ int family;
+ const char * remote_addr_str;
+ ip_address_t remote_addr = IP_ADDRESS_EMPTY;
+ int remote_port = 0;
+ const char * interface_name;
+ const char * interface_type_str;
+
+ facelet_t * facelet = facelet_create();
+
+ /* Face type */
+ if (config_setting_lookup_string(static_setting, "face_type", &face_type_str)) {
+ if (strcasecmp(face_type_str, "auto") == 0) {
+ face_type = FACEMGR_FACE_TYPE_DEFAULT;
+ } else
+ if (strcasecmp(face_type_str, "native-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_UDP;
+ } else
+ if (strcasecmp(face_type_str, "native-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+ } else
+ if (strcasecmp(face_type_str, "overlay-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+ } else
+ if (strcasecmp(face_type_str, "overlay-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
+ } else {
+ ERROR("Invalid face type in section 'global'");
+ goto ERR_FACELET;
+ }
+
+ int rc = facelet_set_face_type(facelet, face_type);
+ if (rc < 0)
+ goto ERR_FACELET;
+ }
+
+ /* Family */
+ if (config_setting_lookup_string(static_setting, "family", &family_str)) {
+ if (strcasecmp(family_str, "AF_INET") == 0) {
+ family = AF_INET;
+ } else
+ if (strcasecmp(family_str, "AF_INET6") == 0) {
+ family = AF_INET6;
+ } else {
+ ERROR("Invalid family in section 'static', items #%d", i+1);
+ goto ERR_FACELET;
+ }
+ int rc = facelet_set_family(facelet, family);
+ if (rc < 0)
+ goto ERR_FACELET;
+ }
+
+ /* Remote address */
+ if (config_setting_lookup_string(static_setting, "remote_addr", &remote_addr_str)) {
+ if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
+ ERROR("Error parsing v4 remote addr");
+ goto ERR_FACELET;
+ }
+
+ int rc = facelet_set_remote_addr(facelet, remote_addr);
+ if (rc < 0)
+ goto ERR_FACELET;
+ }
+
+ /* Remote port */
+ if (config_setting_lookup_int(static_setting, "remote_port", &remote_port)) {
+ if (!IS_VALID_PORT(remote_port))
+ goto ERR_FACELET;
+ int rc = facelet_set_remote_port(facelet, remote_port);
+ if (rc < 0)
+ goto ERR_FACELET;
+ }
+
+ /* Interface name */
+ if (config_setting_lookup_string(static_setting, "interface_name", &interface_name)) {
+ netdevice_t netdevice;
+ /* Warning: interface might not exist when we create the facelet */
+ snprintf(netdevice.name, IFNAMSIZ, "%s", interface_name);
+ netdevice.index = 0;
+ int rc = facelet_set_netdevice(facelet, netdevice);
+ if (rc < 0)
+ goto ERR_FACELET;
+ }
+
+ /* Interface type */
+ netdevice_type_t interface_type = NETDEVICE_TYPE_UNDEFINED;
+ if (config_setting_lookup_string(static_setting, "interface_type", &interface_type_str)) {
+ if (strcasecmp(interface_type_str, "wired") == 0) {
+ interface_type = NETDEVICE_TYPE_WIRED;
+ } else
+ if (strcasecmp(interface_type_str, "wifi") == 0) {
+ interface_type = NETDEVICE_TYPE_WIFI;
+ } else
+ if (strcasecmp(interface_type_str, "cellular") == 0) {
+ interface_type = NETDEVICE_TYPE_CELLULAR;
+ } else {
+ ERROR("Unknown interface type in rule #%d", i);
+ goto ERR_FACELET;
+ }
+
+ int rc = facelet_set_netdevice_type(facelet, interface_type);
+ if (rc < 0)
+ goto ERR_FACELET;
+ }
+
+ /* Routes */
+ config_setting_t * routes_static_setting = config_setting_get_member(static_setting, "routes");
+ if (routes_static_setting) {
+ /* ... */
+ int count_routes = config_setting_length(routes_static_setting);
+ for (unsigned j = 0; j < count_routes; ++j) {
+ config_setting_t * route_static_setting = config_setting_get_elem(routes_static_setting, j);
+
+ const char * prefix_str;
+ ip_prefix_t prefix;
+ int cost = 0; /* default */
+
+ if (config_setting_lookup_string(route_static_setting, "prefix", &prefix_str)) {
+ if (ip_prefix_pton(prefix_str, &prefix) < 0) {
+ ERROR("Error parsing prefix in route #%d, rule #%d", j, i);
+ goto ERR_FACELET;
+ }
+ } else {
+ ERROR("Cannot add route without prefix");
+ goto ERR_FACELET;
+ }
+
+ config_setting_lookup_int(static_setting, "cost", &cost);
+
+ hicn_route_t * route = hicn_route_create(&prefix, 0, cost);
+ if (!route) {
+ ERROR("Could not create hICN route");
+ goto ERR_FACELET;
+ }
+
+ int rc = facelet_add_route(facelet, route);
+ if (rc < 0) {
+ ERROR("Could not add route to facelet");
+ goto ERR_ROUTE;
+ }
+
+ continue;
+
+ERR_ROUTE:
+ hicn_route_free(route);
+ goto ERR_FACELET;
+ }
+ }
+
+ if (facemgr_cfg_add_static_facelet(cfg, facelet) < 0) {
+ ERROR("Could not add static facelet to configuration");
+ goto ERR_FACELET;
+ }
+
+ continue;
+
+ERR_FACELET:
+ facelet_free(facelet);
+ return -1;
+
+ }
+ return 0;
+}
+
/* Currently not using facemgr_cfg_t */
int
parse_config_log(facemgr_cfg_t * cfg, config_setting_t * setting)
@@ -522,6 +697,13 @@ parse_config_file(const char * cfgpath, facemgr_cfg_t * cfg)
goto ERR_PARSE;
}
+ setting = config_lookup(&cfgfile, "static");
+ if (setting) {
+ int rc = parse_config_static_facelets(cfg, setting);
+ if (rc < 0)
+ goto ERR_PARSE;
+ }
+
setting = config_lookup(&cfgfile, "log");
if (setting) {
int rc = parse_config_log(cfg, setting);
diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c
index 01f4b8076..ccd8b54c9 100644
--- a/ctrl/facemgr/src/facelet.c
+++ b/ctrl/facemgr/src/facelet.c
@@ -21,10 +21,18 @@
#include <assert.h>
#include <stdbool.h>
#include <hicn/ctrl/face.h>
+#include <hicn/ctrl/route.h>
#include <hicn/facemgr/cfg.h>
#include <hicn/facemgr/facelet.h>
#include <hicn/util/log.h>
+#include "util/set.h"
+
+#define FACELET_MAX_ROUTES 10
+
+TYPEDEF_SET_H(route_set, hicn_route_t *);
+TYPEDEF_SET(route_set, hicn_route_t *, hicn_route_cmp, generic_snprintf);
+
const char * face_type_layer_str[] = {
#define _(x) [FACE_TYPE_LAYER_ ## x] = STRINGIZE(x),
foreach_face_type_layer
@@ -66,6 +74,8 @@ const char * facelet_attr_status_str_short[] = {
/* Facelet */
struct facelet_s {
+ unsigned id;
+
#define _(TYPE, NAME) TYPE NAME;
foreach_facelet_attr
#undef _
@@ -73,12 +83,16 @@ struct facelet_s {
foreach_facelet_attr
#undef _
+
+
facelet_status_t status;
bool status_error;
facelet_event_t event;
- /* Joins */
+ route_set_t * routes;
+ bool routes_done;
+
bool bj_done;
bool au_done;
};
@@ -96,6 +110,8 @@ facelet_create()
if (!facelet)
goto ERR_MALLOC;
+ facelet->id = 0;
+
facelet->netdevice_status = FACELET_ATTR_STATUS_UNSET;
facelet->netdevice_type_status = FACELET_ATTR_STATUS_UNSET;
facelet->family_status = FACELET_ATTR_STATUS_UNSET;
@@ -115,12 +131,27 @@ facelet_create()
facelet->event = FACELET_EVENT_UNDEFINED;
+ facelet->routes = route_set_create();
+ if (!facelet->routes) {
+ ERROR("[facelet_create] Cannot create route set");
+ goto ERR_ROUTE_SET;
+ }
+ facelet->routes_done = false;
+
return facelet;
+ERR_ROUTE_SET:
+ free(facelet);
ERR_MALLOC:
return NULL;
}
+void
+facelet_set_id(facelet_t * facelet, unsigned id)
+{
+ facelet->id = id;
+}
+
facelet_t *
facelet_create_from_netdevice(netdevice_t * netdevice)
{
@@ -143,7 +174,7 @@ ERR_FACELET:
/**
* \brief Validate whether the facelet has all required fields to construct a
* face of the given type
- * \param [in) facelet - Pointer to the facelet to verify
+ * \param [in] facelet - Pointer to the facelet to verify
* \return 0 in case of success, -1 otherwise
*/
int
@@ -192,6 +223,8 @@ facelet_create_from_face(face_t * face)
if (!facelet)
goto ERR_MALLOC;
+ facelet->id = 0;
+
/* Go through the face attributes to update the local representation */
/* Attribute : netdevice */
@@ -309,8 +342,17 @@ facelet_create_from_face(face_t * face)
facelet->event = FACELET_EVENT_UNDEFINED;
+ /* We need to get route set */
+ facelet->routes = route_set_create();
+ if (!facelet->routes) {
+ ERROR("[facelet_create] Cannot create route set");
+ goto ERR_ROUTE_SET;
+ }
+ facelet->routes_done = false;
+
return facelet;
+ERR_ROUTE_SET:
ERR_FACE:
free(facelet);
ERR_MALLOC:
@@ -321,6 +363,20 @@ ERR_MALLOC:
void
facelet_free(facelet_t * facelet)
{
+ /* Free up routes */
+ hicn_route_t ** route_array;
+ int n = route_set_get_array(facelet->routes, &route_array);
+ if (n < 0) {
+ ERROR("[facelet_free] Error getting route set associated to facelet");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hicn_route_t * route = route_array[i];
+ route_set_remove(facelet->routes, route, NULL);
+ hicn_route_free(route);
+ }
+ }
+ free(route_array);
+ route_set_free(facelet->routes);
free(facelet);
}
@@ -344,6 +400,19 @@ facelet_dup(const facelet_t * current_facelet)
facelet->bj_done = current_facelet->bj_done;
facelet->au_done = current_facelet->au_done;
+ /* Routes */
+ hicn_route_t ** route_array;
+ int n = route_set_get_array(current_facelet->routes, &route_array);
+ if (n < 0) {
+ ERROR("[facelet_free] Error getting route set associated to facelet");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hicn_route_t * route = route_array[i];
+ route_set_add(facelet->routes, route);
+ }
+ }
+ free(route_array);
+
return facelet;
ERR_CREATE:
@@ -358,6 +427,8 @@ facelet_cmp(const facelet_t * f1, const facelet_t * f2)
* facelet is uniquely identified by its netdevice attribute, and address
* family if any.
*
+ * Because of additional static faces, we introduce a unique facelet id
+ *
* This function is mostly used for lookups into the cache, and the face
* thus needs to have a netdevice associated, and optionally, an address
* family.
@@ -365,6 +436,9 @@ facelet_cmp(const facelet_t * f1, const facelet_t * f2)
* For other situations, the `facelet_match` function is more appropriate.
*/
+ if (f1->id != f2->id)
+ return f1->id > f2->id ? 1 : -1;
+
if ((f1->netdevice_status != FACELET_ATTR_STATUS_UNSET) &&
(f2->netdevice_status != FACELET_ATTR_STATUS_UNSET)) {
int rc = netdevice_cmp(&f1->netdevice, &f2->netdevice);
@@ -394,20 +468,58 @@ facelet_cmp(const facelet_t * f1, const facelet_t * f2)
* If the match has a field set, then the facelet only matches iif it has the
* same field set, and both values are equal
*/
+#define EQUALS_ATTRIBUTE(TYPE, NAME) \
+do { \
+ if (facelet_has_ ## NAME(facelet1)) { \
+ if (facelet_has_ ## NAME(facelet2)) { \
+ TYPE NAME ## 1; \
+ TYPE NAME ## 2; \
+ if (facelet_get_ ## NAME (facelet1, & NAME ## 1) < 0) \
+ return false; \
+ if (facelet_get_ ## NAME (facelet2, & NAME ## 2) < 0) \
+ return false; \
+ if (memcmp(& NAME ## 1, & NAME ## 2, sizeof(TYPE)) != 0) \
+ return false; \
+ } else { \
+ return false; \
+ } \
+ } else { \
+ if (facelet_has_ ## NAME(facelet2)) { \
+ return false; \
+ } \
+ } \
+} while(0)
+
+/* facelet_match is the incoming one */
+bool
+facelet_equals(const facelet_t * facelet1, const facelet_t * facelet2)
+{
+#define _(TYPE, NAME) EQUALS_ATTRIBUTE(TYPE, NAME);
+ foreach_facelet_attr
+#undef _
+ return true;
+}
+
+/*
+ * If the match has a field set, then the facelet only matches iif it has the
+ * same field set, and both values are equal
+ */
#define MATCH_ATTRIBUTE(TYPE, NAME) \
do { \
if (facelet_match->NAME ## _status == FACELET_ATTR_STATUS_CLEAN) { \
if (facelet_has_ ## NAME(facelet_match)) { \
TYPE NAME; \
TYPE NAME ## _match; \
- if (!facelet_has_ ## NAME(facelet)) \
- return false; \
+ if (!facelet_has_ ## NAME(facelet)) { \
+ continue; /* return false; */ \
+ } \
if (facelet_get_ ## NAME (facelet, & NAME) < 0) \
return false; \
if (facelet_get_ ## NAME (facelet_match, & NAME ## _match) < 0) \
return false; \
- if (memcmp(& NAME, & NAME ## _match, sizeof(NAME)) != 0) \
+ if (memcmp(& NAME, & NAME ## _match, sizeof(NAME)) != 0) { \
return false; \
+ } \
} \
} \
} while(0)
@@ -561,6 +673,20 @@ int facelet_merge(facelet_t * facelet, const facelet_t * facelet_to_merge)
foreach_facelet_attr
#undef _
facelet->event = facelet_to_merge->event;
+
+ /* Routes */
+ hicn_route_t ** route_array;
+ int n = route_set_get_array(facelet_to_merge->routes, &route_array);
+ if (n < 0) {
+ ERROR("[facelet_free] Error getting route set associated to facelet");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hicn_route_t * route = route_array[i];
+ route_set_add(facelet->routes, route);
+ }
+ }
+ free(route_array);
+
return 0;
}
@@ -781,6 +907,24 @@ facelet_set_event(facelet_t * facelet, facelet_event_t event)
}
int
+facelet_add_route(facelet_t * facelet, hicn_route_t * route)
+{
+ return route_set_add(facelet->routes, route);
+}
+
+int
+facelet_remove_route(facelet_t * facelet, hicn_route_t * route, hicn_route_t ** route_removed)
+{
+ return route_set_remove(facelet->routes, route, route_removed);
+}
+
+int
+facelet_get_route_array(const facelet_t * facelet, hicn_route_t *** route_array)
+{
+ return route_set_get_array(facelet->routes, route_array);
+}
+
+int
facelet_snprintf(char * s, size_t size, const facelet_t * facelet)
{
char * cur = s;
@@ -919,6 +1063,7 @@ facelet_snprintf(char * s, size_t size, const facelet_t * facelet)
return cur - s;
}
+ /* Face type */
if (facelet_has_face_type(facelet)) {
rc = snprintf(cur, s + size - cur, " face_type=LAYER%s/%s",
FACEMGR_FACE_TYPE_STR(facelet->face_type));
@@ -929,7 +1074,39 @@ facelet_snprintf(char * s, size_t size, const facelet_t * facelet)
return cur - s;
}
- rc = snprintf(cur, s + size - cur, ">");
+ /* Routes */
+ rc = snprintf(cur, s + size - cur, " routes={ ");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+
+ hicn_route_t ** route_array;
+ int n = route_set_get_array(facelet->routes, &route_array);
+ if (n < 0) {
+ ERROR("[facelet_free] Error getting route set associated to facelet");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hicn_route_t * route = route_array[i];
+ rc = hicn_route_snprintf(cur, s + size - cur, route);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+
+ rc = snprintf(cur, s + size - cur, ", ");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+ }
+ }
+ free(route_array);
+
+ rc = snprintf(cur, s + size - cur, "}>");
if (rc < 0)
return rc;
cur += rc;
@@ -1129,6 +1306,8 @@ int facelet_snprintf_json(char * s, size_t size, const facelet_t * facelet, int
if (cur >= s + size)
return cur - s;
+ /* Routes */
+ // TODO
rc = snprintf(cur, s + size - cur, "%*s%s", 4 * indent, "", "}");
if (rc < 0)
diff --git a/ctrl/facemgr/src/facelet_array.c b/ctrl/facemgr/src/facelet_array.c
new file mode 100644
index 000000000..4d7f30862
--- /dev/null
+++ b/ctrl/facemgr/src/facelet_array.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file facelet_array.c
+ * \brief Implementation of facelet array
+ */
+
+#include <hicn/facemgr/facelet.h>
+#include "facelet_array.h"
+#include "util/array.h"
+
+TYPEDEF_ARRAY(facelet_array, facelet_t *, facelet_equals, facelet_snprintf);
+
diff --git a/ctrl/facemgr/src/facelet_array.h b/ctrl/facemgr/src/facelet_array.h
new file mode 100644
index 000000000..8febe7885
--- /dev/null
+++ b/ctrl/facemgr/src/facelet_array.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file facelet_array.h
+ * \brief Facelet array
+ */
+#ifndef FACELET_ARRAY_H
+#define FACELET_ARRAY_H
+
+#include <hicn/facemgr/facelet.h>
+
+#include "util/array.h"
+
+TYPEDEF_ARRAY_H(facelet_array, facelet_t *);
+
+#endif /* FACELET_ARRAY_H */
diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
index 01a356f3a..756d85738 100644
--- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
+++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
@@ -44,7 +44,12 @@ typedef enum {
typedef struct {
hc_sock_t * s; /* NULL means no active socket */
hl_state_t state;
- int timer_fd; /* 0 means no active timer */
+
+ /* Timer used for forwarder reconnection */
+ int reconnect_timer_fd; /* 0 means no active timer */
+
+ /* Timer used to periodically poll the forwarder face and routing tables */
+ int poll_timer_fd;
} hl_data_t;
/* Forward declarations */
@@ -148,8 +153,8 @@ ERR_SOCK:
int hl_disconnect(interface_t * interface)
{
hl_data_t * data = (hl_data_t *) interface->data;
- if (data->timer_fd > 0)
- interface_unregister_timer(interface, data->timer_fd);
+ if (data->reconnect_timer_fd > 0)
+ interface_unregister_timer(interface, data->reconnect_timer_fd);
if (data->s) {
interface_unregister_fd(interface, hc_sock_get_fd(data->s));
@@ -169,8 +174,8 @@ hl_connect(interface_t * interface)
/* Timer for managing the connection to the forwarder */
DEBUG("Connection to forwarder failed... next retry in %ds", INTERVAL_MS / 1000);
- data->timer_fd = interface_register_timer(interface, INTERVAL_MS, hl_connect_timeout, NULL);
- if (data->timer_fd < 0) {
+ data->reconnect_timer_fd = interface_register_timer(interface, INTERVAL_MS, hl_connect_timeout, NULL);
+ if (data->reconnect_timer_fd < 0) {
ERROR("[hc_connect] Could not initialize reattempt timer");
return -1;
}
@@ -188,7 +193,7 @@ hl_initialize(interface_t * interface, void * cfg)
}
data->s = NULL;
- data->timer_fd = 0;
+ data->reconnect_timer_fd = 0;
interface->data = data;
@@ -221,6 +226,7 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
hc_face_t hc_face;
hc_route_t route;
int rc;
+ int ret = 0;
hl_data_t * data = (hl_data_t *)interface->data;
face_t * face = NULL;
@@ -245,6 +251,11 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
case FACELET_EVENT_CREATE:
/* Create face */
+ {
+ char buf[MAXSZ_FACELET];
+ facelet_snprintf(buf, MAXSZ_FACELET, facelet);
+ printf("Create face %s\n", buf);
+ }
hc_face.face = *face;
rc = hc_face_create(data->s, &hc_face);
if (rc < 0) {
@@ -253,50 +264,70 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
}
INFO("Created face id=%d", hc_face.id);
- /* Adding default routes */
-#if 1
- route = (hc_route_t) {
- .face_id = hc_face.id,
- .family = AF_INET,
- .remote_addr = IPV4_ANY,
- .len = 0,
- .cost = DEFAULT_ROUTE_COST,
-
- };
- if (hc_route_create(data->s, &route) < 0) {
+ hicn_route_t ** route_array;
+ int n = facelet_get_route_array(facelet, &route_array);
+ if (n < 0) {
ERROR("Failed to create default hICN/IPv4 route");
goto ERR;
}
+ if (n == 0) {
+ /* Adding default routes */
+ route = (hc_route_t) {
+ .face_id = hc_face.id,
+ .family = AF_INET,
+ .remote_addr = IPV4_ANY,
+ .len = 0,
+ .cost = DEFAULT_ROUTE_COST,
+
+ };
+ if (hc_route_create(data->s, &route) < 0) {
+ ERROR("Failed to create default hICN/IPv4 route");
+ ret = -1;
+ }
- route = (hc_route_t) {
- .face_id = hc_face.id,
- .family = AF_INET6,
- .remote_addr = IPV6_ANY,
- .len = 0,
- .cost = DEFAULT_ROUTE_COST,
- };
- if (hc_route_create(data->s, &route) < 0) {
- ERROR("Failed to create default hICN/IPv6 route");
- goto ERR;
- }
+ route = (hc_route_t) {
+ .face_id = hc_face.id,
+ .family = AF_INET6,
+ .remote_addr = IPV6_ANY,
+ .len = 0,
+ .cost = DEFAULT_ROUTE_COST,
+ };
+ if (hc_route_create(data->s, &route) < 0) {
+ ERROR("Failed to create default hICN/IPv6 route");
+ ret = -1;
+ }
+
+ INFO("Successfully created default route(s).");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hicn_route_t * hicn_route = route_array[i];
+ ip_prefix_t prefix;
+ int cost;
+ if (hicn_route_get_prefix(hicn_route, &prefix) < 0) {
+ ERROR("Failed to get route prefix");
+ ret = -1;
+ continue;
+ }
+ if (hicn_route_get_cost(hicn_route, &cost) < 0) {
+ ERROR("Failed to get route cost");
+ ret = -1;
+ continue;
+ }
+ route = (hc_route_t) {
+ .face_id = hc_face.id,
+ .family = prefix.family,
+ .remote_addr = prefix.address,
+ .len = prefix.len,
+ .cost = cost,
+ };
+ if (hc_route_create(data->s, &route) < 0) {
+ ERROR("Failed to create static route route");
+ ret = -1;
+ continue;
+ }
+ }
-#else
- route = (hc_route_t) {
- .face_id = hc_face.id,
- .family = AF_INET6,
- .len = 0,
- .cost = DEFAULT_ROUTE_COST,
- };
- if (ip_address_pton("::", &route.remote_addr) < 0) {
- ERROR("Failed to convert prefix");
- goto ERR;
- }
- if (hc_route_create(data->s, &route) < 0) {
- ERROR("Failed to create hICN/IPv6 route");
- goto ERR;
}
-#endif
- INFO("Successfully created default route(s).");
break;
@@ -351,7 +382,7 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
}
face_free(face);
- return 0;
+ return ret;
ERR:
face_free(face);
diff --git a/ctrl/facemgr/src/interfaces/netlink/netlink.c b/ctrl/facemgr/src/interfaces/netlink/netlink.c
index a9c8c889e..653f49d26 100644
--- a/ctrl/facemgr/src/interfaces/netlink/netlink.c
+++ b/ctrl/facemgr/src/interfaces/netlink/netlink.c
@@ -422,6 +422,7 @@ int nl_callback(interface_t * interface, int fd, void * unused)
//DEBUG("Interface %s: address was removed", interface_name);
if (facelet) {
facelet_set_event(facelet, FACELET_EVENT_DELETE);
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
interface_raise_event(interface, facelet);
}
break;
@@ -443,6 +444,7 @@ int nl_callback(interface_t * interface, int fd, void * unused)
if (facelet) {
facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
interface_raise_event(interface, facelet);
}
break;
@@ -464,6 +466,7 @@ int nl_callback(interface_t * interface, int fd, void * unused)
break;
facelet_set_event(facelet, FACELET_EVENT_DELETE);
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
interface_raise_event(interface, facelet);
break;
@@ -493,17 +496,19 @@ int nl_callback(interface_t * interface, int fd, void * unused)
break;
if (up && running) {
facelet_set_event(facelet, FACELET_EVENT_CREATE);
+ //facelet_set_family(facelet, AF_INET);
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ interface_raise_event(interface, facelet);
+
+#if 0
facelet_t * facelet6 = facelet_dup(facelet);
if (!facelet6) {
ERROR("Could not duplicate face for v6");
break;
}
-
- facelet_set_family(facelet, AF_INET);
- interface_raise_event(interface, facelet);
-
facelet_set_family(facelet6, AF_INET6);
interface_raise_event(interface, facelet6);
+#endif
} else {
facelet_free(facelet);
}
diff --git a/ctrl/facemgr/src/util/array.h b/ctrl/facemgr/src/util/array.h
new file mode 100644
index 000000000..ab8852ed8
--- /dev/null
+++ b/ctrl/facemgr/src/util/array.h
@@ -0,0 +1,199 @@
+/*
+ * 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 array.h
+ * \brief Generic array template
+ */
+
+#ifndef UTIL_ARRAY_H
+#define UTIL_ARRAY_H
+
+#include <assert.h>
+#include <hicn/util/log.h>
+#include <math.h> // log2
+#include <string.h> // memmove
+
+#define BUFSIZE 1024
+
+typedef int(*cmp_t)(const void * x, const void * y);
+
+#define TYPEDEF_ARRAY_H(NAME, T) \
+ \
+typedef struct { \
+ size_t size; \
+ size_t max_size_log; \
+ T * elements; \
+} NAME ## _t; \
+ \
+int NAME ## _initialize(NAME ## _t * array); \
+ \
+int NAME ## _finalize(NAME ## _t * array); \
+ \
+NAME ## _t * NAME ## _create(); \
+ \
+void NAME ## _free(NAME ## _t * array); \
+ \
+int NAME ## _add(NAME ## _t * array, T element); \
+ \
+int NAME ## _remove_index(NAME ## _t * array, int index, T * element); \
+ \
+int NAME ## _remove(NAME ## _t * array, const T search, T * element); \
+ \
+int NAME ## _get(const NAME ## _t * array, const T search, T * element); \
+ \
+int NAME ## _get_index(const NAME ## _t * array, int index, T * element); \
+ \
+int NAME ## _get_elements(const NAME ## _t * array, T ** elements); \
+ \
+size_t NAME ## _len(const NAME ## _t * array);
+
+
+#define ARRAY_MAX_SIZE_LOG_INIT 0
+
+#define TYPEDEF_ARRAY(NAME, T, CMP, SNPRINTF) \
+int \
+NAME ## _initialize(NAME ## _t * array) \
+{ \
+ array->max_size_log = ARRAY_MAX_SIZE_LOG_INIT; \
+ array->size = 0; \
+ if (array->max_size_log == 0) { \
+ array->elements = NULL; \
+ return 0; \
+ } \
+ array->elements = malloc((1 << array->max_size_log) * sizeof(T)); \
+ if (!array->elements) \
+ return -1; \
+ return 0; \
+} \
+ \
+int \
+NAME ## _finalize(NAME ## _t * array) \
+{ \
+ for (unsigned i = 0; i < array->size; i++) { \
+ NAME ## _remove_index(array, i, NULL); \
+ } \
+ return 0; \
+} \
+ \
+NAME ## _t * \
+NAME ## _create() \
+{ \
+ NAME ## _t * array = malloc(sizeof(NAME ## _t)); \
+ if (!array) \
+ goto ERR_MALLOC; \
+ \
+ if (NAME ## _initialize(array) < 0) \
+ goto ERR_INITIALIZE; \
+ \
+ return array; \
+ \
+ERR_INITIALIZE: \
+ free(array); \
+ERR_MALLOC: \
+ return NULL; \
+} \
+ \
+void \
+NAME ## _free(NAME ## _t * array) \
+{ \
+ NAME ## _finalize(array); \
+ free(array->elements); \
+ free(array); \
+} \
+ \
+int \
+NAME ## _add(NAME ## _t * array, T element) \
+{ \
+ /* Ensure sufficient space for next addition */ \
+ size_t new_size_log = (array->size > 0) ? log2(array->size)+1 : 1; \
+ if (new_size_log > array->max_size_log) { \
+ array->max_size_log = new_size_log; \
+ array->elements = realloc(array->elements, \
+ (1 << new_size_log) * sizeof(T)); \
+ } \
+ \
+ if (!array->elements) \
+ goto ERR_REALLOC; \
+ \
+ array->elements[array->size++] = element; \
+ return 0; \
+ \
+ERR_REALLOC: \
+ return -1; \
+} \
+ \
+int \
+NAME ## _remove_index(NAME ## _t * array, int index, T * element) \
+{ \
+ if (index > NAME ## _len(array)) \
+ return -1; \
+ if (element) \
+ *element = array->elements[index]; \
+ if (index < array->size) \
+ memmove(array->elements + index, array->elements + index + 1, \
+ array->size - index); \
+ array->size--; \
+ return 0; \
+} \
+ \
+int \
+NAME ## _remove(NAME ## _t * array, const T search, T * element) \
+{ \
+ for (unsigned i = 0; i < array->size; i++) { \
+ if (CMP(search, array->elements[i]) == 0) \
+ return facelet_array_remove_index(array, i, element); \
+ } \
+ /* Not found */ \
+ if (element) \
+ *element = NULL; \
+ return 0; \
+} \
+ \
+int \
+NAME ## _get(const NAME ## _t * array, const T search, T * element) \
+{ \
+ assert(element); \
+ for (unsigned i = 0; i < array->size; i++) \
+ if (CMP(search, array->elements[i]) == 0) \
+ *element = array->elements[i]; \
+ return 0; \
+ /* Not found */ \
+ *element = NULL; \
+ return 0; \
+} \
+ \
+int \
+NAME ## _get_index(const NAME ## _t * array, int index, T * element) \
+{ \
+ assert(element); \
+ *element = array->elements[index]; \
+ return 0; \
+} \
+ \
+int \
+NAME ## _get_elements(const NAME ## _t * array, T ** elements) \
+{ \
+ *elements = array->elements; \
+ return 0; \
+} \
+ \
+size_t \
+NAME ## _len(const NAME ## _t * array) \
+{ \
+ return array->size; \
+}
+
+#endif /* UTIL_ARRAY_H */
diff --git a/ctrl/libhicnctrl/includes/CMakeLists.txt b/ctrl/libhicnctrl/includes/CMakeLists.txt
index a85489a0c..50cfa4ad5 100644
--- a/ctrl/libhicnctrl/includes/CMakeLists.txt
+++ b/ctrl/libhicnctrl/includes/CMakeLists.txt
@@ -22,5 +22,6 @@ set(TO_INSTALL_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/api.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/commands.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/face.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/route.h
PARENT_SCOPE
-) \ No newline at end of file
+)
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
index 7b57a6323..f522010cd 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -213,7 +213,7 @@ hc_ ## TYPE ## _find(hc_data_t * data, const hc_ ## TYPE ## _t * element, \
hc_ ## TYPE ## _t **found) \
{ \
foreach_type(hc_ ## TYPE ## _t, x, data) { \
- if (hc_ ## TYPE ## _cmp(x, element) >= 0) { \
+ if (hc_ ## TYPE ## _cmp(x, element) == 0) { \
*found = x; \
return 0; \
} \
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
new file mode 100644
index 000000000..f67cccf93
--- /dev/null
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
@@ -0,0 +1,46 @@
+/*
+ * 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 route.h
+ * \brief hICN route
+ */
+#ifndef HICN_ROUTE_H
+#define HICN_ROUTE_H
+
+#include <hicn/util/ip_address.h>
+
+typedef u8 face_id_t;
+typedef u16 route_cost_t;
+
+typedef struct hicn_route_s hicn_route_t;
+
+#define MAXSZ_ROUTE_ MAXSZ_PREFIX + 3 + MAXSZ_COST
+#define MAXSZ_ROUTE MAXSZ_ROUTE_ + NULLTERM
+
+hicn_route_t * hicn_route_create(ip_prefix_t * prefix, face_id_t face_id, route_cost_t cost);
+void hicn_route_free(hicn_route_t * route);
+
+int hicn_route_cmp(const hicn_route_t * route1, const hicn_route_t * route2);
+
+int hicn_route_get_prefix(const hicn_route_t * route, ip_prefix_t * prefix);
+int hicn_route_set_prefix(hicn_route_t * route, const ip_prefix_t prefix);
+
+int hicn_route_get_cost(const hicn_route_t * route, int * cost);
+int hicn_route_set_cost(hicn_route_t * route, const int cost);
+
+size_t hicn_route_snprintf(char * s, size_t size, const hicn_route_t * route);
+
+#endif
diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt
index 4708595e0..670e79f05 100644
--- a/ctrl/libhicnctrl/src/CMakeLists.txt
+++ b/ctrl/libhicnctrl/src/CMakeLists.txt
@@ -30,6 +30,7 @@ set(UTIL_HEADER_FILES
set(SOURCE_FILES
api.c
face.c
+ route.c
util/log.c
)
diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c
index 2955e2e71..e6fdb4120 100644
--- a/ctrl/libhicnctrl/src/api.c
+++ b/ctrl/libhicnctrl/src/api.c
@@ -36,6 +36,8 @@
#define PORT 9695
+#define INT_CMP(x, y) ((x > y) ? 1 : (x < y) ? -1 : 0)
+
/*
* Internal state associated to a pending request
*/
@@ -1086,13 +1088,29 @@ hc_listener_validate(const hc_listener_t * listener)
int
hc_listener_cmp(const hc_listener_t * l1, const hc_listener_t * l2)
{
- return ((l1->type == l2->type) &&
- (l1->family == l2->family) &&
- (strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN) == 0) &&
- (ip_address_cmp(&l1->local_addr, &l2->local_addr, l1->family) == 0) &&
- (l1->local_port == l2->local_port))
- ? 0
- : -1;
+ int rc;
+
+ rc = INT_CMP(l1->type, l2->type);
+ if (rc != 0)
+ return rc;
+
+ rc = INT_CMP(l1->family, l2->family);
+ if (rc != 0)
+ return rc;
+
+ rc = strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN);
+ if (rc != 0)
+ return rc;
+
+ rc = ip_address_cmp(&l1->local_addr, &l2->local_addr, l1->family);
+ if (rc != 0)
+ return rc;
+
+ rc = INT_CMP(l1->local_port, l2->local_port);
+ if (rc != 0)
+ return rc;
+
+ return rc;
}
/* LISTENER PARSE */
@@ -1360,14 +1378,37 @@ hc_connection_validate(const hc_connection_t * connection)
*/
int hc_connection_cmp(const hc_connection_t * c1, const hc_connection_t * c2)
{
- return ((c1->type == c2->type) &&
- (c1->family == c2->family) &&
- (ip_address_cmp(&c1->local_addr, &c2->local_addr, c1->family) == 0) &&
- (c1->local_port == c2->local_port) &&
- (ip_address_cmp(&c1->remote_addr, &c2->remote_addr, c1->family) == 0) &&
- (c1->remote_port == c2->remote_port))
- ? 0
- : -1;
+ int rc;
+
+ rc = INT_CMP(c1->type, c2->type);
+ if (rc != 0)
+ return rc;
+
+ rc = INT_CMP(c1->family, c2->family);
+ if (rc != 0)
+ return rc;
+
+ rc = strncmp(c1->interface_name, c2->interface_name, INTERFACE_LEN);
+ if (rc != 0)
+ return rc;
+
+ rc = ip_address_cmp(&c1->local_addr, &c2->local_addr, c1->family);
+ if (rc != 0)
+ return rc;
+
+ rc = INT_CMP(c1->local_port, c2->local_port);
+ if (rc != 0)
+ return rc;
+
+ rc = ip_address_cmp(&c1->remote_addr, &c2->remote_addr, c1->family);
+ if (rc != 0)
+ return rc;
+
+ rc = INT_CMP(c1->remote_port, c2->remote_port);
+ if (rc != 0)
+ return rc;
+
+ return rc;
}
/* CONNECTION PARSE */
@@ -2350,12 +2391,25 @@ int hc_punting_validate(const hc_punting_t * punting)
int hc_punting_cmp(const hc_punting_t * p1, const hc_punting_t * p2)
{
- return ((p1->face_id == p2->face_id) &&
- (p1->family == p2->family) &&
- (ip_address_cmp(&p1->prefix, &p2->prefix, p1->family) == 0) &&
- (p1->prefix_len == p2->prefix_len))
- ? 0
- : -1;
+ int rc;
+
+ rc = INT_CMP(p1->face_id, p2->face_id);
+ if (rc != 0)
+ return rc;
+
+ rc = INT_CMP(p1->family, p2->family);
+ if (rc != 0)
+ return rc;
+
+ rc = ip_address_cmp(&p1->prefix, &p2->prefix, p1->family);
+ if (rc != 0)
+ return rc;
+
+ rc = INT_CMP(p1->prefix_len, p2->prefix_len);
+ if (rc != 0)
+ return rc;
+
+ return rc;
}
int hc_punting_parse(void * in, hc_punting_t * punting)
diff --git a/ctrl/libhicnctrl/src/route.c b/ctrl/libhicnctrl/src/route.c
new file mode 100644
index 000000000..61434871b
--- /dev/null
+++ b/ctrl/libhicnctrl/src/route.c
@@ -0,0 +1,98 @@
+/*
+ * 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 route.c
+ * \brief Implementation of hICN route
+ */
+
+#include <hicn/hicn.h>
+#include <hicn/ctrl/route.h>
+#include <hicn/util/ip_address.h>
+
+#define DEFAULT_HICN_ROUTE_COST 1
+
+struct hicn_route_s {
+ ip_prefix_t prefix;
+ face_id_t face_id;
+ route_cost_t cost; /* Optional, 0 means no value, defaults to 1 */
+};
+
+hicn_route_t *
+hicn_route_create(ip_prefix_t * prefix, face_id_t face_id, route_cost_t cost)
+{
+ hicn_route_t * route = malloc(sizeof(hicn_route_t));
+ if (!route)
+ return NULL;
+ route->prefix = *prefix;
+ route->face_id = face_id;
+ route->cost = cost != 0 ? cost : DEFAULT_HICN_ROUTE_COST;
+
+ return route;
+}
+
+void hicn_route_free(hicn_route_t * route)
+{
+ free(route);
+}
+
+int
+hicn_route_cmp(const hicn_route_t * route1, const hicn_route_t * route2)
+{
+ int rc;
+ rc = ip_prefix_cmp(&route1->prefix, &route2->prefix);
+ if (rc != 0)
+ return rc;
+
+ return (route1->face_id > route2->face_id) ? 1 :
+ (route1->face_id < route2->face_id) ? -1 : 0;
+}
+
+int
+hicn_route_get_prefix(const hicn_route_t * route, ip_prefix_t * prefix)
+{
+ *prefix = route->prefix;
+ return 0;
+}
+
+int
+hicn_route_set_prefix(hicn_route_t * route, const ip_prefix_t prefix)
+{
+ route->prefix = prefix;
+ return 0;
+}
+
+int
+hicn_route_get_cost(const hicn_route_t * route, int * cost)
+{
+ *cost = route->cost;
+ return 0;
+}
+
+int
+hicn_route_set_cost(hicn_route_t * route, const int cost)
+{
+ route->cost = cost;
+ return 0;
+}
+
+/* /!\ Please update constants in header file upon changes */
+size_t
+hicn_route_snprintf(char * s, size_t size, const hicn_route_t * route)
+{
+ char prefix_s[MAXSZ_PREFIX];
+ ip_prefix_ntop(&route->prefix, prefix_s, MAXSZ_PREFIX);
+ return snprintf(s, size, "%s [%d]", prefix_s, route->cost);
+}
diff --git a/lib/includes/hicn/util/ip_address.h b/lib/includes/hicn/util/ip_address.h
index 33c0d9ab5..d9dea8faa 100644
--- a/lib/includes/hicn/util/ip_address.h
+++ b/lib/includes/hicn/util/ip_address.h
@@ -148,7 +148,7 @@ int ip_prefix_ntop (const ip_prefix_t * ip_prefix, char *dst, size_t size);
int ip_prefix_len (const ip_prefix_t * prefix);
bool ip_prefix_empty (const ip_prefix_t * prefix);
int ip_prefix_to_sockaddr(const ip_prefix_t * prefix, struct sockaddr *sa);
-
+int ip_prefix_cmp(const ip_prefix_t * prefix1, const ip_prefix_t * prefix2);
/* URL */
diff --git a/lib/src/util/ip_address.c b/lib/src/util/ip_address.c
index 938c0e49d..062ff8c75 100644
--- a/lib/src/util/ip_address.c
+++ b/lib/src/util/ip_address.c
@@ -179,7 +179,16 @@ ip_address_to_sockaddr(const ip_address_t * ip_address,
int
ip_address_cmp(const ip_address_t * ip1, const ip_address_t * ip2, int family)
{
- return memcmp(ip1, ip2, ip_address_len(family));
+ switch(family) {
+ case AF_INET:
+ return memcmp(&ip1->v4, &ip2->v4, sizeof(ip1->v4));
+ break;
+ case AF_INET6:
+ return memcmp(&ip1->v6, &ip2->v6, sizeof(ip1->v6));
+ break;
+ default:
+ return memcmp(ip1, ip2, sizeof(ip_address_t));
+ }
}
int
@@ -312,13 +321,29 @@ ip_prefix_empty (const ip_prefix_t * prefix)
return prefix->len == 0;
}
-int ip_prefix_to_sockaddr(const ip_prefix_t * prefix,
+int
+ip_prefix_to_sockaddr(const ip_prefix_t * prefix,
struct sockaddr *sa)
{
// XXX assert len == ip_address_len
return ip_address_to_sockaddr(&prefix->address, sa, prefix->family);
}
+int
+ip_prefix_cmp(const ip_prefix_t * prefix1, const ip_prefix_t * prefix2)
+{
+ if (prefix1->family < prefix2->family)
+ return -1;
+ else if (prefix1->family > prefix2->family)
+ return 1;
+
+ if (prefix1->len < prefix2->len)
+ return -1;
+ else if (prefix1->len > prefix2->len)
+ return 1;
+
+ return ip_address_cmp(&prefix1->address, &prefix2->address, prefix1->family);
+}
/* URL */