From 955e71001bd6d360805d2b33a9e6b9d6fd17397f Mon Sep 17 00:00:00 2001 From: Jordan Augé Date: Tue, 5 Nov 2019 14:18:34 +0100 Subject: [HICN-376] Add manual connection/route setting to face manager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I5c24f687e8e815d0e2f437ff8ce7fbb2c76e0579 Signed-off-by: Jordan Augé --- ctrl/facemgr/CMakeLists.txt | 5 + ctrl/facemgr/includes/hicn/facemgr/cfg.h | 62 +---- ctrl/facemgr/includes/hicn/facemgr/facelet.h | 67 ++++- ctrl/facemgr/src/CMakeLists.txt | 4 + ctrl/facemgr/src/api.c | 271 ++++++++++++++++----- ctrl/facemgr/src/cfg.c | 75 +++++- ctrl/facemgr/src/cfg_file.c | 182 ++++++++++++++ ctrl/facemgr/src/facelet.c | 191 ++++++++++++++- ctrl/facemgr/src/facelet_array.c | 26 ++ ctrl/facemgr/src/facelet_array.h | 29 +++ .../facemgr/src/interfaces/hicn_light/hicn_light.c | 121 +++++---- ctrl/facemgr/src/interfaces/netlink/netlink.c | 13 +- ctrl/facemgr/src/util/array.h | 199 +++++++++++++++ ctrl/libhicnctrl/includes/CMakeLists.txt | 3 +- ctrl/libhicnctrl/includes/hicn/ctrl/api.h | 2 +- ctrl/libhicnctrl/includes/hicn/ctrl/route.h | 46 ++++ ctrl/libhicnctrl/src/CMakeLists.txt | 1 + ctrl/libhicnctrl/src/api.c | 96 ++++++-- ctrl/libhicnctrl/src/route.c | 98 ++++++++ lib/includes/hicn/util/ip_address.h | 2 +- lib/src/util/ip_address.c | 29 ++- 21 files changed, 1317 insertions(+), 205 deletions(-) create mode 100644 ctrl/facemgr/src/facelet_array.c create mode 100644 ctrl/facemgr/src/facelet_array.h create mode 100644 ctrl/facemgr/src/util/array.h create mode 100644 ctrl/libhicnctrl/includes/hicn/ctrl/route.h create mode 100644 ctrl/libhicnctrl/src/route.c 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 +#include #include -/* 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 #include -#include +#include #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 d3c62e527..452730134 100644 --- a/ctrl/facemgr/src/api.c +++ b/ctrl/facemgr/src/api.c @@ -28,6 +28,7 @@ #include #include +#include #include #ifdef __APPLE__ @@ -45,6 +46,7 @@ #include #include #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(" "); - facelet_cache_dump(&facemgr->facelet_cache); + facelet_set_dump(facemgr->facelet_cache); DEBUG(" "); DEBUG("", 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; } @@ -1669,10 +1818,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 */ @@ -1720,7 +1869,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; @@ -1740,7 +1889,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 #include #include +#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 // access #include + +#include + #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 #include #include +#include #include #include #include +#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); @@ -390,6 +464,42 @@ facelet_cmp(const facelet_t * f1, const facelet_t * f2) (diff < 0) ? -1 : 0; } +/* + * If the match has a field set, then the facelet only matches iif it has the + * same field set, and both values are equal + */ +#define 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 @@ -400,14 +510,16 @@ do { 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; } @@ -780,6 +906,24 @@ facelet_set_event(facelet_t * facelet, facelet_event_t event) facelet->event = 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) { @@ -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 +#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 + +#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 +#include +#include // log2 +#include // 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 + +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 +#include +#include + +#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 */ -- cgit 1.2.3-korg