diff options
Diffstat (limited to 'hicn-light')
99 files changed, 2835 insertions, 6312 deletions
diff --git a/hicn-light/CMakeLists.txt b/hicn-light/CMakeLists.txt index 241cae7f2..337e22b7f 100644 --- a/hicn-light/CMakeLists.txt +++ b/hicn-light/CMakeLists.txt @@ -93,7 +93,6 @@ else() ${LIBHICNCTRL_STATIC} ) else () - message("qui2!!!") set(HICN_LIBRARIES ${LIBHICN_SHARED} ${LIBHICNCTRL_SHARED} diff --git a/hicn-light/src/hicn/CMakeLists.txt b/hicn-light/src/hicn/CMakeLists.txt index 401ae84eb..feaac5c39 100644 --- a/hicn-light/src/hicn/CMakeLists.txt +++ b/hicn-light/src/hicn/CMakeLists.txt @@ -61,7 +61,8 @@ endif() # Compiler options ############################################################## set(COMPILER_OPTIONS - ${DEFAULT_COMPILER_OPTIONS} + PRIVATE ${DEFAULT_COMPILER_OPTIONS} + #PRIVATE "-Wno-address-of-packed-member" ) ############################################################## diff --git a/hicn-light/src/hicn/cli/hicnc.c b/hicn-light/src/hicn/cli/hicnc.c index 3074016c5..b4a6e8191 100644 --- a/hicn-light/src/hicn/cli/hicnc.c +++ b/hicn-light/src/hicn/cli/hicnc.c @@ -22,13 +22,23 @@ #endif #include "color.h" -#include "../config/parse.h" +#include <hicn/ctrl/parse.h> +#include <hicn/ctrl/hicn-light.h> #include <hicn/util/log.h> #include <hicn/util/sstrncpy.h> -#include <hicn/ctrl/hicn-light-ng.h> #define PORT 9695 +/* + * Duplicated from hicn_light_ng_api.c while is only available as a module in + * libhicnctrl + */ +const char *command_type_str[] = { +#define _(l, u) [COMMAND_TYPE_##u] = STRINGIZE(u), + foreach_command_type +#undef _ +}; + static struct option longFormOptions[] = {{"help", no_argument, 0, 'h'}, {"server", required_argument, 0, 'S'}, {"port", required_argument, 0, 'P'}, @@ -50,6 +60,55 @@ void signal_handler(int sig) { stop = true; } +#if 0 +int hc_active_interface_snprintf(char *buf, size_t size, + hc_event_active_interface_update_t *event) { + int rc; + char *pos = buf; + + rc = ip_prefix_snprintf(pos, size, &event->prefix); + if ((rc < 0) || (rc >= size)) return rc; + pos += rc; + size -= rc; + + for (netdevice_type_t type = NETDEVICE_TYPE_UNDEFINED + 1; + type < NETDEVICE_TYPE_N; type++) { + if (!netdevice_flags_has(event->interface_type, type)) continue; + rc = snprintf(pos, size, " %s", netdevice_type_str(type)); + if ((rc < 0) || (rc >= size)) return pos - buf + rc; + + pos += rc; + size -= rc; + } + return pos - buf; +} + +// XXX hc_object_snprintf +void hc_subscription_display(command_type_t command_type, + const uint8_t *buffer) { + char buf[65535]; + + switch (command_type) { + case COMMAND_TYPE_CONNECTION_ADD: + case COMMAND_TYPE_CONNECTION_REMOVE: + case COMMAND_TYPE_CONNECTION_UPDATE: + hc_connection_snprintf(buf, sizeof(buf), (hc_connection_t *)buffer); + break; + case COMMAND_TYPE_ACTIVE_INTERFACE_UPDATE: + hc_active_interface_snprintf( + buf, sizeof(buf), (hc_event_active_interface_update_t *)buffer); + break; + case COMMAND_TYPE_ROUTE_LIST: + hc_route_snprintf(buf, sizeof(buf), (hc_route_t *)buffer); + break; + default: + INFO("Unknown event received"); + return; + } + INFO("%s %s", command_type_str(command_type), buf); +} +#endif + int main(int argc, char *const *argv) { log_conf.log_level = LOG_INFO; @@ -149,13 +208,13 @@ int main(int argc, char *const *argv) { #define BUFSIZE 255 char url[BUFSIZE]; snprintf(url, BUFSIZE, "tcp://%s:%d/", server_ip, server_port); - s = hc_sock_create_forwarder_url(HICNLIGHT_NG, url); + s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, url); } else { - s = hc_sock_create_forwarder(HICNLIGHT_NG); + s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL); } if (!s) { fprintf(stderr, "Could not create socket.\n"); - goto ERR_SOCK; + goto ERR_SOCKET; } if (hc_sock_connect(s) < 0) { @@ -163,7 +222,7 @@ int main(int argc, char *const *argv) { goto ERR_CONNECT; } - if (!IS_VALID_OBJECT_TYPE(command.object.type) || + if (!IS_VALID_OBJECT_TYPE(command.object_type) || !IS_VALID_ACTION(command.action)) { fprintf(stderr, "Unsupported command"); goto ERR_PARAM; @@ -171,285 +230,54 @@ int main(int argc, char *const *argv) { int rc = UNSUPPORTED_CMD_ERROR; hc_data_t *data = NULL; - char buf_listener[MAXSZ_HC_LISTENER]; - char buf_connection[MAXSZ_HC_CONNECTION]; - char buf_route[MAXSZ_HC_ROUTE]; - char buf[MAX_LEN]; - switch (command.object.type) { - case OBJECT_ROUTE: - switch (command.action) { - case ACTION_CREATE: - rc = hc_route_create(s, &command.object.route); - break; - - case ACTION_DELETE: - rc = hc_route_delete(s, &command.object.route); - break; - - case ACTION_LIST: - rc = hc_route_list(s, &data); - if (rc < 0) break; - - INFO("Routes:"); - foreach_route(r, data) { - if (hc_route_snprintf(buf_route, MAXSZ_HC_ROUTE, r) >= - MAXSZ_HC_ROUTE) - ERROR("Display error"); - INFO("%s", buf_route); - } - break; - - default: - break; - } - break; - - case OBJECT_LISTENER: - switch (command.action) { - case ACTION_CREATE: - rc = hc_listener_create(s, &command.object.listener); - break; - - case ACTION_DELETE: - rc = hc_listener_delete(s, &command.object.listener); - break; - - case ACTION_LIST: - rc = hc_listener_list(s, &data); - if (rc < 0) break; - - INFO("Listeners:"); - foreach_listener(l, data) { - if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER + 17, l) >= - MAXSZ_HC_LISTENER) - ERROR("Display error"); - INFO("[%d] %s", l->id, buf_listener); - } - break; - - default: - break; - } - break; - - case OBJECT_CONNECTION: - switch (command.action) { - case ACTION_CREATE: - rc = hc_connection_create(s, &command.object.connection); - break; - - case ACTION_DELETE: - rc = hc_connection_delete(s, &command.object.connection); - break; - - case ACTION_LIST: - rc = hc_connection_list(s, &data); - if (rc < 0) break; - - INFO("Connections:"); - foreach_connection(c, data) { - if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION, - c) >= MAXSZ_HC_CONNECTION) - ERROR("Display error"); - INFO("[%d] %s", c->id, buf_connection); - } - break; - - default: - break; - } - break; - - case OBJECT_CACHE: - switch (command.action) { - case ACTION_SERVE: - rc = hc_cache_set_serve(s, &command.object.cache); - break; - - case ACTION_STORE: - rc = hc_cache_set_store(s, &command.object.cache); - break; - - case ACTION_CLEAR: - rc = hc_cache_clear(s, &command.object.cache); - break; - - case ACTION_LIST: - rc = hc_cache_list(s, &data); - if (rc < 0) break; - - hc_cache_snprintf(buf, MAX_LEN, (hc_cache_info_t *)data->buffer); - printf("%s\n", buf); - break; - - default: - break; - } - break; - - case OBJECT_STRATEGY: - switch (command.action) { - case ACTION_SET: - rc = hc_strategy_set(s, &command.object.strategy); - break; - - default: - break; - } - break; - case OBJECT_MAPME: - switch (command.action) { - case ACTION_UPDATE: - rc = hc_mapme_send_update(s, &command.object.mapme); - break; - case ACTION_SET: - if (command.object.mapme.target == MAPME_TARGET_ENABLE) { - rc = hc_mapme_set(s, &command.object.mapme); - } else if (command.object.mapme.target == MAPME_TARGET_DISCOVERY) { - rc = hc_mapme_set_discovery(s, &command.object.mapme); - } else if (command.object.mapme.target == MAPME_TARGET_TIMESCALE) { - rc = hc_mapme_set_timescale(s, &command.object.mapme); - } else if (command.object.mapme.target == MAPME_TARGET_RETX) { - rc = hc_mapme_set_retx(s, &command.object.mapme); - } - break; - - default: - break; - } - break; - - case OBJECT_LOCAL_PREFIX: - switch (command.action) { - case ACTION_CREATE: - rc = hc_strategy_add_local_prefix(s, &command.object.strategy); - break; - - default: - break; - } - break; - - case OBJECT_SUBSCRIPTION: - // Disable socket recv timeout - hc_sock_set_recv_timeout_ms(s, 0); - - rc = hc_subscription_create(s, &command.object.subscription); - if (rc < 0) break; - INFO("Subscription sent"); - - while (!stop) { - int rc = hc_sock_callback(s, &data); - if (rc < 0 && !stop) ERROR("Notification error"); - - if (!stop) { - event_type_t event_type = rc; - INFO("Notification recevied %s [%d]", event_str(event_type), - event_type); - - if (event_type == EVENT_INTERFACE_UPDATE) { - hc_event_interface_update_t *event = - (hc_event_interface_update_t *)(data->buffer); - INFO("Interface update event received: %u", event->interface_type); - } - } - } - - INFO("Unsubscribing..."); - rc = hc_subscription_delete(s, &command.object.subscription); - break; - - case OBJECT_STATS: - switch (command.action) { - case ACTION_GET: - rc = hc_stats_get(s, &data); - if (rc < 0) break; - - hc_stats_snprintf(buf, MAX_LEN, (hicn_light_stats_t *)data->buffer); - INFO("\n%s", buf); - break; - - case ACTION_LIST: - rc = hc_stats_list(s, &data); - if (rc < 0) break; - - cmd_stats_list_item_t *conn_stats = - (cmd_stats_list_item_t *)data->buffer; - cmd_stats_list_item_t *end = - (cmd_stats_list_item_t *)(data->buffer + - data->size * data->out_element_size); - while (conn_stats < end) { - INFO("Connection #%d:", conn_stats->id); - INFO("\tinterests received: %d pkts (%d bytes)", - conn_stats->stats.interests.rx_pkts, - conn_stats->stats.interests.rx_bytes); - INFO("\tinterests transmitted: %d pkts (%d bytes)", - conn_stats->stats.interests.tx_pkts, - conn_stats->stats.interests.tx_bytes); - INFO("\tdata received: %d pkts (%d bytes)", - conn_stats->stats.data.rx_pkts, - conn_stats->stats.data.rx_bytes); - INFO("\tdata transmitted: %d pkts (%d bytes)", - conn_stats->stats.data.tx_pkts, - conn_stats->stats.data.tx_bytes); - - conn_stats++; - } - break; - - default: - break; - } - break; + rc = hc_execute(s, command.action, command.object_type, &command.object, + &data); -#ifdef TEST_FACE_CREATION - case OBJECT_FACE: - switch (command.action) { - case ACTION_CREATE: { - hc_face_t face = {0}; - face.face.type = FACE_TYPE_UDP; - face.face.family = AF_INET; - face.face.local_addr = IPV4_LOOPBACK; - face.face.remote_addr = IPV4_LOOPBACK; - face.face.local_port = 9696; - face.face.remote_port = 9696; - - rc = hc_face_create(s, &face); - break; - } - default: - break; - } - break; -#endif - - default: - break; + if (rc < 0) { + switch (rc) { + case INPUT_ERROR: + ERROR("Wrong input parameters"); + break; + case UNSUPPORTED_CMD_ERROR: + ERROR("Unsupported command"); + break; + default: + ERROR("Error executing command"); + break; + } + goto ERR_COMMAND; } - hc_data_free(data); - if (rc < -1) { - if (rc == INPUT_ERROR) ERROR("Wrong input parameters"); - if (rc == UNSUPPORTED_CMD_ERROR) ERROR("Unsupported command"); - goto ERR_CMD; + if (!data) goto ERR_QUERY; + if (!hc_data_get_result(data)) goto ERR_DATA; + + if (command.action == ACTION_LIST) { + char buf[MAXSZ_HC_OBJECT]; + hc_data_foreach(data, obj, { + rc = hc_object_snprintf(buf, MAXSZ_HC_OBJECT, command.object_type, obj); + if (rc < 0) + WARN("Display error"); + else if (rc >= MAXSZ_HC_OBJECT) + WARN("Output truncated"); + else + printf("%s\n", buf); + }); } - if (rc < 0) ERROR("Error executing command"); - // Remove the connection created to send the command - command.object.connection.id = 0; - rc = strcpy_s(command.object.connection.name, - sizeof(command.object.connection.name), "SELF"); - if (rc != EOK || hc_connection_delete(s, &command.object.connection) < 0) - fprintf(stderr, "Error removing local connection to forwarder\n"); - - exit(EXIT_SUCCESS); + hc_data_free(data); + hc_sock_free(s); + return EXIT_SUCCESS; -ERR_CMD: +ERR_DATA: + hc_data_free(data); +ERR_QUERY: +ERR_COMMAND: ERR_CONNECT: hc_sock_free(s); -ERR_SOCK: +ERR_SOCKET: ERR_PARSE: ERR_PARAM: - exit(EXIT_FAILURE); + ERROR("Error"); + return EXIT_FAILURE; } diff --git a/hicn-light/src/hicn/cli/hicns.c b/hicn-light/src/hicn/cli/hicns.c index 2f7a360f8..fa668062d 100644 --- a/hicn-light/src/hicn/cli/hicns.c +++ b/hicn-light/src/hicn/cli/hicns.c @@ -21,7 +21,7 @@ #endif #include "logo.h" -#include "../config/parse.h" +#include <hicn/ctrl/parse.h> #include <hicn/util/sstrncpy.h> #define PORT 9695 @@ -181,9 +181,9 @@ int main(int argc, char *const *argv) { #define BUFSIZE 255 char url[BUFSIZE]; snprintf(url, BUFSIZE, "tcp://%s:%d/", server_ip, server_port); - s = hc_sock_create_forwarder_url(HICNLIGHT_NG, url); + s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, url); } else { - s = hc_sock_create_forwarder(HICNLIGHT_NG); + s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL); } if (!s) { fprintf(stderr, "Could not create socket.\n"); diff --git a/hicn-light/src/hicn/config/CMakeLists.txt b/hicn-light/src/hicn/config/CMakeLists.txt index 90d0a2229..b1b04d679 100644 --- a/hicn-light/src/hicn/config/CMakeLists.txt +++ b/hicn-light/src/hicn/config/CMakeLists.txt @@ -13,28 +13,32 @@ list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/configuration.h - ${CMAKE_CURRENT_SOURCE_DIR}/command.h ${CMAKE_CURRENT_SOURCE_DIR}/commands.h - ${CMAKE_CURRENT_SOURCE_DIR}/parse.h ) list(APPEND SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/module_object.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/connection.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/listener.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/face.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/route.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/strategy.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/subscription.c ${CMAKE_CURRENT_SOURCE_DIR}/configuration.c ${CMAKE_CURRENT_SOURCE_DIR}/configuration_file.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_cache.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_connection.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_face.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_listener.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_mapme.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_policy.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_punting.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_route.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_stats.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_strategy.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_subscription.c - ${CMAKE_CURRENT_SOURCE_DIR}/command.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_cache.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_connection.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_face.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_listener.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_mapme.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_policy.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_punting.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_route.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_stats.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_strategy.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_subscription.c ${CMAKE_CURRENT_SOURCE_DIR}/commands.c - ${CMAKE_CURRENT_SOURCE_DIR}/parse.c ) set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) diff --git a/hicn-light/src/hicn/config/command.c b/hicn-light/src/hicn/config/command.c deleted file mode 100644 index bee0d2663..000000000 --- a/hicn-light/src/hicn/config/command.c +++ /dev/null @@ -1,119 +0,0 @@ - -/** - * @file command.c - * @brief Implementation of commands. - */ - -#include <search.h> /* tfind, tdestroy, twalk */ -#include <stdio.h> -#include <ctype.h> -#include "command.h" -#include "parse.h" - -/* Commands are registered in the following tree. */ -static void *commands_root = NULL; /**< Tree ordered by name */ - -#ifdef __linux__ -static void nothing_to_free() {} - -__attribute__((destructor)) static void command_clear() { - tdestroy(commands_root, nothing_to_free); -} -#endif /* __linux__ */ - -static int _command_compare(const command_parser_t *c1, - const command_parser_t *c2) { - if (c1->object != c2->object) return c2->object - c1->object; - if (c1->action != c2->action) return c2->action - c1->action; - if (c1->nparams != c2->nparams) return c2->nparams - c1->nparams; - return 0; -} - -#define command_compare (int (*)(const void *, const void *))(_command_compare) - -void command_register(const command_parser_t *command) { - // Insert the command in the tree if the keys does not exist yet - tsearch(command, &commands_root, command_compare); -} - -const command_parser_t *command_search(const hc_action_t action, - hc_object_type_t object, - unsigned nparams) { - command_parser_t **command, search; - - search.action = action; - search.object = object; - search.nparams = nparams; - command = tfind(&search, &commands_root, command_compare); - - return command ? *command : NULL; -} - -static inline void to_lowercase(char *p) { - for (; *p; ++p) *p = tolower(*p); -} - -typedef struct { - hc_object_type_t object; - hc_action_t action; -} cmd_search_params_t; - -static hc_object_type_t prev_obj = OBJECT_UNDEFINED; -static hc_action_t prev_action = ACTION_UNDEFINED; -static void traversal_action(const void *nodep, VISIT which, - void *cmd_params0) { - cmd_search_params_t *cmd_params = cmd_params0; - - // Execute this function during inorder traversal - if (which != postorder && which != leaf) return; - - command_parser_t *datap; - datap = *(command_parser_t **)nodep; - char *obj_str = strdup(object_str(datap->object)); - to_lowercase(obj_str); - - // List all objects - if (cmd_params->object == OBJECT_UNDEFINED && - cmd_params->action == ACTION_UNDEFINED) { - if (datap->object == prev_obj) goto FREE_STR; - prev_obj = datap->object; - - printf("\thelp %s\n", obj_str); - goto FREE_STR; - } - - // List actions for specific object - if (datap->object != cmd_params->object) goto FREE_STR; - if (cmd_params->action == ACTION_UNDEFINED) { - if (datap->action == prev_action) goto FREE_STR; - prev_action = datap->action; - - printf("\thelp %s %s\n", obj_str, action_to_cmd_action(datap->action)); - goto FREE_STR; - } - - // List commands for specific object and action - if (datap->action != cmd_params->action) goto FREE_STR; - printf(" %s %s ", action_to_cmd_action(datap->action), obj_str); - for (int i = 0; i < datap->nparams; i++) - printf("<%s> ", datap->parameters[i].name); - printf("\n\n"); - // List options' details - if (datap->nparams == 0) goto FREE_STR; - for (int i = 0; i < datap->nparams; i++) - printf("%16s: %s\n", datap->parameters[i].name, datap->parameters[i].help); - printf("\n"); - -FREE_STR: - free(obj_str); -} - -void command_list(hc_object_type_t object, hc_action_t action) { -#if defined(__linux__) && !defined(__ANDROID__) - cmd_search_params_t cmd_params = {.object = object, .action = action}; - twalk_r(commands_root, traversal_action, &cmd_params); -#else - fprintf(stderr, "twalk_r() function only available on linux"); - (void)traversal_action; -#endif -} diff --git a/hicn-light/src/hicn/config/command.h b/hicn-light/src/hicn/config/command.h deleted file mode 100644 index 73d8edb1f..000000000 --- a/hicn-light/src/hicn/config/command.h +++ /dev/null @@ -1,179 +0,0 @@ -#ifndef HICNLIGHT_CONFIG_COMMAND -#define HICNLIGHT_CONFIG_COMMAND - -/** - * @file command.h - * @brief Commands. - */ - -#include <stddef.h> // offsetof -#include <hicn/util/ip_address.h> - -#include <hicn/ctrl/api.h> - -/* Update sscanf accordingly in parse_cmd.c */ -#define MAX_PARAMETERS 10 -#define MAX_SCANF_PARAM_LEN 100 - -typedef int (*parser_hook_t)(void *arg); - -typedef enum { - TYPENAME_UNDEFINED, - TYPENAME_INT, - TYPENAME_UINT, - TYPENAME_STR, - TYPENAME_SYMBOLIC_OR_ID, - TYPENAME_INTERFACE_NAME, - TYPENAME_IP_ADDRESS, - TYPENAME_IP_PREFIX, - TYPENAME_ON_OFF, - TYPENAME_ENUM, - TYPENAME_POLICY_STATE, -} parser_typename_t; - -typedef struct { - parser_typename_t name; - union { - struct { - size_t max_size; - } str; - struct { - int min; - int max; - } sint; - struct { - int min; - int max; - } uint; - struct { - int (*from_str)(const char *str); - } enum_; - struct { - policy_tag_t tag; - } policy_state; - }; -} parser_type_t; - -typedef struct { - const char *name; - const char *help; - parser_type_t type; - size_t offset; - /* - * quick hack to let the functions update two or more parameters, like for - * IP_ADDRESS or IP_PREFIX types - */ - size_t offset2; - size_t offset3; -} command_parameter_t; - -typedef struct { - hc_action_t action; - hc_object_type_t object; - unsigned nparams; - command_parameter_t parameters[MAX_PARAMETERS]; - parser_hook_t post_hook; -} command_parser_t; - -#define TYPE_STRN(N) \ - (parser_type_t) { \ - .name = TYPENAME_STR, \ - .str = { \ - .max_size = N, \ - }, \ - } -#define TYPE_FMT_STRN(N) "%s" - -#define TYPE_INT(MIN, MAX) \ - (parser_type_t) { \ - .name = TYPENAME_INT, \ - .sint = { \ - .min = (MIN), \ - .max = (MAX), \ - }, \ - } -#define TYPE_FMT_INT "%d" - -#define TYPE_UINT(min, max) \ - (parser_type_t) { \ - .name = TYPENAME_UINT, \ - .uint = { \ - .min = min, \ - .max = max, \ - }, \ - } -#define TYPE_FMT_UINT "%u" - -#define TYPE_SYMBOLIC_OR_ID TYPE_STRN(SYMBOLIC_NAME_LEN) -#define TYPE_FMT_SYMBOLIC_OR_ID "%s" - -#define TYPE_INTERFACE_NAME TYPE_STRN(INTERFACE_LEN) -#define TYPE_FMT_INTERFACE_NAME "%s" - -#define TYPE_IP_ADDRESS \ - (parser_type_t) { .name = TYPENAME_IP_ADDRESS, } -#define TYPE_FMT_IP_ADDRESS "%s" - -#define TYPE_IP_PREFIX \ - (parser_type_t) { .name = TYPENAME_IP_PREFIX, } -#define TYPE_FMT_IP_PREFIX "%s" - -#define TYPE_ON_OFF \ - (parser_type_t) { .name = TYPENAME_ON_OFF, } -#define TYPE_FMT_ON_OFF "%s" - -#define TYPE_ENUM(x) \ - (parser_type_t) { \ - .name = TYPENAME_ENUM, \ - .enum_ = { \ - .from_str = (int (*)(const char *))x##_from_str, \ - }, \ - } -/* We need to allocate room for the intermediate string */ -#define TYPE_FMT_ENUM "%s" - -#define TYPE_POLICY_STATE(TAG) \ - (parser_type_t) { \ - .name = TYPENAME_POLICY_STATE, \ - .policy_state = { \ - .tag = TAG, \ - }, \ - } -/* We need to allocate room for the intermediate string */ -#define TYPE_FMT_POLICY_STATE "%s" - -/** - * \brief Register a protocol - * \param protocol Pointer to a protocol_t structure describing the protocol to - * register \return None - */ - -void command_register(const command_parser_t *command); - -/** - * \brief Search a registered protocol in the library according to its name - * \param[in] action The action of the command. - * \param[in] object The object of the command. - * \param[in] nparams The number of parameters expected in the command. - * \return A pointer to the corresponding command if any, NULL othewise - */ -const command_parser_t *command_search(hc_action_t action, - hc_object_type_t object, - unsigned nparams); - -/** - * @brief List the commands associated with the specified object and/or action. - * Use OBJECT_UNDEFINED and ACTION_UNDEFINED to list all the available objects. - * Use ACTION_UNDEFINED to list all the actions associated to the specified - * object. - * - * @param object The action of the command - * @param action The object of the command - */ -void command_list(hc_object_type_t object, hc_action_t action); - -#define COMMAND_REGISTER(MOD) \ - static void __init_##MOD(void) __attribute__((constructor)); \ - static void __init_##MOD(void) { command_register(&MOD); } - -#endif /* HICNLIGHT_CONFIG_COMMAND */ diff --git a/hicn-light/src/hicn/config/command_cache.c b/hicn-light/src/hicn/config/command_cache.c deleted file mode 100644 index 073221cf0..000000000 --- a/hicn-light/src/hicn/config/command_cache.c +++ /dev/null @@ -1,54 +0,0 @@ -#include <math.h> -#include "command.h" - -/* Parameters */ - -#define serve \ - { \ - .name = "serve", \ - .help = \ - "Enables/disables replies from local content store. Either the " \ - "string 'on' or 'off'", \ - .type = TYPE_ON_OFF, .offset = offsetof(hc_cache_t, serve), \ - } - -#define store \ - { \ - .name = "store", \ - .help = \ - "enables/disables the storage of incoming data packets in the local " \ - "content store. Either the string 'on' or 'off'", \ - .type = TYPE_ON_OFF, .offset = offsetof(hc_cache_t, store), \ - } - -/* Commands */ - -static const command_parser_t command_cache_set_serve = { - .action = ACTION_SERVE, - .object = OBJECT_CACHE, - .nparams = 1, - .parameters = {serve}, -}; -COMMAND_REGISTER(command_cache_set_serve); - -static const command_parser_t command_cache_set_store = { - .action = ACTION_STORE, - .object = OBJECT_CACHE, - .nparams = 1, - .parameters = {store}, -}; -COMMAND_REGISTER(command_cache_set_store); - -static const command_parser_t command_cache_clear = { - .action = ACTION_CLEAR, - .object = OBJECT_CACHE, - .nparams = 0, -}; -COMMAND_REGISTER(command_cache_clear); - -static const command_parser_t command_cache_list = { - .action = ACTION_LIST, - .object = OBJECT_CACHE, - .nparams = 0, -}; -COMMAND_REGISTER(command_cache_list); diff --git a/hicn-light/src/hicn/config/command_connection.c b/hicn-light/src/hicn/config/command_connection.c deleted file mode 100644 index 069bf55a6..000000000 --- a/hicn-light/src/hicn/config/command_connection.c +++ /dev/null @@ -1,128 +0,0 @@ -#include <math.h> -#include "command.h" - -/* Parameters */ - -#define type_hicn \ - { \ - .name = "type", .help = "connection type (hICN)", \ - .type = TYPE_ENUM(face_type), .offset = offsetof(hc_connection_t, type), \ - } - -#define type_tcp_udp \ - { \ - .name = "type", .help = "connection type [tcp | udp]", \ - .type = TYPE_ENUM(face_type), .offset = offsetof(hc_connection_t, type), \ - } - -#define symbolic \ - { \ - .name = "symbolic", \ - .help = "symbolic name, e.g. 'conn1' (must be unique, start with alpha)", \ - .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_connection_t, name), \ - } - -#define local_address \ - { \ - .name = "local_addr", .help = "local IP address on which to bind.", \ - .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_connection_t, local_addr), \ - .offset2 = offsetof(hc_connection_t, family), \ - } - -#define local_port \ - { \ - .name = "local_port", .help = "Local port.", \ - .type = TYPE_INT(1, UINT16_MAX), \ - .offset = offsetof(hc_connection_t, local_port), \ - } - -#define remote_address \ - { \ - .name = "remote_address", \ - .help = "The IPv4 or IPv6 or hostname of the remote system.", \ - .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_connection_t, remote_addr), \ - .offset2 = offsetof(hc_connection_t, family), \ - } - -#define remote_port \ - { \ - .name = "remote_port", .help = "Remote port.", \ - .type = TYPE_INT(1, UINT16_MAX), \ - .offset = offsetof(hc_connection_t, remote_port), \ - } - -#define interface \ - { \ - .name = "interface", .help = "Interface on which to bind", \ - .type = TYPE_INTERFACE_NAME, \ - .offset = offsetof(hc_connection_t, interface_name), \ - } - -#define symbolic_or_id \ - { \ - .name = "symbolic", .help = "The connection symbolic name or id", \ - .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_connection_t, name), \ - } - -/* Commands */ - -int on_connection_create(hc_connection_t* connection) { - connection->admin_state = FACE_STATE_UP; - return 0; -} - -#if 0 -static command_parser_t command_connection_create4 = { - .action = ACTION_CREATE, - .object = OBJECT_CONNECTION, - .nparams = 4, - .parameters = {type_hicn, symbolic, local_address, remote_address}, - .post_hook = (parser_hook_t)on_connection_create, -}; -COMMAND_REGISTER(command_connection_create4); - -static const command_parser_t command_connection_create5 = { - .action = ACTION_CREATE, - .object = OBJECT_CONNECTION, - .nparams = 5, - .parameters = {type_hicn, symbolic, local_address, remote_address, - interface}, - .post_hook = (parser_hook_t)on_connection_create, -}; -COMMAND_REGISTER(command_connection_create5); -#endif - -static const command_parser_t command_connection_create6 = { - .action = ACTION_CREATE, - .object = OBJECT_CONNECTION, - .nparams = 6, - .parameters = {type_tcp_udp, symbolic, remote_address, remote_port, - local_address, local_port}, - .post_hook = (parser_hook_t)on_connection_create, -}; -COMMAND_REGISTER(command_connection_create6); - -static const command_parser_t command_connection_create7 = { - .action = ACTION_CREATE, - .object = OBJECT_CONNECTION, - .nparams = 7, - .parameters = {type_tcp_udp, symbolic, remote_address, remote_port, - local_address, local_port, interface}, - .post_hook = (parser_hook_t)on_connection_create, -}; -COMMAND_REGISTER(command_connection_create7); - -static const command_parser_t command_connection_list = { - .action = ACTION_LIST, - .object = OBJECT_CONNECTION, - .nparams = 0, -}; -COMMAND_REGISTER(command_connection_list); - -static const command_parser_t command_connection_remove = { - .action = ACTION_DELETE, - .object = OBJECT_CONNECTION, - .nparams = 1, - .parameters = {symbolic_or_id}, -}; -COMMAND_REGISTER(command_connection_remove); diff --git a/hicn-light/src/hicn/config/command_face.c b/hicn-light/src/hicn/config/command_face.c deleted file mode 100644 index 95ec404f0..000000000 --- a/hicn-light/src/hicn/config/command_face.c +++ /dev/null @@ -1,16 +0,0 @@ -#if 0 -#include "command.h" - -/* Parameters */ - -/* Commands */ - -// XXX missing add - -static const command_parser_t command_face_list = { - .action = ACTION_LIST, - .object = OBJECT_FACE, - .nparams = 0, -}; -COMMAND_REGISTER(command_face_list); -#endif
\ No newline at end of file diff --git a/hicn-light/src/hicn/config/command_listener.c b/hicn-light/src/hicn/config/command_listener.c deleted file mode 100644 index 8ad7c94be..000000000 --- a/hicn-light/src/hicn/config/command_listener.c +++ /dev/null @@ -1,111 +0,0 @@ -#include <math.h> -#include "command.h" - -/* Parameters */ - -#define protocol_hicn \ - { \ - .name = "protocol", .help = "Protocol [hicn].", \ - .type = TYPE_ENUM(face_type), .offset = offsetof(hc_listener_t, type), \ - } - -#define protocol_tcp_udp \ - { \ - .name = "protocol", .help = "Protocol [tcp | udp]", \ - .type = TYPE_ENUM(face_type), .offset = offsetof(hc_listener_t, type), \ - } - -#define symbolic \ - { \ - .name = "symbolic", \ - .help = \ - "User defined name for listener, must start with alpha and be " \ - "alphanum", \ - .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_listener_t, name), \ - } - -#define local_address \ - { \ - .name = "local_addr", \ - .help = \ - "IPv4 or IPv6 address (or prefix protocol = hicn) assigend to the " \ - "local interface", \ - .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_listener_t, local_addr), \ - .offset2 = offsetof(hc_listener_t, family), \ - } - -#define local_port \ - { \ - .name = "local_port", .help = "Local port.", \ - .type = TYPE_INT(1, UINT16_MAX), \ - .offset = offsetof(hc_listener_t, local_port), \ - } - -#define interface \ - { \ - .name = "interface", .help = "Interface on which to bind", \ - .type = TYPE_INTERFACE_NAME, \ - .offset = offsetof(hc_listener_t, interface_name), \ - } - -#define symbolic_or_id \ - { \ - .name = "symbolic", .help = "The listener symbolic name or id", \ - .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_listener_t, name), \ - } - -/* Commands */ - -/* The parse sets the wrong face_type_t for listener, we fix that here */ -int on_listener_create(hc_listener_t* listener) { - switch (listener->type) { - case FACE_TYPE_UDP: - listener->type = FACE_TYPE_UDP_LISTENER; - break; - case FACE_TYPE_TCP: - listener->type = FACE_TYPE_TCP_LISTENER; - break; - case FACE_TYPE_HICN: - listener->type = FACE_TYPE_HICN_LISTENER; - break; - default: - break; - } - return 0; -} - -#if 0 -static const command_parser_t command_listener_create4 = { - .action = ACTION_CREATE, - .object = OBJECT_LISTENER, - .nparams = 4, - .parameters = {protocol_hicn, symbolic, local_address, interface}, - .post_hook = (parser_hook_t)on_listener_create, -}; -COMMAND_REGISTER(command_listener_create4); -#endif - -static const command_parser_t command_listener_create6 = { - .action = ACTION_CREATE, - .object = OBJECT_LISTENER, - .nparams = 5, - .parameters = {protocol_tcp_udp, symbolic, local_address, local_port, - interface}, - .post_hook = (parser_hook_t)on_listener_create, -}; -COMMAND_REGISTER(command_listener_create6); - -static const command_parser_t command_listener_list = { - .action = ACTION_LIST, - .object = OBJECT_LISTENER, - .nparams = 0, -}; -COMMAND_REGISTER(command_listener_list); - -static const command_parser_t command_listener_remove = { - .action = ACTION_DELETE, - .object = OBJECT_LISTENER, - .nparams = 1, - .parameters = {symbolic_or_id}, -}; -COMMAND_REGISTER(command_listener_remove); diff --git a/hicn-light/src/hicn/config/command_mapme.c b/hicn-light/src/hicn/config/command_mapme.c deleted file mode 100644 index a22e8b340..000000000 --- a/hicn-light/src/hicn/config/command_mapme.c +++ /dev/null @@ -1,59 +0,0 @@ -#include <math.h> -#include "command.h" - -/* Parameters */ - -#define target \ - { \ - .name = "target", \ - .help = \ - "Target for the set action, e.g. enable, discovery, timescale, retx", \ - .type = TYPE_ENUM(mapme_target), .offset = offsetof(hc_mapme_t, target), \ - } - -#define value \ - { \ - .name = "value", \ - .help = "Value to set for the target, e.g. 'on', 'off', milliseconds", \ - .type = TYPE_STRN(4), .offset = offsetof(hc_mapme_t, unparsed_arg), \ - } - -#define prefix \ - { \ - .name = "prefix", \ - .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \ - .type = TYPE_IP_PREFIX, .offset = offsetof(hc_mapme_t, address), \ - .offset2 = offsetof(hc_mapme_t, len), \ - .offset3 = offsetof(hc_mapme_t, family), \ - } - -/* Commands */ - -// Parse the raw string argument into 'timescale' or 'enabled', -// necessary since the command dispatch is based on the number -// of arguments and not their type -int parse_args(hc_mapme_t* mapme) { - mapme->timescale = atoi(mapme->unparsed_arg); - - if (strcasecmp(mapme->unparsed_arg, "off") == 0) mapme->enabled = 0; - if (strcasecmp(mapme->unparsed_arg, "on") == 0) mapme->enabled = 1; - - return 0; -} - -static const command_parser_t command_mapme_set = { - .action = ACTION_SET, - .object = OBJECT_MAPME, - .nparams = 2, - .parameters = {target, value}, - .post_hook = (parser_hook_t)parse_args, -}; -COMMAND_REGISTER(command_mapme_set); - -static const command_parser_t command_mapme_update = { - .action = ACTION_UPDATE, - .object = OBJECT_MAPME, - .nparams = 1, - .parameters = {prefix}, -}; -COMMAND_REGISTER(command_mapme_update);
\ No newline at end of file diff --git a/hicn-light/src/hicn/config/command_policy.c b/hicn-light/src/hicn/config/command_policy.c deleted file mode 100644 index 1e802c3f5..000000000 --- a/hicn-light/src/hicn/config/command_policy.c +++ /dev/null @@ -1,52 +0,0 @@ -#if 0 -#include <hicn/policy.h> - -#include "command.h" - -/* Parameters */ - -#define prefix \ - { \ - .name = "prefix", \ - .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \ - .type = TYPE_IP_PREFIX, .offset = offsetof(hc_policy_t, remote_addr), \ - .offset2 = offsetof(hc_policy_t, len), \ - .offset3 = offsetof(hc_policy_t, family), \ - } - -#define app_name \ - { \ - .name = "app_name", \ - .help = "The application name associated to this policy", \ - .type = TYPE_STR, .offset = offsetof(hc_policy_t, policy.app_name), \ - } - -/* Commands */ - -static const command_parser_t command_policy_create = { - .action = ACTION_CREATE, - .object = OBJECT_POLICY, - .nparams = 2 + POLICY_TAG_N, - .parameters = {prefix, app_name, -#define _(x, y) \ - { \ - .name = "flag:" #x, \ - .help = \ - "A value among [neutral|require|prefer|avoid|prohibit] with an " \ - "optional '!' character prefix for disabling changes", \ - .type = TYPE_POLICY_STATE(POLICY_TAG_##x), \ - .offset = offsetof(hc_policy_t, policy.tags), \ - }, - foreach_policy_tag -#undef _ - }, -}; -COMMAND_REGISTER(command_policy_create); - -static const command_parser_t command_policy_list = { - .action = ACTION_LIST, - .object = OBJECT_POLICY, - .nparams = 0, -}; -COMMAND_REGISTER(command_policy_list); -#endif
\ No newline at end of file diff --git a/hicn-light/src/hicn/config/command_punting.c b/hicn-light/src/hicn/config/command_punting.c deleted file mode 100644 index 8c7a6dec3..000000000 --- a/hicn-light/src/hicn/config/command_punting.c +++ /dev/null @@ -1,40 +0,0 @@ -#if 0 -#include "command.h" - -/* Parameters */ - -#define symbolic_or_id \ - { \ - .name = "symbolic_or_id", \ - .help = \ - "The symbolic name for an egress, or the egress punting id (see " \ - "'help list puntings')", \ - .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_punting_t, face_id), \ - } - -#define prefix \ - { \ - .name = "prefix", \ - .help = "Prefix to add as a punting rule. (example 1234::0/64)", \ - .type = TYPE_IP_PREFIX, .offset = offsetof(hc_punting_t, prefix), \ - .offset2 = offsetof(hc_punting_t, prefix_len), \ - .offset3 = offsetof(hc_punting_t, family), \ - } - -/* Commands */ - -static const command_parser_t command_punting_create = { - .action = ACTION_CREATE, - .object = OBJECT_PUNTING, - .nparams = 2, - .parameters = {symbolic_or_id, prefix}, -}; -COMMAND_REGISTER(command_punting_create); - -static const command_parser_t command_punting_list = { - .action = ACTION_LIST, - .object = OBJECT_PUNTING, - .nparams = 0, -}; -COMMAND_REGISTER(command_punting_list); -#endif
\ No newline at end of file diff --git a/hicn-light/src/hicn/config/command_route.c b/hicn-light/src/hicn/config/command_route.c deleted file mode 100644 index dfbea101f..000000000 --- a/hicn-light/src/hicn/config/command_route.c +++ /dev/null @@ -1,53 +0,0 @@ -#include <math.h> -#include "command.h" - -/* Parameters */ - -#define symbolic_or_id \ - { \ - .name = "symbolic_or_id", \ - .help = \ - "The symbolic name for an egress, or the egress route id (see 'help " \ - "list routes')", \ - .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_route_t, name), \ - } - -#define prefix \ - { \ - .name = "prefix", \ - .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \ - .type = TYPE_IP_PREFIX, .offset = offsetof(hc_route_t, remote_addr), \ - .offset2 = offsetof(hc_route_t, len), \ - .offset3 = offsetof(hc_route_t, family), \ - } - -#define cost \ - { \ - .name = "cost", .help = "Positive integer representing cost.", \ - .type = TYPE_INT(1, 255), .offset = offsetof(hc_route_t, cost), \ - } - -/* Commands */ - -static const command_parser_t command_route_create = { - .action = ACTION_CREATE, - .object = OBJECT_ROUTE, - .nparams = 3, - .parameters = {symbolic_or_id, prefix, cost}, -}; -COMMAND_REGISTER(command_route_create); - -static const command_parser_t command_route_list = { - .action = ACTION_LIST, - .object = OBJECT_ROUTE, - .nparams = 0, -}; -COMMAND_REGISTER(command_route_list); - -static const command_parser_t command_route_remove = { - .action = ACTION_DELETE, - .object = OBJECT_ROUTE, - .nparams = 2, - .parameters = {symbolic_or_id, prefix}, -}; -COMMAND_REGISTER(command_route_remove); diff --git a/hicn-light/src/hicn/config/command_strategy.c b/hicn-light/src/hicn/config/command_strategy.c deleted file mode 100644 index 2341ac830..000000000 --- a/hicn-light/src/hicn/config/command_strategy.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "command.h" - -/* Parameters */ -#define prefix \ - { \ - .name = "prefix", \ - .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \ - .type = TYPE_IP_PREFIX, .offset = offsetof(hc_strategy_t, address), \ - .offset2 = offsetof(hc_strategy_t, len), \ - .offset3 = offsetof(hc_strategy_t, family), \ - } - -#define strategy \ - { \ - .name = "strategy", \ - .help = \ - "Strategy type (e.g. 'random', 'loadbalancer', 'low_latency', " \ - "'replication', 'bestpath').", \ - .type = TYPE_ENUM(strategy_type), .offset = offsetof(hc_strategy_t, type), \ - } - -#define local_prefix \ - { \ - .name = "local_prefix", \ - .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \ - .type = TYPE_IP_PREFIX, .offset = offsetof(hc_strategy_t, local_address), \ - .offset2 = offsetof(hc_strategy_t, local_len), \ - .offset3 = offsetof(hc_strategy_t, local_family), \ - } - -/* Commands */ - -static const command_parser_t command_strategy_list = { - .action = ACTION_SET, - .object = OBJECT_STRATEGY, - .nparams = 2, - .parameters = {prefix, strategy}, -}; -COMMAND_REGISTER(command_strategy_list); - -static const command_parser_t local_prefix_add = { - .action = ACTION_CREATE, - .object = OBJECT_LOCAL_PREFIX, - .nparams = 3, - .parameters = {prefix, strategy, local_prefix}, -}; -COMMAND_REGISTER(local_prefix_add); diff --git a/hicn-light/src/hicn/config/command_subscription.c b/hicn-light/src/hicn/config/command_subscription.c deleted file mode 100644 index 89e3dcd98..000000000 --- a/hicn-light/src/hicn/config/command_subscription.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "command.h" - -/* Parameters */ - -#define topics \ - { \ - .name = "topics", \ - .help = \ - "Topics to subscribe to, e.g. 6 (110 in binary) means topic 2 (10 in " \ - "binary, TOPIC_CONNECTION) and topic 4 (100 in binary, " \ - "TOPIC_LISTENER).", \ - .type = TYPE_INT(1, 255), .offset = offsetof(hc_subscription_t, topics), \ - } - -/* Commands */ - -static const command_parser_t command_subscription_create = { - .action = ACTION_CREATE, - .object = OBJECT_SUBSCRIPTION, - .nparams = 1, - .parameters = {topics}, -}; -COMMAND_REGISTER(command_subscription_create);
\ No newline at end of file diff --git a/hicn-light/src/hicn/config/commands.c b/hicn-light/src/hicn/config/commands.c index be00575d7..08c43ba24 100644 --- a/hicn-light/src/hicn/config/commands.c +++ b/hicn-light/src/hicn/config/commands.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -42,7 +42,8 @@ #include <hicn/core/listener.h> //the listener list #include <hicn/core/listener_table.h> #include <hicn/core/subscription.h> -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/ctrl/hicn-light.h> +//#include <hicn/utils/utils.h> #include <hicn/utils/punting.h> #include <hicn/util/log.h> #include <hicn/validation.h> @@ -55,8 +56,17 @@ #define DEFAULT_COST 1 #define DEFAULT_PORT 1234 -#define make_ack(msg) ((msg_header_t *)msg)->header.message_type = ACK_LIGHT -#define make_nack(msg) ((msg_header_t *)msg)->header.message_type = NACK_LIGHT +#define make_ack(msg) \ + do { \ + ((msg_header_t *)msg)->header.message_type = ACK_LIGHT; \ + ((msg_header_t *)msg)->header.length = 0; \ + } while (0) + +#define make_nack(msg) \ + do { \ + ((msg_header_t *)msg)->header.message_type = NACK_LIGHT; \ + ((msg_header_t *)msg)->header.length = 0; \ + } while (0) #define msg_malloc_list(msg, COMMAND_ID, N, seq_number) \ do { \ @@ -138,6 +148,7 @@ uint8_t *configuration_on_listener_add(forwarder_t *forwarder, uint8_t *packet, case FACE_TYPE_HICN_LISTENER: break; default: + ERROR("Wrong listener type"); goto NACK; } @@ -266,8 +277,11 @@ uint8_t *configuration_on_listener_remove(forwarder_t *forwarder, continue; unsigned conn_id = - (unsigned int)connection_table_get_connection_id(table, connection); + (unsigned)connection_table_get_connection_id(table, connection); + /* Remove connection from the FIB */ + // XXX TODO get entries, raise notifications... + // XXX isn't it possible to implement this in the forwarder ????? forwarder_remove_connection_id_from_routes(forwarder, conn_id); /* Remove connection */ @@ -288,10 +302,8 @@ NACK: } // TODO(eloparco): Unused forwarder param -static inline void fill_listener_command(forwarder_t *forwarder, - listener_t *listener, +static inline void fill_listener_command(const listener_t *listener, cmd_listener_list_item_t *cmd) { - assert(forwarder); assert(listener); assert(cmd); @@ -306,15 +318,15 @@ static inline void fill_listener_command(forwarder_t *forwarder, switch (addr->as_ss.ss_family) { case AF_INET: sin = (struct sockaddr_in *)addr; - cmd->family = AF_INET; - cmd->address.v4.as_inaddr = sin->sin_addr; - cmd->port = sin->sin_port; + cmd->family = (uint8_t)AF_INET; + cmd->local_addr.v4.as_inaddr = sin->sin_addr; + cmd->local_port = sin->sin_port; break; case AF_INET6: sin6 = (struct sockaddr_in6 *)addr; - cmd->family = AF_INET6; - cmd->address.v6.as_in6addr = sin6->sin6_addr; - cmd->port = sin6->sin6_port; + cmd->family = (uint8_t)AF_INET6; + cmd->local_addr.v6.as_in6addr = sin6->sin6_addr; + cmd->local_port = sin6->sin6_port; break; default: break; @@ -344,9 +356,8 @@ uint8_t *configuration_on_listener_list(forwarder_t *forwarder, uint8_t *packet, if (!msg) goto NACK; cmd_listener_list_item_t *payload = &msg->payload; - listener_t *listener; listener_table_foreach(table, listener, { - fill_listener_command(forwarder, listener, payload); + fill_listener_command(listener, payload); payload++; }); @@ -406,41 +417,10 @@ uint8_t *configuration_on_connection_add(forwarder_t *forwarder, control->remote_port) < 0) goto NACK; - connection_t *connection = connection_table_get_by_pair(table, &pair); -#ifdef WITH_MAPME - connection_event_t event; -#endif /* WITH_MAPME */ - - if (!connection) { - connection = - connection_create(control->type, symbolic_name, &pair, forwarder); - if (!connection) { - ERROR("Failed to create %s connection", face_type_str(control->type)); - goto NACK; - } - -#ifdef WITH_MAPME - event = CONNECTION_EVENT_CREATE; -#endif /* WITH_MAPME */ - } else { - WARN("Connection already exists"); - -#ifdef WITH_MAPME - event = CONNECTION_EVENT_UPDATE; -#endif /* WITH_MAPME */ - } - -#ifdef WITH_POLICY - connection_set_tags(connection, control->tags); - connection_set_priority(connection, control->priority); -#endif /* WITH_POLICY */ - - connection_set_admin_state(connection, control->admin_state); - -#ifdef WITH_MAPME - /* Hook: new connection created through the control protocol */ - forwarder_on_connection_event(forwarder, connection, event); -#endif /* WITH_MAPME */ + if (forwarder_add_connection(forwarder, symbolic_name, control->type, &pair, + control->tags, control->priority, + control->admin_state) < 0) + goto NACK; make_ack(msg); return (uint8_t *)msg; @@ -486,24 +466,20 @@ uint8_t *configuration_on_connection_remove(forwarder_t *forwarder, goto NACK; } - /* Remove connection from the FIB */ - forwarder_remove_connection_id_from_routes(forwarder, conn_id); - - /* Remove connection */ - connection_table_t *table = forwarder_get_connection_table(forwarder); - connection_t *connection = connection_table_get_by_id(table, conn_id); - connection_table_remove_by_id(table, conn_id); + /* + * + * Don't close the fd for SELF otherwise it won't be possible + * to send the reply back. The connection is finalized later in + * _forwarder_finalize_connection_if_self + */ + bool finalize = (strcmp(control->symbolic_or_connid, "SELF") != 0); - // Don't close the fd for SELF otherwise it won't be possible - // to send the reply back - if (strcmp(control->symbolic_or_connid, "SELF") != 0) - connection_finalize(connection); - WITH_DEBUG(connection_table_print_by_pair(table);) + if (forwarder_remove_connection(forwarder, conn_id, finalize) < 0) goto NACK; -#ifdef WITH_MAPME - /* Hook: new connection created through the control protocol */ - forwarder_on_connection_event(forwarder, NULL, CONNECTION_EVENT_DELETE); -#endif /* WITH_MAPME */ + WITH_DEBUG({ + connection_table_t *table = forwarder_get_connection_table(forwarder); + connection_table_print_by_pair(table); + }) make_ack(msg); return (uint8_t *)msg; @@ -519,10 +495,8 @@ static inline void tolower_str(char *str) { } // TODO(eloparco): Forwarder param not used -static inline void fill_connections_command(forwarder_t *forwarder, - connection_t *connection, +static inline void fill_connections_command(const connection_t *connection, cmd_connection_list_item_t *cmd) { - assert(forwarder); assert(connection); assert(cmd); @@ -531,12 +505,12 @@ static inline void fill_connections_command(forwarder_t *forwarder, const address_pair_t *pair = connection_get_pair(connection); cmd->id = connection_get_id(connection), - cmd->state = connection_get_state(connection), - cmd->admin_state = connection_get_admin_state(connection), - cmd->type = connection_get_type(connection), + cmd->state = (uint8_t)connection_get_state(connection), + cmd->admin_state = (uint8_t)connection_get_admin_state(connection), + cmd->type = (uint8_t)connection_get_type(connection), #ifdef WITH_POLICY cmd->priority = connection_get_priority(connection), - cmd->tags = connection_get_tags(connection), + cmd->tags = (uint8_t)connection_get_tags(connection), #endif /* WITH_POLICY */ snprintf(cmd->name, SYMBOLIC_NAME_LEN, "%s", connection_get_name(connection)); @@ -547,7 +521,7 @@ static inline void fill_connections_command(forwarder_t *forwarder, switch (pair->local.as_ss.ss_family) { case AF_INET: - cmd->family = AF_INET; + cmd->family = (uint8_t)AF_INET; sin = (struct sockaddr_in *)(&pair->local); cmd->local_port = sin->sin_port; @@ -559,7 +533,7 @@ static inline void fill_connections_command(forwarder_t *forwarder, break; case AF_INET6: - cmd->family = AF_INET6; + cmd->family = (uint8_t)AF_INET6; sin6 = (struct sockaddr_in6 *)(&pair->local); cmd->local_port = sin6->sin6_port; @@ -594,6 +568,7 @@ uint8_t *configuration_on_connection_list(forwarder_t *forwarder, // -1 since current connection (i.e. the one used to send // the command) is not considered size_t n = connection_table_len(table) - 1; + msg_connection_list_t *msg_received = (msg_connection_list_t *)packet; uint8_t command_id = msg_received->header.command_id; uint32_t seq_num = msg_received->header.seq_num; @@ -603,10 +578,9 @@ uint8_t *configuration_on_connection_list(forwarder_t *forwarder, if (!msg) goto NACK; cmd_connection_list_item_t *payload = &msg->payload; - connection_t *connection; - connection_table_foreach(table, connection, { + connection_table_foreach_new(table, connection, { if (connection->id == ingress_id) continue; - fill_connections_command(forwarder, connection, payload); + fill_connections_command(connection, payload); payload++; }); @@ -619,6 +593,7 @@ NACK: return (uint8_t *)msg; } +#if 0 uint8_t *configuration_on_connection_set_admin_state(forwarder_t *forwarder, uint8_t *packet, unsigned ingress_id, @@ -640,13 +615,11 @@ uint8_t *configuration_on_connection_set_admin_state(forwarder_t *forwarder, connection_set_admin_state(conn, control->admin_state); -#ifdef WITH_MAPME /* Hook: connection event */ forwarder_on_connection_event(forwarder, conn, control->admin_state == FACE_STATE_UP ? CONNECTION_EVENT_SET_UP : CONNECTION_EVENT_SET_DOWN); -#endif /* WITH_MAPME */ make_ack(msg); return (uint8_t *)msg; @@ -656,6 +629,7 @@ NACK: return (uint8_t *)msg; } +#endif uint8_t *configuration_on_connection_update(forwarder_t *forwarder, uint8_t *packet, unsigned ingress_id, @@ -684,6 +658,8 @@ NACK: return (uint8_t *)msg; } +#if 0 + uint8_t *configuration_on_connection_set_priority(forwarder_t *forwarder, uint8_t *packet, unsigned ingress_id, @@ -701,11 +677,9 @@ uint8_t *configuration_on_connection_set_priority(forwarder_t *forwarder, connection_set_priority(conn, control->priority); -#ifdef WITH_MAPME /* Hook: connection event */ forwarder_on_connection_event(forwarder, conn, CONNECTION_EVENT_PRIORITY_CHANGED); -#endif /* WITH_MAPME */ make_ack(msg); return (uint8_t *)msg; @@ -733,10 +707,8 @@ uint8_t *configuration_on_connection_set_tags(forwarder_t *forwarder, connection_set_tags(conn, control->tags); -#ifdef WITH_MAPME /* Hook: connection event */ forwarder_on_connection_event(forwarder, conn, CONNECTION_EVENT_TAGS_CHANGED); -#endif /* WITH_MAPME */ make_ack(msg); return (uint8_t *)msg; @@ -747,6 +719,8 @@ NACK: return (uint8_t *)msg; } +#endif + /* Route */ uint8_t *configuration_on_route_add(forwarder_t *forwarder, uint8_t *packet, @@ -763,9 +737,9 @@ uint8_t *configuration_on_route_add(forwarder_t *forwarder, uint8_t *packet, forwarder, control->symbolic_or_connid, ingress_id); if (!connection_id_is_valid(conn_id)) goto NACK; - ip_prefix_t prefix = {.family = control->family, - .address = control->address, - .len = control->len}; + hicn_ip_prefix_t prefix = {.family = control->family, + .address = control->address, + .len = control->len}; if (!forwarder_add_or_update_route(forwarder, &prefix, conn_id)) goto NACK; @@ -792,9 +766,9 @@ uint8_t *configuration_on_route_remove(forwarder_t *forwarder, uint8_t *packet, symbolic_to_conn_id(forwarder, control->symbolic_or_connid); if (!connection_id_is_valid(conn_id)) goto NACK; - ip_prefix_t prefix = {.family = control->family, - .address = control->address, - .len = control->len}; + hicn_ip_prefix_t prefix = {.family = control->family, + .address = control->address, + .len = control->len}; if (!forwarder_remove_route(forwarder, &prefix, conn_id)) goto NACK; @@ -806,6 +780,29 @@ NACK: return (uint8_t *)msg; } +static inline void fill_route_command(const fib_entry_t *entry, + cmd_route_list_item_t *cmd) { + const nexthops_t *nexthops = fib_entry_get_nexthops(entry); + assert(nexthops_get_len(nexthops) == nexthops_get_curlen(nexthops)); + size_t num_nexthops = nexthops_get_len(nexthops); + + if (num_nexthops == 0) return; + + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); + const hicn_ip_address_t *address = hicn_prefix_get_ip_address(prefix); + int family = hicn_ip_address_get_family(address); + + nexthops_foreach(nexthops, nexthop, { + cmd->family = family; + cmd->remote_addr = *address; + cmd->face_id = nexthop; + cmd->len = hicn_prefix_get_len(prefix); + cmd->cost = DEFAULT_COST; + + cmd++; + }); +} + uint8_t *configuration_on_route_list(forwarder_t *forwarder, uint8_t *packet, unsigned ingress_id, size_t *reply_size) { INFO("CMD: route list (ingress=%d)", ingress_id); @@ -816,7 +813,6 @@ uint8_t *configuration_on_route_list(forwarder_t *forwarder, uint8_t *packet, uint8_t command_id = msg_received->header.command_id; uint32_t seq_num = msg_received->header.seq_num; const fib_t *fib = forwarder_get_fib(forwarder); - fib_entry_t *entry; /* * Two step approach to precompute the number of entries to allocate @@ -835,38 +831,7 @@ uint8_t *configuration_on_route_list(forwarder_t *forwarder, uint8_t *packet, if (!msg) goto NACK; cmd_route_list_item_t *payload = &msg->payload; - fib_foreach_entry(fib, entry, { - const nexthops_t *nexthops = fib_entry_get_nexthops(entry); - assert(nexthops_get_len(nexthops) == nexthops_get_curlen(nexthops)); - size_t num_nexthops = nexthops_get_len(nexthops); - - if (num_nexthops == 0) continue; - - NameBitvector *prefix = name_GetContentName(fib_entry_get_prefix(entry)); - - unsigned nexthop; - nexthops_foreach(nexthops, nexthop, { - address_t address; - nameBitvector_ToAddress(prefix, &address); - switch (address_family(&address)) { - case AF_INET: - payload->family = AF_INET; - payload->address.v4.as_inaddr = address4_ip(&address); - break; - case AF_INET6: - payload->family = AF_INET6; - payload->address.v6.as_in6addr = address6_ip(&address); - break; - default: - break; - } - payload->connection_id = nexthop; - payload->len = nameBitvector_GetLength(prefix); - payload->cost = DEFAULT_COST; - - payload++; - }); - }); + fib_foreach_entry(fib, entry, { fill_route_command(entry, payload); }); *reply_size = sizeof(msg->header) + n * sizeof(msg->payload); return (uint8_t *)msg; @@ -983,12 +948,12 @@ uint8_t *configuration_on_strategy_set(forwarder_t *forwarder, uint8_t *packet, cmd_strategy_set_t *control = &msg->payload; char prefix_s[MAXSZ_IP_PREFIX]; - ip_prefix_t prefix = { + hicn_ip_prefix_t prefix = { .family = control->family, .address = control->address, .len = control->len, }; - int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); + int rc = hicn_ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); assert(rc < MAXSZ_IP_PREFIX); if (rc < 0) goto NACK; @@ -998,9 +963,10 @@ uint8_t *configuration_on_strategy_set(forwarder_t *forwarder, uint8_t *packet, configuration_get_strategy(config, prefix_s); strategy_options_t *options = NULL; - Name name_prefix = EMPTY_NAME; - name_CreateFromAddress(&name_prefix, control->family, control->address, - control->len); + // XXX check control->family + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&control->address, control->len, + &name_prefix); // The strategy is not present in the hash table // or has to be updated or to be restarted @@ -1012,9 +978,9 @@ uint8_t *configuration_on_strategy_set(forwarder_t *forwarder, uint8_t *packet, forwarder_set_strategy(forwarder, &name_prefix, strategy, options); } else { WITH_WARN({ - char *nameString = name_ToString(&name_prefix); - WARN("Strategy for prefix %s not updated", nameString); - free(nameString); + char buf[MAXSZ_HICN_PREFIX]; + hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, &name_prefix); + WARN("Strategy for prefix %s not updated", buf); }) } @@ -1040,12 +1006,12 @@ uint8_t *configuration_on_strategy_add_local_prefix(forwarder_t *forwarder, cmd_strategy_add_local_prefix_t *control = &msg->payload; char prefix_s[MAXSZ_IP_PREFIX]; - ip_prefix_t prefix = { + hicn_ip_prefix_t prefix = { .family = control->family, .address = control->address, .len = control->len, }; - int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); + int rc = hicn_ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); assert(rc < MAXSZ_IP_PREFIX); if (rc < 0) goto NACK; @@ -1060,17 +1026,17 @@ uint8_t *configuration_on_strategy_add_local_prefix(forwarder_t *forwarder, strategy != STRATEGY_TYPE_REPLICATION) goto NACK; - Name name_prefix = EMPTY_NAME; - name_CreateFromAddress(&name_prefix, control->family, control->address, - control->len); + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&control->address, control->len, + &name_prefix); strategy_options_t options; - Name local_prefix = EMPTY_NAME; - name_CreateFromAddress(&local_prefix, control->local_family, - control->local_address, control->local_len); + hicn_prefix_t local_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&control->address, control->len, + &local_prefix); - // for the moment bestpath and replication are the same but we distinguish the - // two in case they will diverge in the future + // for the moment bestpath and replication are the same but we distinguish + // the two in case they will diverge in the future if (strategy == STRATEGY_TYPE_BESTPATH) { options.bestpath.local_prefixes = create_local_prefixes(); local_prefixes_add_prefix(options.bestpath.local_prefixes, &local_prefix); @@ -1212,11 +1178,11 @@ uint8_t *configuration_on_punting_add(forwarder_t *forwarder, uint8_t *packet, goto NACK; } - ip_prefix_t prefix = {.family = control->family, - .address = control->address, - .len = control->len}; + hicn_ip_prefix_t prefix = {.family = control->family, + .address = control->address, + .len = control->len}; char prefix_s[MAXSZ_IP_PREFIX]; - int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); + int rc = hicn_ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); assert(rc < MAXSZ_IP_PREFIX); if (rc < 0) goto NACK; @@ -1359,12 +1325,11 @@ uint8_t *configuration_on_mapme_send_update(forwarder_t *forwarder, mapme_t *mapme = forwarder_get_mapme(forwarder); /* - * The command triggers a mapme update for all prefixes produced on this face + * The command triggers a mapme update for all prefixes produced on this + * face * */ - fib_entry_t *entry; fib_foreach_entry(fib, entry, { const nexthops_t *nexthops = fib_entry_get_nexthops(entry); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { if (nexthop != ingress_id) continue; /* This entry points to the producer face */ @@ -1393,9 +1358,9 @@ uint8_t *configuration_on_policy_add(forwarder_t *forwarder, uint8_t *packet, msg_policy_add_t *msg = (msg_policy_add_t *)packet; cmd_policy_add_t *control = &msg->payload; - ip_prefix_t prefix = {.family = control->family, - .address = control->address, - .len = control->len}; + hicn_ip_prefix_t prefix = {.family = control->family, + .address = control->address, + .len = control->len}; if (!forwarder_add_or_update_policy(forwarder, &prefix, &control->policy)) goto NACK; @@ -1419,9 +1384,9 @@ uint8_t *configuration_on_policy_remove(forwarder_t *forwarder, uint8_t *packet, msg_policy_remove_t *msg = (msg_policy_remove_t *)packet; cmd_policy_remove_t *control = &msg->payload; - ip_prefix_t prefix = {.family = control->family, - .address = control->address, - .len = control->len}; + hicn_ip_prefix_t prefix = {.family = control->family, + .address = control->address, + .len = control->len}; if (!forwarder_remove_policy(forwarder, &prefix)) goto NACK; @@ -1434,6 +1399,39 @@ NACK: return (uint8_t *)msg; } +static inline void fill_policy_command(const fib_entry_t *entry, + cmd_policy_list_item_t *cmd) { + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); + const hicn_ip_address_t *ip_address = hicn_prefix_get_ip_address(prefix); + cmd->remote_addr = *ip_address; + cmd->family = hicn_ip_address_get_family(ip_address); + cmd->len = hicn_prefix_get_len(prefix); + + hicn_policy_t policy = fib_entry_get_policy(entry); + _hicn_policy_t _policy = { + .stats = { + .wired = {.throughput = htonf(policy.stats.wired.throughput), + .latency = htonf(policy.stats.wired.latency), + .loss_rate = htonf(policy.stats.wired.loss_rate)}, + .wifi = {.throughput = htonf(policy.stats.wifi.throughput), + .latency = htonf(policy.stats.wifi.latency), + .loss_rate = htonf(policy.stats.wifi.loss_rate)}, + .cellular = {.throughput = htonf(policy.stats.cellular.throughput), + .latency = htonf(policy.stats.cellular.latency), + .loss_rate = htonf(policy.stats.cellular.loss_rate)}, + .all = {.throughput = htonf(policy.stats.all.throughput), + .latency = htonf(policy.stats.all.latency), + .loss_rate = htonf(policy.stats.all.loss_rate)}}}; + for (unsigned i = 0; i < POLICY_TAG_N; i++) { + _policy.tags[i] = (_policy_tag_state_t){ + .state = policy.tags[i].state, + .disabled = policy.tags[i].disabled, + }; + } + memcpy(_policy.app_name, policy.app_name, APP_NAME_LEN); + memcpy(cmd->policy, &_policy, sizeof(_policy)); +} + uint8_t *configuration_on_policy_list(forwarder_t *forwarder, uint8_t *packet, unsigned ingress_id, size_t *reply_size) { assert(forwarder); @@ -1454,30 +1452,8 @@ uint8_t *configuration_on_policy_list(forwarder_t *forwarder, uint8_t *packet, cmd_policy_list_item_t *payload = &msg->payload; - fib_entry_t *entry; - fib_foreach_entry(fib, entry, { - NameBitvector *prefix = name_GetContentName(fib_entry_get_prefix(entry)); - address_t address; - nameBitvector_ToAddress(prefix, &address); - - switch (address_family(&address)) { - case AF_INET: - payload->family = AF_INET; - payload->address.v4.as_inaddr = address4_ip(&address); - break; - - case AF_INET6: - payload->family = AF_INET6; - payload->address.v6.as_in6addr = address6_ip(&address); - break; - - default: - break; - } - payload->len = nameBitvector_GetLength(prefix); - payload->policy = fib_entry_get_policy(entry); - + fill_policy_command(entry, payload); payload++; }); @@ -1544,9 +1520,17 @@ uint8_t *configuration_on_subscription_remove(forwarder_t *forwarder, return (uint8_t *)msg; } +uint8_t *configuration_on_active_interface_update(forwarder_t *forwarder, + uint8_t *packet, + unsigned ingress_id, + size_t *reply_size) { + msg_active_interface_update_t *msg = (msg_active_interface_update_t *)packet; + make_nack(msg); + return (uint8_t *)msg; +} + uint8_t *command_process(forwarder_t *forwarder, uint8_t *packet, - command_type_t command_type, unsigned ingress_id, - size_t *reply_size) { + unsigned ingress_id, size_t *reply_size) { uint8_t *reply = NULL; /* @@ -1557,6 +1541,7 @@ uint8_t *command_process(forwarder_t *forwarder, uint8_t *packet, * * XXX rework this part. */ + command_type_t command_type = ((msg_header_t *)packet)->header.command_id; switch (command_type) { #define _(l, u) \ case COMMAND_TYPE_##u: \ @@ -1586,28 +1571,100 @@ ssize_t command_process_msgbuf(forwarder_t *forwarder, msgbuf_t *msgbuf) { uint8_t *reply = NULL; size_t reply_size = 0; - command_type_t command_type = msgbuf_get_command_type(msgbuf); - - reply = - command_process(forwarder, packet, command_type, ingress_id, &reply_size); + reply = command_process(forwarder, packet, ingress_id, &reply_size); if (connection_id_is_valid(msgbuf->connection_id)) { connection_table_t *table = forwarder_get_connection_table(forwarder); const connection_t *connection = connection_table_at(table, ingress_id); connection_send_packet(connection, reply, reply_size); } - switch (msgbuf->command.type) { - case COMMAND_TYPE_LISTENER_LIST: - case COMMAND_TYPE_CONNECTION_LIST: - case COMMAND_TYPE_ROUTE_LIST: - case COMMAND_TYPE_POLICY_LIST: - /* Free replies that have been allocated (not NACK's) */ - if (((msg_header_t *)reply)->header.message_type != NACK_LIGHT) - free(reply); + /* Free allocated replies */ + if (reply != packet) free(reply); + return msgbuf_get_len(msgbuf); +} + +void commands_notify(const forwarder_t *forwarder, hc_topic_t topic, + uint8_t *msg, size_t size) { + // Retrieve subscribed connections + subscription_table_t *subscriptions = forwarder_get_subscriptions(forwarder); + unsigned *subscribed_conn_ids = + subscription_table_get_connections_for_topic(subscriptions, topic); + + // Send notification to subscribed connections + const connection_table_t *table = forwarder_get_connection_table(forwarder); + for (int i = 0; i < vector_len(subscribed_conn_ids); i++) { + const connection_t *conn = + connection_table_at(table, subscribed_conn_ids[i]); + connection_send_packet(conn, msg, size); + } +} + +void commands_notify_connection(const forwarder_t *forwarder, + connection_event_t event, + const connection_t *connection) { +#if 0 + uint8_t command_id; + switch (event) { + case CONNECTION_EVENT_CREATE: + command_id = COMMAND_TYPE_CONNECTION_ADD; break; - default: + case CONNECTION_EVENT_DELETE: + command_id = COMMAND_TYPE_CONNECTION_REMOVE; + break; + case CONNECTION_EVENT_UPDATE: + case CONNECTION_EVENT_SET_UP: + case CONNECTION_EVENT_SET_DOWN: + case CONNECTION_EVENT_PRIORITY_CHANGED: + case CONNECTION_EVENT_TAGS_CHANGED: + command_id = COMMAND_TYPE_CONNECTION_UPDATE; break; + case CONNECTION_EVENT_UNDEFINED: + case CONNECTION_EVENT_N: + default: + return; } +#endif - return msgbuf_get_len(msgbuf); + msg_connection_notify_t msg = {.header = { + .message_type = NOTIFICATION_LIGHT, + .command_id = OBJECT_TYPE_CONNECTION, + .length = 1, + .seq_num = 0, + }}; + fill_connections_command(connection, &msg.payload); + + commands_notify(forwarder, TOPIC_CONNECTION, (uint8_t *)&msg, sizeof(msg)); +} + +void commands_notify_route(const forwarder_t *forwarder, + const fib_entry_t *entry) { + const nexthops_t *nexthops = fib_entry_get_nexthops(entry); + size_t n = nexthops_get_len(nexthops); + msg_route_notify_t *msg = NULL; + msg_malloc_list(msg, OBJECT_TYPE_ROUTE, n, 0); + if (!msg) return; + + fill_route_command(entry, &msg->payload); + + commands_notify(forwarder, TOPIC_ROUTE, (uint8_t *)&msg, sizeof(msg)); +} + +void commands_notify_active_interface_update(const forwarder_t *forwarder, + hicn_ip_prefix_t *prefix, + netdevice_flags_t flags) { + struct { + cmd_header_t header; + hc_active_interface_t payload; + } msg = {.header = + { + .message_type = NOTIFICATION_LIGHT, + .command_id = OBJECT_TYPE_ACTIVE_INTERFACE, + .length = 1, + .seq_num = 0, + }, + .payload = {.prefix = *prefix, .interface_types = flags}}; + + INFO("Notify active interface"); + commands_notify(forwarder, TOPIC_ACTIVE_INTERFACE, (uint8_t *)&msg, + sizeof(msg)); } diff --git a/hicn-light/src/hicn/config/commands.h b/hicn-light/src/hicn/config/commands.h index 3852a76ac..f212c1b0b 100644 --- a/hicn-light/src/hicn/config/commands.h +++ b/hicn-light/src/hicn/config/commands.h @@ -29,11 +29,10 @@ #include "../core/msgbuf.h" #include "../core/strategy.h" #include <hicn/ctrl/api.h> -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/ctrl/hicn-light.h> uint8_t *command_process(forwarder_t *forwarder, uint8_t *packet, - command_type_t command_type, unsigned ingress_id, - size_t *reply_size); + unsigned ingress_id, size_t *reply_size); ssize_t command_process_msgbuf(forwarder_t *forwarder, msgbuf_t *msgbuf); @@ -152,4 +151,15 @@ uint8_t *configuration_on_policy_list(forwarder_t *forwarder, uint8_t *packet, uint8_t *configuration_on_stats_list(forwarder_t *forwarder, uint8_t *packet, unsigned ingress_id, size_t *reply_size); +void commands_notify_connection(const forwarder_t *forwarder, + connection_event_t event, + const connection_t *connection); + +void commands_notify_route(const forwarder_t *forwarder, + const fib_entry_t *entry); + +void commands_notify_active_interface_update(const forwarder_t *forwarder, + hicn_ip_prefix_t *prefix, + netdevice_flags_t flags); + #endif // HICNLIGHT_COMMANDS_H diff --git a/hicn-light/src/hicn/config/configuration.c b/hicn-light/src/hicn/config/configuration.c index 9123ceebf..f38c4f22f 100644 --- a/hicn-light/src/hicn/config/configuration.c +++ b/hicn-light/src/hicn/config/configuration.c @@ -41,7 +41,8 @@ #include <hicn/core/listener.h> //the listener list #include <hicn/core/listener_table.h> -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/ctrl/hicn-light.h> +//#include <hicn/utils/utils.h> #include <hicn/utils/punting.h> #include <hicn/util/log.h> #include <hicn/face.h> @@ -72,6 +73,8 @@ struct configuration_s { int logfile_fd; bool daemon; kh_strategy_map_t *strategy_map; + size_t n_suffixes_per_split; + int_manifest_split_strategy_t split_strategy; }; configuration_t *configuration_create() { @@ -92,6 +95,8 @@ configuration_t *configuration_create() { #endif configuration_set_loglevel(config, loglevel_from_str(DEFAULT_LOGLEVEL)); config->strategy_map = kh_init_strategy_map(); + config->n_suffixes_per_split = DEFAULT_N_SUFFIXES_PER_SPLIT; + config->split_strategy = DEFAULT_DISAGGREGATION_STRATEGY; return config; } @@ -127,6 +132,25 @@ void configuration_set_fn_config(configuration_t *config, config->fn_config = fn_config; } +void configuration_set_suffixes_per_split(configuration_t *config, + size_t n_suffixes_per_split) { + config->n_suffixes_per_split = n_suffixes_per_split; +} + +size_t configuration_get_suffixes_per_split(const configuration_t *config) { + return config->n_suffixes_per_split; +} + +void configuration_set_split_strategy( + configuration_t *config, int_manifest_split_strategy_t split_strategy) { + config->split_strategy = split_strategy; +} + +int_manifest_split_strategy_t configuration_get_split_strategy( + const configuration_t *config) { + return config->split_strategy; +} + void configuration_set_port(configuration_t *config, uint16_t port) { config->port = port; } diff --git a/hicn-light/src/hicn/config/configuration.h b/hicn-light/src/hicn/config/configuration.h index 93b4cf7c3..0d1a2b8e7 100644 --- a/hicn-light/src/hicn/config/configuration.h +++ b/hicn-light/src/hicn/config/configuration.h @@ -30,7 +30,8 @@ #include "../core/msgbuf.h" #include "../core/strategy.h" #include <hicn/ctrl/api.h> -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/ctrl/hicn-light.h> +#include <hicn/interest_manifest.h> KHASH_MAP_INIT_STR(strategy_map, unsigned); @@ -103,6 +104,18 @@ const char *configuration_get_fn_config(const configuration_t *config); void configuration_set_fn_config(configuration_t *config, const char *fn_config); +void configuration_set_suffixes_per_split(configuration_t *config, + size_t n_suffixes_per_split); + +size_t configuration_get_suffixes_per_split(const configuration_t *config); + +void configuration_set_split_strategy( + configuration_t *config, + int_manifest_split_strategy_t n_suffixes_per_split); + +int_manifest_split_strategy_t configuration_get_split_strategy( + const configuration_t *config); + void configuration_set_port(configuration_t *config, uint16_t port); uint16_t configuration_get_port(const configuration_t *config); diff --git a/hicn-light/src/hicn/config/configuration_file.c b/hicn-light/src/hicn/config/configuration_file.c index 2e8e7a6ac..8649e0143 100644 --- a/hicn-light/src/hicn/config/configuration_file.c +++ b/hicn-light/src/hicn/config/configuration_file.c @@ -20,11 +20,13 @@ #include <errno.h> #include <stdio.h> #include <string.h> + +#include <hicn/ctrl/hicn-light.h> #include <hicn/config/configuration_file.h> #include <hicn/util/sstrncpy.h> #include "commands.h" -#include "parse.h" +#include <hicn/ctrl/parse.h> #define BUFFERLEN 2048 @@ -62,12 +64,17 @@ bool configuration_file_process(forwarder_t *forwarder, const char *filename) { char buffer[BUFFERLEN]; bool success = true; + +#if 0 // TODO(eloparco): We could use a fake socket since we only need the vft - hc_sock_t *s = hc_sock_create_forwarder(HICNLIGHT_NG); + hc_sock_t *s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL); if (!s) { ERROR("Could not create socket"); goto ERR_SOCK; } +#else + hc_sock_initialize_module(NULL); +#endif while (success && fgets(buffer, BUFFERLEN, f) != NULL) { linesRead++; @@ -83,42 +90,31 @@ bool configuration_file_process(forwarder_t *forwarder, const char *filename) { continue; } - // TODO(eloparco): Handle all commands - hc_result_t *result = NULL; - if (command.action == ACTION_CREATE) { - if (command.object.type == OBJECT_LISTENER) { - result = hc_listener_create_conf(s, &command.object.listener); - } else if (command.object.type == OBJECT_CONNECTION) { - result = hc_connection_create_conf(s, &command.object.connection); - } else if (command.object.type == OBJECT_ROUTE) { - result = hc_route_create_conf(s, &command.object.route); - } else if (command.object.type == OBJECT_LOCAL_PREFIX) { - result = hc_strategy_add_local_prefix_conf(s, &command.object.strategy); - } - } else if (command.action == ACTION_SET) { - if (command.object.type == OBJECT_STRATEGY) { - result = hc_strategy_set_conf(s, &command.object.strategy); - } - } - if (result == NULL) { - ERROR("Command '%s' not supported", cmd); - continue; + /* Serialize request into message */ + // hc_msg_t msg; + uint8_t msg[1024]; + ssize_t msg_len = hc_light_command_serialize( + command.action, command.object_type, &command.object, msg); + switch (msg_len) { + case -1: + case -2: + ERROR("Command '%s' not supported", cmd); + continue; + case -3: + ERROR("Error during command serialization '%s'", cmd); + continue; + default: + break; } size_t _unused; - hc_msg_t *msg = hc_result_get_msg(s, result); - command_type_t cmd_id = hc_result_get_cmd_id(s, result); - bool success = hc_result_get_success(s, result); - if (success == false) { - ERROR("Error serializing command : '%s'", cmd); - continue; - } - - command_process(forwarder, (uint8_t *)msg, cmd_id, CONNECTION_ID_UNDEFINED, + command_process(forwarder, (uint8_t *)msg, CONNECTION_ID_UNDEFINED, &_unused); - hc_result_free(result); } + +#if 0 hc_sock_free(s); +#endif if (ferror(f)) { ERROR("Error on input file %s line %d: (%d) %s", filename, linesRead, errno, @@ -128,8 +124,10 @@ bool configuration_file_process(forwarder_t *forwarder, const char *filename) { fclose(f); return true; +#if 0 ERR_SOCK: hc_sock_free(s); +#endif ERR_READ: fclose(f); ERR_OPEN: diff --git a/hicn-light/src/hicn/config/configuration_file.h b/hicn-light/src/hicn/config/configuration_file.h index 4d9535ab7..03599d4f4 100644 --- a/hicn-light/src/hicn/config/configuration_file.h +++ b/hicn-light/src/hicn/config/configuration_file.h @@ -28,6 +28,7 @@ #define configuration_file_h #include <hicn/core/forwarder.h> +#include <hicn/ctrl/hicn-light.h> /** * Configure hicn-light by reading a configuration file line-by-line and diff --git a/hicn-light/src/hicn/config/parse.c b/hicn-light/src/hicn/config/parse.c deleted file mode 100644 index ba9c0b348..000000000 --- a/hicn-light/src/hicn/config/parse.c +++ /dev/null @@ -1,402 +0,0 @@ -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> - -//#include <hicn/ctrl/cli.h> -#include <hicn/util/log.h> -#include <hicn/util/sstrncpy.h> -#include "parse.h" - -/* - * As there is no portable way to generate a va_list to use with sscanf to - * support a variable number of arguments, and no way to use a variable array - * initialize in a nested struct, we use a fixed maximum number of parameters - * - * NOTE: update sscanf accordingly - */ - -#include "command.h" - -const char *action_str[] = { -#define _(x) [ACTION_##x] = #x, - foreach_action -#undef _ -}; - -#define action_str(x) action_str[x] - -hc_action_t action_from_str(const char *action_str) { -#define _(x) \ - if (strcasecmp(action_str, #x) == 0) \ - return ACTION_##x; \ - else - foreach_action -#undef _ - if (strcasecmp(action_str, "add") == 0) return ACTION_CREATE; - else if (strcasecmp(action_str, "remove") == 0) return ACTION_DELETE; - else return ACTION_UNDEFINED; -} - -const char *object_str[] = { -#define _(x) [OBJECT_##x] = #x, - foreach_object -#undef _ -}; - -#define object_str(x) object_str[x] - -hc_object_type_t object_from_str(const char *object_str) { -#define _(x) \ - if (strcasecmp(object_str, #x) == 0) \ - return OBJECT_##x; \ - else - foreach_object -#undef _ - return OBJECT_UNDEFINED; -} - -const char *action_to_cmd_action(hc_action_t action) { - switch (action) { - case ACTION_CREATE: - return "add"; - case ACTION_UPDATE: - return "update"; - case ACTION_DELETE: - return "remove"; - case ACTION_LIST: - return "list"; - case ACTION_SET: - return "set"; - case ACTION_SERVE: - return "serve"; - case ACTION_STORE: - return "store"; - case ACTION_CLEAR: - return "clear"; - default: - return "UNDEFINED"; - } -} - -const char *parser_type_fmt(const parser_type_t *type) { - switch (type->name) { - case TYPENAME_INT: - return TYPE_FMT_INT; - case TYPENAME_UINT: - return TYPE_FMT_UINT; - case TYPENAME_STR: - return TYPE_FMT_STRN(type->str.max_size); - case TYPENAME_SYMBOLIC_OR_ID: - return TYPE_FMT_SYMBOLIC_OR_ID; - case TYPENAME_INTERFACE_NAME: - return TYPE_FMT_INTERFACE_NAME; - case TYPENAME_IP_ADDRESS: - return TYPE_FMT_IP_ADDRESS; - case TYPENAME_IP_PREFIX: - return TYPE_FMT_IP_PREFIX; - case TYPENAME_ON_OFF: - return TYPE_FMT_ON_OFF; - case TYPENAME_ENUM: - return TYPE_FMT_ENUM; - case TYPENAME_POLICY_STATE: - return TYPE_FMT_POLICY_STATE; - case TYPENAME_UNDEFINED: - default: - return NULL; - } -} - -int parser_type_func(const parser_type_t *type, void *src, void *dst, - void *dst2, void *dst3) { - ip_address_t addr; - char *addr_str; - char *len_str; - int len, tmp, rc; - - switch (type->name) { - case TYPENAME_INT: - tmp = *(int *)src; - if (tmp < type->sint.min || tmp > type->sint.max) { - ERROR("Input number (%d) not inside range [%d, %d]", tmp, - type->sint.min, type->sint.max); - return -1; - } - *(int *)dst = *(int *)src; - break; - case TYPENAME_UINT: - tmp = *(int *)src; - if (tmp < type->uint.min || tmp > type->uint.max) { - ERROR("Input number (%d) not inside range [%d, %d]", tmp, - type->uint.min, type->uint.max); - return -1; - } - *(unsigned *)dst = *(unsigned *)src; - break; - case TYPENAME_STR: - rc = strcpy_s(dst, type->str.max_size, src); - if (rc != EOK) { - ERROR("Input string is too long"); - return -1; - } - break; - case TYPENAME_IP_ADDRESS: - rc = ip_address_pton((char *)src, &addr); - if (rc < 0) { - ERROR("Wrong IP address format"); - return -1; - } - - *(ip_address_t *)dst = addr; - *(int *)dst2 = ip_address_get_family((char *)src); - break; - case TYPENAME_ON_OFF: - if (strcmp((char *)src, "off") == 0) { - *(unsigned *)dst = 0; - } else if (strcmp((char *)src, "on") == 0) { - *(unsigned *)dst = 1; - } else { - ERROR("on/off are the only possible values"); - return -1; - } - break; - case TYPENAME_IP_PREFIX: - addr_str = strtok((char *)src, "/"); - len_str = strtok(NULL, " "); - rc = ip_address_pton((char *)src, &addr); - if (rc < 0) { - ERROR("Wrong IP address format"); - return -1; - } - len = atoi(len_str); - - *(ip_address_t *)dst = addr; - *(int *)dst2 = len; - *(int *)dst3 = ip_address_get_family(addr_str); - break; - case TYPENAME_ENUM: - /* Enum index from string */ - assert(type->enum_.from_str); - *(int *)dst = type->enum_.from_str((char *)src); - break; - case TYPENAME_POLICY_STATE: { - assert(IS_VALID_POLICY_TAG(type->policy_state.tag)); - policy_tag_t tag = type->policy_state.tag; - /* Format string is "%ms" */ - const char *str = *(const char **)src; - policy_tag_state_t *pts = ((policy_tag_state_t *)dst); - pts[tag].disabled = (str[0] == '!') ? 1 : 0; - pts[tag].state = policy_state_from_str(str + pts[tag].disabled); - break; - } - case TYPENAME_UNDEFINED: - default: - ERROR("Unknown format"); - return -1; - } - return 0; -} - -int parse_params(const command_parser_t *parser, const char *params_s, - hc_command_t *command) { - char fmt[1024]; - int n; - size_t size = 0; - char *pos = fmt; - /* Update MAX_PARAMETERS accordingly in command.h */ - char sscanf_params[MAX_PARAMETERS][MAX_SCANF_PARAM_LEN]; - - unsigned count = 0; - for (unsigned i = 0; i < parser->nparams; i++) { - const command_parameter_t *p = &parser->parameters[i]; - const char *_fmt = parser_type_fmt(&p->type); - // printf(" _fmt=%s\n", _fmt); - if (!_fmt) { - WARN("Ignored parameter %s with unknown type formatter", p->name); - continue; - } - n = snprintf(pos, 1024 - size, "%s", _fmt); - pos += n; - - *pos = ' '; - pos++; - - size += n + 1; - count++; - } - *pos = '\0'; - DEBUG("parser format: %s", fmt); - - int ret = sscanf(params_s, fmt, sscanf_params[0], sscanf_params[1], - sscanf_params[2], sscanf_params[3], sscanf_params[4], - sscanf_params[5], sscanf_params[6], sscanf_params[7], - sscanf_params[8], sscanf_params[9]); - if (ret != parser->nparams) { - ERROR("Parsing failed: check for string used where integer was expected"); - goto ERR; - } - - for (unsigned i = 0; i < count; i++) { - const command_parameter_t *p = &parser->parameters[i]; - if (parser_type_func(&p->type, sscanf_params[i], - &command->object.as_uint8 + p->offset, - &command->object.as_uint8 + p->offset2, - &command->object.as_uint8 + p->offset3) < 0) { - ERROR("Error during parsing of parameter '%s' value", p->name); - goto ERR; - } - } - return 0; - -ERR: - return -1; -} - -int parse(const char *cmd, hc_command_t *command) { - int nparams = 0; - char action_s[MAX_SCANF_PARAM_LEN]; - char object_s[MAX_SCANF_PARAM_LEN]; - char params_s[MAX_SCANF_PARAM_LEN]; - - // if n = 2 later, params_s is uninitialized - memset(params_s, 0, MAX_SCANF_PARAM_LEN * sizeof(char)); - - errno = 0; - int n = sscanf(cmd, "%s %s%[^\n]s", action_s, object_s, params_s); - if ((n < 2) || (n > 3)) { - if (errno != 0) perror("scanf"); - return -1; - } - - command->action = action_from_str(action_s); - command->object.type = object_from_str(object_s); - - if (strnlen_s(params_s, MAX_SCANF_PARAM_LEN) > 0) { - for (char *ptr = params_s; (ptr = strchr(ptr, ' ')) != NULL; ptr++) - nparams++; - } - - /* - * This checks is important even with 0 parameters as it checks whether the - * command exists. - */ - const command_parser_t *parser = - command_search(command->action, command->object.type, nparams); - if (!parser) { - ERROR("Could not find parser for command '%s %s'", action_s, object_s); - return -1; - } - - if (strnlen_s(params_s, MAX_SCANF_PARAM_LEN) > 0) { - if (parse_params(parser, params_s, command) < 0) return -1; - } - - if (parser->post_hook) parser->post_hook(&command->object.as_uint8); - return 0; -} - -int help(const char *cmd) { - int nparams = 1; - char action_s[MAX_SCANF_PARAM_LEN]; - char object_s[MAX_SCANF_PARAM_LEN]; - char params_s[MAX_SCANF_PARAM_LEN]; - hc_object_type_t object = OBJECT_UNDEFINED; - hc_action_t action = ACTION_UNDEFINED; - - int n = sscanf(cmd, "help %[^\n]s", params_s); - - // No arguments provided to the help command: just list available objects - if (n != 1) goto CMD_LIST; - - // Count number of provided parameters - for (char *ptr = params_s; (ptr = strchr(ptr, ' ')) != NULL; ptr++) nparams++; - if (nparams > 2) { - fprintf(stderr, "Error: too many arguments.\n"); - return -1; - } - - // Object specified: list actions available for that object - if (nparams == 1) { - object = object_from_str(params_s); - if (object == OBJECT_UNDEFINED) { - fprintf(stderr, "Error: undefined object.\n"); - return -1; - } - - goto CMD_LIST; - } - - // Object and action specified: list detailed commands - n = sscanf(params_s, "%s %[^\n]s", object_s, action_s); - assert(n == 2); - object = object_from_str(object_s); - action = action_from_str(action_s); - if (object == OBJECT_UNDEFINED || action == ACTION_UNDEFINED) { - fprintf(stderr, "Error: undefined object and/or action.\n"); - return -1; - } - -CMD_LIST: - printf("Available commands:\n"); - command_list(object, action); - return 0; -} - -#if 0 // tests -/* For the tests, we will need to test all non-compliant inputs */ -const char * cmds[] = { - "add connection hicn conn1 8.8.8.8 127.0.0.1 eth0", - "add connection udp <symbolic> <remote_ip> <port> <local_ip> <port> eth0", - "add listener udp lst1 127.0.0.1 9695 eth0", - //"add face", - "add route 3 b001::/16 1", - //"add punting", - //"add strategy", - "add policy b001::/16 webex require avoid prohibit !prohibit neutral !require prefer", - "list connection", // need pluralize - "list listener", - "list face", - "list route", - "list punting", - "list strategy", - "list policy", - "remove connection 1", - "remove listener 1", - //"remove face", - "remove route 1 b001::/16", - //"remove punting", - //"remove policy", - "set debug", - "unset debug", - "set strategy b001::/16 random", // related prefixes (10 max) ? - "set strategy b001::/16 load_balancer", - "set strategy b001::/16 low_latency", - "set strategy b001::/16 replication", - "set strategy b001::/16 bestpath", - "set wldr <on|off> <connection_id>", // on-off vs unset - "cache clear", - "cache store on/off", // set/unset - "cache serve on/off", - "mapme enable on/off", - "mapme discovery on/off", - "mapme timescale 500ms", - "mapme retx 500ms", - "update connection conn1 WT", -}; - -#define array_size(x) sizeof(x) / sizeof(typeof(x[0])) -int main() -{ - for (unsigned i = 0; i < array_size(cmds); i++) { - printf("PARSING [%d] %s\n", i, cmds[i]); - if (parse(cmds[i]) < 0) { - ERROR("Could not parse command: %s\n", cmds[i]); - continue; - } - } - exit(EXIT_SUCCESS); - -ERR: - exit(EXIT_FAILURE); -} -#endif diff --git a/hicn-light/src/hicn/config/parse.h b/hicn-light/src/hicn/config/parse.h deleted file mode 100644 index 06269208a..000000000 --- a/hicn-light/src/hicn/config/parse.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef HICNLIGHT_PARSE_CMD -#define HICNLIGHT_PARSE_CMD - -#include <hicn/ctrl/api.h> - -int parse(const char* cmd, hc_command_t* command); -int help(const char* cmd); - -/** - * @brief Convert the action enum to the action name used in the commands (e.g. - * from ACTION_CREATE to "add"). - */ -const char* action_to_cmd_action(hc_action_t action); - -#endif /* HICNLIGHT_PARSE_CMD */ diff --git a/hicn-light/src/hicn/core/CMakeLists.txt b/hicn-light/src/hicn/core/CMakeLists.txt index 9516a6a72..94295bdf1 100644 --- a/hicn-light/src/hicn/core/CMakeLists.txt +++ b/hicn-light/src/hicn/core/CMakeLists.txt @@ -3,7 +3,7 @@ # 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 +# 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, @@ -21,7 +21,6 @@ list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/fib_entry.h ${CMAKE_CURRENT_SOURCE_DIR}/fib.h ${CMAKE_CURRENT_SOURCE_DIR}/forwarder.h - ${CMAKE_CURRENT_SOURCE_DIR}/interest_manifest.h ${CMAKE_CURRENT_SOURCE_DIR}/listener.h ${CMAKE_CURRENT_SOURCE_DIR}/listener_table.h ${CMAKE_CURRENT_SOURCE_DIR}/listener_vft.h @@ -34,13 +33,11 @@ list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/strategy_vft.h ${CMAKE_CURRENT_SOURCE_DIR}/subscription.h ${CMAKE_CURRENT_SOURCE_DIR}/ticks.h -# ${CMAKE_CURRENT_SOURCE_DIR}/system.h + + # ${CMAKE_CURRENT_SOURCE_DIR}/system.h ${CMAKE_CURRENT_SOURCE_DIR}/mapme.h ${CMAKE_CURRENT_SOURCE_DIR}/wldr.h - ${CMAKE_CURRENT_SOURCE_DIR}/messageHandler.h - ${CMAKE_CURRENT_SOURCE_DIR}/nameBitvector.h ${CMAKE_CURRENT_SOURCE_DIR}/nexthops.h - ${CMAKE_CURRENT_SOURCE_DIR}/name.h ) list(APPEND SOURCE_FILES @@ -53,15 +50,12 @@ list(APPEND SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/fib.c ${CMAKE_CURRENT_SOURCE_DIR}/fib_entry.c ${CMAKE_CURRENT_SOURCE_DIR}/forwarder.c - ${CMAKE_CURRENT_SOURCE_DIR}/interest_manifest.c ${CMAKE_CURRENT_SOURCE_DIR}/listener.c ${CMAKE_CURRENT_SOURCE_DIR}/listener_table.c ${CMAKE_CURRENT_SOURCE_DIR}/listener_vft.c ${CMAKE_CURRENT_SOURCE_DIR}/mapme.c ${CMAKE_CURRENT_SOURCE_DIR}/msgbuf.c ${CMAKE_CURRENT_SOURCE_DIR}/msgbuf_pool.c - ${CMAKE_CURRENT_SOURCE_DIR}/nameBitvector.c - ${CMAKE_CURRENT_SOURCE_DIR}/name.c ${CMAKE_CURRENT_SOURCE_DIR}/nexthops.c ${CMAKE_CURRENT_SOURCE_DIR}/packet_cache.c ${CMAKE_CURRENT_SOURCE_DIR}/pit.c diff --git a/hicn-light/src/hicn/core/address.c b/hicn-light/src/hicn/core/address.c index a4b41c8b5..65664fa17 100644 --- a/hicn-light/src/hicn/core/address.c +++ b/hicn-light/src/hicn/core/address.c @@ -21,8 +21,8 @@ #include <hicn/core/address.h> #include <hicn/util/sstrncpy.h> -int address_from_ip_port(address_t *address, int family, ip_address_t *addr, - uint16_t port) { +int address_from_ip_port(address_t *address, int family, + hicn_ip_address_t *addr, uint16_t port) { switch (family) { case AF_INET: *address = ADDRESS4(ntohl(addr->v4.as_inaddr.s_addr), ntohs(port)); diff --git a/hicn-light/src/hicn/core/address.h b/hicn-light/src/hicn/core/address.h index 7958bd063..38cd1e87c 100644 --- a/hicn-light/src/hicn/core/address.h +++ b/hicn-light/src/hicn/core/address.h @@ -63,8 +63,8 @@ static inline bool _address6_is_local(struct sockaddr_in6 *sin6) { ((address)->as_ss.ss_family == AF_INET) ? address4_is_local(address) \ : address6_is_local(address) -int address_from_ip_port(address_t *address, int family, ip_address_t *addr, - uint16_t port); +int address_from_ip_port(address_t *address, int family, + hicn_ip_address_t *addr, uint16_t port); static inline address_t ADDRESS4(in_addr_t in_addr, int port) { address_t address = { diff --git a/hicn-light/src/hicn/core/address_pair.c b/hicn-light/src/hicn/core/address_pair.c index facbb8dc4..c4f8b397b 100644 --- a/hicn-light/src/hicn/core/address_pair.c +++ b/hicn-light/src/hicn/core/address_pair.c @@ -30,8 +30,10 @@ address_pair_t address_pair_factory(address_t local, address_t remote) { } int address_pair_from_ip_port(address_pair_t* pair, int family, - ip_address_t* local_addr, uint16_t local_port, - ip_address_t* remote_addr, uint16_t remote_port) { + hicn_ip_address_t* local_addr, + uint16_t local_port, + hicn_ip_address_t* remote_addr, + uint16_t remote_port) { memset(pair, 0, sizeof(*pair)); if (address_from_ip_port(&pair->local, family, local_addr, local_port) < 0) return -1; diff --git a/hicn-light/src/hicn/core/address_pair.h b/hicn-light/src/hicn/core/address_pair.h index 2fd207d34..b2872ad35 100644 --- a/hicn-light/src/hicn/core/address_pair.h +++ b/hicn-light/src/hicn/core/address_pair.h @@ -40,8 +40,10 @@ typedef struct { address_pair_t address_pair_factory(address_t local, address_t remote); int address_pair_from_ip_port(address_pair_t* pair, int family, - ip_address_t* local_addr, uint16_t local_port, - ip_address_t* remote_addr, uint16_t remote_port); + hicn_ip_address_t* local_addr, + uint16_t local_port, + hicn_ip_address_t* remote_addr, + uint16_t remote_port); static inline int address_pair_equals(const address_pair_t* pair1, const address_pair_t* pair2) { diff --git a/hicn-light/src/hicn/core/connection.c b/hicn-light/src/hicn/core/connection.c index 2108d30af..ff73a9ae8 100644 --- a/hicn-light/src/hicn/core/connection.c +++ b/hicn-light/src/hicn/core/connection.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -22,8 +22,9 @@ #include <hicn/core/forwarder.h> #include <hicn/core/listener.h> -#include <hicn/util/log.h> #include <hicn/core/wldr.h> +#include <hicn/policy.h> +#include <hicn/util/log.h> #include "connection.h" #include "connection_vft.h" @@ -31,7 +32,7 @@ // This is called by configuration connection_t *connection_create(face_type_t type, const char *name, const address_pair_t *pair, - forwarder_t *forwarder) { + const forwarder_t *forwarder) { assert(face_type_is_valid(type)); assert(pair); assert(forwarder); @@ -70,6 +71,38 @@ connection_t *connection_create(face_type_t type, const char *name, return connection_table_at(table, connection_id); } +netdevice_type_t connection_get_netdevice_type(const char *interface_name) { + if (strncmp(interface_name, "lo", 2) == 0) { + return NETDEVICE_TYPE_LOOPBACK; + } + if ((strncmp(interface_name, "eth", 3) == 0) || + (strncmp(interface_name, "en", 2) == 0)) { + /* eth* en* enx* */ + return NETDEVICE_TYPE_WIRED; + } + if (strncmp(interface_name, "wl", 2) == 0) { + /* wlan* wlp* wlx* */ + return NETDEVICE_TYPE_WIFI; + } + if (strncmp(interface_name, "rmnet_ipa", 9) == 0) { + /* Qualcomm IPA driver */ + return NETDEVICE_TYPE_UNDEFINED; + } + if ((strncmp(interface_name, "rmnet", 5) == 0) || + (strncmp(interface_name, "rev_rmnet", 9) == 0) || + (strncmp(interface_name, "ccmni", 5) == 0)) { + /* + * rmnet* (Qualcomm) ccmni* (MediaTek) + */ + return NETDEVICE_TYPE_CELLULAR; + } + /* usb0 might be cellular (eg Zenfone2) */ + /* what about tethering */ + /* tun* dummy* ... */ + /* bnet* pan* hci* for bluetooth */ + return NETDEVICE_TYPE_UNDEFINED; +} + /** * @brief Initializes a connection * @@ -122,6 +155,30 @@ int connection_initialize(connection_t *connection, face_type_t type, .wldr_autostart = true, }; + connection->interface_type = + connection_get_netdevice_type(connection->interface_name); + +#ifdef WITH_POLICY + connection_clear_tags(connection); + switch (connection->interface_type) { +#if 0 + case NETDEVICE_TYPE_LOOPBACK: + connection_add_tag(connection, POLICY_TAG_LOOPBACK); + break; +#endif + case NETDEVICE_TYPE_WIRED: + connection_add_tag(connection, POLICY_TAG_WIRED); + break; + case NETDEVICE_TYPE_WIFI: + connection_add_tag(connection, POLICY_TAG_WIFI); + break; + case NETDEVICE_TYPE_CELLULAR: + connection_add_tag(connection, POLICY_TAG_CELLULAR); + default: + break; + } +#endif + connection->data = malloc(connection_vft[get_protocol(connection->type)]->data_size); if (!connection->data) goto ERR_DATA; @@ -200,8 +257,8 @@ int connection_finalize(connection_t *connection) { return 0; } -int connection_send_packet(const connection_t *connection, - const uint8_t *packet, size_t size) { +bool connection_send_packet(const connection_t *connection, + const uint8_t *packet, size_t size) { assert(connection); assert(face_type_is_valid(connection->type)); assert(packet); @@ -231,10 +288,12 @@ bool connection_send(connection_t *connection, off_t msgbuf_id, bool queue) { const msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder); msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); +#if 0 if (connection->wldr) wldr_set_label(connection->wldr, msgbuf); else msgbuf_reset_wldr_label(msgbuf); +#endif return _connection_send(connection, msgbuf, queue); } diff --git a/hicn-light/src/hicn/core/connection.h b/hicn-light/src/hicn/core/connection.h index ac75428dd..b459a6d81 100644 --- a/hicn-light/src/hicn/core/connection.h +++ b/hicn-light/src/hicn/core/connection.h @@ -33,25 +33,30 @@ #define CONNECTION_ID_UNDEFINED ~0 -#ifdef WITH_MAPME +#define foreach_connection_event \ + _(UNDEFINED) \ + _(CREATE) \ + _(DELETE) \ + _(UPDATE) \ + _(SET_UP) \ + _(SET_DOWN) \ + _(PRIORITY_CHANGED) \ + _(TAGS_CHANGED) \ + _(N) + typedef enum { - CONNECTION_EVENT_CREATE, - CONNECTION_EVENT_DELETE, - CONNECTION_EVENT_UPDATE, - CONNECTION_EVENT_SET_UP, - CONNECTION_EVENT_SET_DOWN, - CONNECTION_EVENT_PRIORITY_CHANGED, - CONNECTION_EVENT_TAGS_CHANGED, +#define _(x) CONNECTION_EVENT_##x, + foreach_connection_event +#undef _ } connection_event_t; -#endif /* WITH_MAPME */ - struct wldr_s; typedef struct { unsigned id; char* name; char* interface_name; + netdevice_type_t interface_type; face_type_t type; address_pair_t pair; // bool up; @@ -111,6 +116,7 @@ typedef struct { #define connection_get_admin_state(C) ((C)->admin_state) #define connection_set_admin_state(C, STATE) (C)->admin_state = STATE #define connection_get_interface_name(C) ((C)->interface_name) +#define connection_get_interface_type(C) ((C)->interface_type) #ifdef WITH_POLICY #define connection_get_priority(C) ((C)->priority) @@ -118,7 +124,7 @@ typedef struct { #define connection_get_tags(C) ((C)->tags) #define connection_set_tags(C, TAGS) (C)->tags = TAGS #define connection_has_tag(C, TAG) policy_tags_has(connection_get_tags(C), TAG) -#define connection_add_tag(C, TAG) policy_tags_add(connection_get_tags(X), TAG) +#define connection_add_tag(C, TAG) policy_tags_add(&connection_get_tags(C), TAG) #define connection_remove_tag(C, TAG) \ do { \ policy_tags_t _conn_var(tags); \ @@ -198,7 +204,7 @@ static inline void connection_set_tags(connection_t* connection, connection_t* connection_create(face_type_t type, const char* name, const address_pair_t* pair, - struct forwarder_s* forwarder); + const struct forwarder_s* forwarder); int connection_initialize(connection_t* connection, face_type_t type, const char* name, const char* interface_name, int fd, @@ -207,8 +213,8 @@ int connection_initialize(connection_t* connection, face_type_t type, int connection_finalize(connection_t* connection); -int connection_send_packet(const connection_t* connection, - const uint8_t* packet, size_t size); +bool connection_send_packet(const connection_t* connection, + const uint8_t* packet, size_t size); bool connection_flush(connection_t* connection); diff --git a/hicn-light/src/hicn/core/connection_table.c b/hicn-light/src/hicn/core/connection_table.c index c723073a1..7bc0e2f4c 100644 --- a/hicn-light/src/hicn/core/connection_table.c +++ b/hicn-light/src/hicn/core/connection_table.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -81,6 +81,14 @@ connection_t *connection_table_allocate(const connection_table_t *table, pool_get(table->connections, conn); if (!conn) return NULL; +#ifdef __APPLE__ + // set __uint8_t sin_len to 0 + uint8_t *ptr = (uint8_t *)address_pair_get_local(pair); + *ptr = 0x0; + ptr = (uint8_t *)address_pair_get_remote(pair); + *ptr = 0x0; +#endif /* __APPLE__ */ + off_t id = conn - table->connections; int rc; @@ -106,6 +114,14 @@ void connection_table_deallocate(const connection_table_t *table, const char *name = connection_get_name(conn); const address_pair_t *pair = connection_get_pair(conn); +#ifdef __APPLE__ + // set __uint8_t sin_len to 0 + uint8_t *ptr = (uint8_t *)address_pair_get_local(pair); + *ptr = 0x0; + ptr = (uint8_t *)address_pair_get_remote(pair); + *ptr = 0x0; +#endif /* __APPLE__ */ + // Remove from name hash table khiter_t k = kh_get_ct_name(table->id_by_name, name); assert(k != kh_end(table->id_by_name)); @@ -124,6 +140,14 @@ void connection_table_deallocate(const connection_table_t *table, connection_t *connection_table_get_by_pair(const connection_table_t *table, const address_pair_t *pair) { +#ifdef __APPLE__ + // set __uint8_t sin_len to 0 + uint8_t *ptr = (uint8_t *)address_pair_get_local(pair); + *ptr = 0x0; + ptr = (uint8_t *)address_pair_get_remote(pair); + *ptr = 0x0; +#endif /* __APPLE__ */ + khiter_t k = kh_get_ct_pair(table->id_by_pair, pair); if (k == kh_end(table->id_by_pair)) return NULL; return table->connections + kh_val(table->id_by_pair, k); @@ -196,7 +220,7 @@ int connection_table_get_random_name(const connection_table_t *table, int i, n_attempts = 2 * USHRT_MAX; for (i = 0; i < n_attempts; i++) { int rc = snprintf(name, SYMBOLIC_NAME_LEN, "conn%u", RAND16()); - if (rc >= SYMBOLIC_NAME_LEN) continue; + if (rc < 0 || rc >= SYMBOLIC_NAME_LEN) continue; // Check if generated connection name is a duplicate khiter_t k = kh_get_ct_name(table->id_by_name, name); @@ -209,4 +233,4 @@ int connection_table_get_random_name(const connection_table_t *table, } return 0; -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/core/connection_table.h b/hicn-light/src/hicn/core/connection_table.h index 7d4bad761..566443d93 100644 --- a/hicn-light/src/hicn/core/connection_table.h +++ b/hicn-light/src/hicn/core/connection_table.h @@ -160,11 +160,14 @@ connection_t *_connection_table_get_by_id(connection_table_t *table, off_t id); * @return off_t The index of the specified connection in the connection table. */ #define connection_table_get_connection_id(table, conn) \ - (conn - table->connections) + (unsigned)(conn - table->connections) #define connection_table_foreach(table, conn, BODY) \ pool_foreach(table->connections, (conn), BODY) +#define connection_table_foreach_new(table, CONN, BODY) \ + pool_foreach_typed(table->connections, connection_t *, CONN, BODY) + #define connection_table_enumerate(table, i, conn, BODY) \ pool_enumerate(table->connections, (i), (conn), BODY) diff --git a/hicn-light/src/hicn/core/connection_vft.h b/hicn-light/src/hicn/core/connection_vft.h index 1a6ecbb78..cc736905c 100644 --- a/hicn-light/src/hicn/core/connection_vft.h +++ b/hicn-light/src/hicn/core/connection_vft.h @@ -30,8 +30,8 @@ typedef struct { const address_t* remote, const char* interface_name); bool (*flush)(connection_t* connection); bool (*send)(connection_t* connection, msgbuf_t* msgbuf, bool queue); - int (*send_packet)(const connection_t* connection, const uint8_t* packet, - size_t size); + bool (*send_packet)(const connection_t* connection, const uint8_t* packet, + size_t size); // void (*read_callback)(connection_t * connection, int fd, void * data); size_t data_size; } connection_ops_t; diff --git a/hicn-light/src/hicn/core/fib.c b/hicn-light/src/hicn/core/fib.c index d8d3c7cfa..64dd3fe7d 100644 --- a/hicn-light/src/hicn/core/fib.c +++ b/hicn-light/src/hicn/core/fib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -19,20 +19,21 @@ #include <hicn/core/fib.h> typedef struct fib_node_s { - struct fib_node_s *left; - struct fib_node_s *right; + struct fib_node_s *child[2]; /* 0: left, 1: right */ fib_entry_t *entry; bool is_used; } fib_node_t; +#define ZERO 0 +#define ONE 1 + static fib_node_t *fib_node_create(fib_node_t *left, fib_node_t *right, fib_entry_t *entry, bool is_used) { fib_node_t *node = malloc(sizeof(fib_node_t)); if (!node) return NULL; *node = (fib_node_t){ - .left = left, - .right = right, + .child = {left, right}, .entry = entry, .is_used = is_used, }; @@ -43,8 +44,8 @@ static fib_node_t *fib_node_create(fib_node_t *left, fib_node_t *right, static void fib_node_free(fib_node_t *node) { if (!node) return; - fib_node_free(node->right); - fib_node_free(node->left); + fib_node_free(node->child[ZERO]); + fib_node_free(node->child[ONE]); fib_entry_free(node->entry); free(node); @@ -82,293 +83,387 @@ size_t fib_get_size(const fib_t *fib) { return fib->size; } -#define FIB_SET(CURR, NEW_PREFIX, CURR_PREFIX_LEN) \ - do { \ - bool bit; \ - int res = nameBitvector_testBit(NEW_PREFIX, CURR_PREFIX_LEN, &bit); \ - assert(res >= 0); \ - (void)res; /* unused */ \ - CURR = bit ? CURR->right : CURR->left; \ - } while (0) - -#define FIB_INSERT(DST, SRC, PREFIX, PREFIX_LEN) \ - do { \ - bool bit; \ - int res = nameBitvector_testBit(PREFIX, PREFIX_LEN, &bit); \ - assert(res >= 0); \ - (void)res; /* unused */ \ - if (bit) \ - DST->right = SRC; \ - else \ - DST->left = SRC; \ - } while (0) - -void fib_add(fib_t *fib, fib_entry_t *entry) { - assert(fib); - assert(entry); +/* + * This struct will hold various information related to the returned node such + * as its parent and grandparent if any, as well as some already computed + * information about the prefix. + */ +typedef struct { + /* Result node ancestors (NULL if not applicable) */ + fib_node_t *parent; + fib_node_t *gparent; + /* Information related to the result node */ + hicn_prefix_t *prefix; + uint32_t prefix_len; + uint32_t match_len; +} fib_search_t; +/* + * @brief Search for longest subprefix (helper function) + * @param [in] fib - Pointer to the FIB to search + * @param [in] prefix - The prefix used for search + * @param [out] search - A pointer to a structure that will hold related search + * information, that can be NULL if this is not needed. + * + * @returns The node whose entry corresponds to the longest subprefix of the + * prefix passed in parameter, or NULL if not found. The longest prefix match is + * thus the resulting node if curr_len == prefix_len, and its parent + * otherwise. + * + * Implementation details: + * + * This function performs a descent in the tree, following branches + * corresponding to the value of the next bit, until reaching past a leaf, or + * either the current node prefix: + * when one of the two following conditions is met: + * - is not a prefix of the searched one (match_len < curr_len), or + * - is longer or equal than the inserted one (curr_len >= prefix_len) + */ +fib_node_t *fib_search(const fib_t *fib, const hicn_prefix_t *prefix, + fib_search_t *search) { + uint32_t prefix_len = hicn_prefix_get_len(prefix); + uint32_t curr_len; + uint32_t match_len; - NameBitvector *new_prefix = name_GetContentName(fib_entry_get_prefix(entry)); - uint32_t new_prefix_len = nameBitvector_GetLength(new_prefix); + fib_node_t *parent = NULL; + fib_node_t *gparent = NULL; fib_node_t *curr = fib->root; - fib_node_t *last = NULL; + while (curr) { + const hicn_prefix_t *curr_prefix = fib_entry_get_prefix(curr->entry); + curr_len = hicn_prefix_get_len(curr_prefix); + match_len = hicn_prefix_lpm(prefix, curr_prefix); + + // XXX >= vs == for the second stop condition + // curr_len >= prefix_len l >= L + // L is a prefix of l + // > means we did not find + // = means we could have found + // leverage this info for contains! + // XXX remove this comment when done + if (match_len < curr_len || curr_len >= prefix_len) break; + + gparent = parent; + parent = curr; - NameBitvector *curr_name; - uint32_t curr_prefix_len; - uint32_t match_len; + /* The following lookup won't fail since curr_len < prefix_len */ + uint8_t next_bit = hicn_prefix_get_bit(prefix, curr_len); + curr = curr->child[next_bit]; + } - while (curr) { - curr_name = name_GetContentName(fib_entry_get_prefix(curr->entry)); + if (search) { + search->parent = parent; + search->gparent = gparent; + if (curr) { + search->prefix_len = curr_len; + search->match_len = match_len; + } + } + return curr; +} - match_len = nameBitvector_lpm(new_prefix, curr_name); - curr_prefix_len = nameBitvector_GetLength(curr_name); +/* + * Helper: insert a new node between parent and child. + * + * parent == NULL means we set the root of the FIB + * child == NULL means our node has no child + */ +fib_node_t *_fib_insert(fib_t *fib, fib_entry_t *entry, fib_node_t *parent, + fib_node_t *child, bool is_used) { + fib_node_t *new_node = fib_node_create(NULL, NULL, entry, is_used); + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); - if (curr_prefix_len != - match_len || // the new entry does not match the curr - curr_prefix_len >= - new_prefix_len) // in this case we cannot procede anymore - break; + if (!parent) { + fib->root = new_node; + } else { + const hicn_prefix_t *parent_prefix = fib_entry_get_prefix(parent->entry); + uint32_t parent_prefix_len = hicn_prefix_get_len(parent_prefix); + uint8_t next_bit = hicn_prefix_get_bit(prefix, parent_prefix_len); + parent->child[next_bit] = new_node; + } - last = curr; - FIB_SET(curr, new_prefix, curr_prefix_len); + if (child) { + const hicn_prefix_t *curr_prefix = fib_entry_get_prefix(entry); + uint32_t match_len = hicn_prefix_lpm(prefix, curr_prefix); + uint8_t next_bit = hicn_prefix_get_bit(curr_prefix, match_len); + new_node->child[next_bit] = child; } - // this is the root (empty trie) or an empty child - if (!curr) { - fib_node_t *new_node = fib_node_create(NULL, NULL, entry, true); - if (!last) { - fib->root = new_node; - } else { - uint32_t last_prefix_len = nameBitvector_GetLength( - name_GetContentName(fib_entry_get_prefix(last->entry))); + if (is_used) fib->size++; + return new_node; +} - FIB_INSERT(last, new_node, new_prefix, last_prefix_len); - } - fib->size++; - return; +/* + * Helper: remove a node from parent + */ +void _fib_remove(fib_t *fib, fib_node_t *curr, fib_node_t *parent) { + /* + * If we remove the node, curr has either 0 or 1 child. In the latter case, + * we attach it to parent + */ + fib_node_t *child = curr->child[ZERO] ? curr->child[ZERO] : curr->child[ONE]; + if (!parent) { + fib->root = child; + } else { + if (parent->child[ZERO] == curr) + parent->child[ZERO] = child; + else + parent->child[ONE] = child; } + if (curr->is_used) fib->size--; + fib_node_free(curr); +} + +/* + * - Stop condition: curr == NULL. This corresponds to: + * + * (CASE 1) Our parent is a strict prefix and we simply have to create a new + * leaf child in the correct branch based on the next bit following the parent + * prefix. + * + * Otherwise, our parent node exist. Based on the stop condition, we + * either have: + * + * - Stop condition 1 : curr_len == match_len AND curr_len >= + * prefix_len l == m && l >= L + * + * 2 sub-cases: + * - l = m > L : IMPOSSIBLE L < m since m = LPM(l, L) means L >= m + * - l = m = L : insert the current node, either it exists or not + * + * We thus have: + * + * (CASE 2) The node already exist. If is not in use we turn it on and we set + * the right fib entry. + * + * The case when it is used should never occur because of the way we add + * entries in the FIB... but let's add the nexthops we wish to insert into + * the existing FIB entry. + * + * - Stop condition 2: curr_len != match_len + * l != m => l > m + * + * We have two possibilities: + * - Only one is bigger than m (case 3) + * - They are both bigger than m (case 4) + * + * (CASE 3) Only one is bigger than m + * L == m => L < l (since l != m and l >= m) + * l > L = m + * + * This means L is a prefix of l. + * l' + * / + * L + * / + * l + * + * (CASE 4) They are both bigger than m + * - l > L > m + * - L > l > m + * - L = l > m + * + * Both share L and l share l' as a common prefix, and this is not l' since + * they share the name next bit. + * + * So this case is impossible and we would have taken the other branch during + * the descent: + * + * l' + * / \ + * l L + * + * We are in a situation where e need to insert an internal node: + * + * l' + * | + * X <------ internal node + * / \ + * l L + */ +void fib_add(fib_t *fib, fib_entry_t *entry) { + assert(fib); + assert(entry); + + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); + uint32_t prefix_len = hicn_prefix_get_len(prefix); + + fib_search_t search; + fib_node_t *curr = fib_search(fib, prefix, &search); - // curr is not null + /* Case 1 */ + if (!curr) { + _fib_insert(fib, entry, search.parent, NULL, true); + return; + } - // the node already exist - // if is not in use we turn it on and we set the rigth fib entry - if (curr_prefix_len == match_len && new_prefix_len == match_len) { + /* Case 2 */ + if (search.prefix_len == search.match_len && prefix_len == search.match_len) { if (!curr->is_used) { curr->is_used = true; + if (curr->entry) fib_entry_free(curr->entry); curr->entry = entry; fib->size++; - return; } else { - // this case should never happen beacuse of the way we add - // entries in the fib const nexthops_t *nexthops = fib_entry_get_nexthops(entry); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { fib_entry_nexthops_add(curr->entry, nexthop); }); + fib_entry_free(entry); } + return; } - // key is prefix of the curr node (so new_prefix_len < curr_prefix_len) - if (new_prefix_len == match_len) { - fib_node_t *new_node = fib_node_create(NULL, NULL, entry, true); - if (!last) { - fib->root = new_node; - } else { - uint32_t last_prefix_len = nameBitvector_GetLength( - name_GetContentName(fib_entry_get_prefix(last->entry))); - FIB_INSERT(last, new_node, new_prefix, last_prefix_len); - } - FIB_INSERT(new_node, curr, curr_name, match_len); - fib->size++; + /* Case 3 */ + if (prefix_len == search.match_len) { + _fib_insert(fib, entry, search.parent, curr, true); return; } - // in the last case we need to add an inner node - Name inner_prefix = EMPTY_NAME; - name_Copy(fib_entry_get_prefix(entry), &inner_prefix); - nameBitvector_clear(name_GetContentName(&inner_prefix), match_len); - name_setLen(&inner_prefix, match_len); - - // this is an inner node, we don't want an acctive strategy - // like low_latency that sends probes in this node + /* Case 4 */ + hicn_prefix_t inner_prefix; /* dup'ed in fib_entry_create */ + hicn_prefix_copy(&inner_prefix, prefix); + hicn_prefix_truncate(&inner_prefix, search.match_len); fib_entry_t *inner_entry = fib_entry_create( &inner_prefix, STRATEGY_TYPE_UNDEFINED, NULL, fib->forwarder); - - fib_node_t *inner_node = fib_node_create(NULL, NULL, inner_entry, false); - fib_node_t *new_node = fib_node_create(NULL, NULL, entry, true); - - if (!last) { - // we need to place the inner_node at the root - fib->root = inner_node; - } else { - uint32_t last_prefix_len = nameBitvector_GetLength( - name_GetContentName(fib_entry_get_prefix(last->entry))); - NameBitvector *inner_name = name_GetContentName(&inner_prefix); - FIB_INSERT(last, inner_node, inner_name, last_prefix_len); - } - - bool bit; - int res = nameBitvector_testBit(new_prefix, match_len, &bit); - assert(res >= 0); - (void)res; /* unused */ - inner_node->left = bit ? curr : new_node; - inner_node->right = bit ? new_node : curr; - fib->size++; + fib_node_t *new_node = + _fib_insert(fib, inner_entry, search.parent, curr, false); + _fib_insert(fib, entry, new_node, NULL, true); } -fib_entry_t *fib_contains(const fib_t *fib, const Name *prefix) { +/* + * Implementation details: + * + * To find whether the fib contains a prefix, we issue a search, and based on + * the stopping conditions, we return the entry if and only if curr + * is not NULL, and prefix_len == curr_len (== match_len) + */ +fib_entry_t *fib_contains(const fib_t *fib, const hicn_prefix_t *prefix) { assert(fib); assert(prefix); - NameBitvector *key_name = name_GetContentName(prefix); - uint32_t key_prefix_len = nameBitvector_GetLength(key_name); + uint32_t prefix_len = hicn_prefix_get_len(prefix); - fib_node_t *curr = fib->root; + fib_search_t search; + fib_node_t *curr = fib_search(fib, prefix, &search); - while (curr) { - NameBitvector *curr_name = - name_GetContentName(fib_entry_get_prefix(curr->entry)); - uint32_t match_len = nameBitvector_lpm(key_name, curr_name); - uint32_t curr_prefix_len = nameBitvector_GetLength(curr_name); - - if (match_len < curr_prefix_len) { - // the current node does not match completelly the key, so - // the key is not in the trie - // this implies curr_prefix_len > key_prefix_len - return NULL; - } - - if (curr_prefix_len == key_prefix_len) { //== match_len - // this is an exact match - if (!curr->is_used) { - // the key does not exists - return NULL; - } - // we found the key - return curr->entry; - } - - FIB_SET(curr, key_name, curr_prefix_len); - } - - return NULL; + if (!curr) return NULL; + if (search.prefix_len != prefix_len) return NULL; + return curr->is_used ? curr->entry : NULL; } -static void fib_node_remove(fib_t *fib, const Name *prefix) { +/* + * @brief Remove a prefix (and the associated node) from FIB + * + * We search for + * + * Actions depend on N, the number of children of the node to remove + * Examples are build using 'left' children only, but the cases with 'right' + * children are symmetrical. + * + * Legend: + * (empty) : no children + * * : 0 or more children + * + : at least one children + * + * N == 2 - Mark the node as unused + * + * parent parent + * / \ / \ + * curr ... ==> (curr) ... + * / \ / \ + * L R L R + * + * N == 1 - Attach the child to the parent node (whether parent is used or not) + * + * a) curr has no parent (curr is the root) + * + * curr + + * / ==> + * + + * + * b) curr has a parent + * parent parent + * / \ / \ + * curr * ==> L * + * / \ + * L + * + * (parent) (parent) + * / \ / \ + * curr + ==> L + + * / \ + * L + * + * N == 0 + * + * a) curr has no parent (curr is the root) + * + * curr + * / \ ==> + * + * b) parent is unused. + * + * Assuming curr is the left child, then parent must have a + * right child, and the grand-parent must be used. + * + * gp gp gp + * / / / + * (parent) ==> (parent) ==> + + * / \ / \ + * curr + + + * / \ + * + * c) parent is used. + * + * Assuming curr is the left child, we simply remove it from + * parent, leaving parent unchanged whether it has a right child or not. + * + * parent parent + * / \ / \ + * curr * ==> * + * / \ + * + * + */ +static void fib_node_remove(fib_t *fib, const hicn_prefix_t *prefix) { assert(fib); assert(prefix); - NameBitvector *key_name = name_GetContentName(prefix); - uint32_t key_prefix_len = nameBitvector_GetLength(key_name); + uint32_t prefix_len = hicn_prefix_get_len(prefix); - fib_node_t *curr = fib->root; - fib_node_t *parent = NULL; - fib_node_t *grandpa = NULL; + fib_search_t search; + fib_node_t *curr = fib_search(fib, prefix, &search); - uint32_t match_len; - uint32_t curr_prefix_len; + /* + * If we reach a NULL, unused node, or a node not matching, that means the + * node does not exist + */ + if (!curr || !curr->is_used || (search.prefix_len != prefix_len)) return; - while (curr) { - NameBitvector *curr_name = - name_GetContentName(fib_entry_get_prefix(curr->entry)); - match_len = nameBitvector_lpm(key_name, curr_name); - curr_prefix_len = nameBitvector_GetLength(curr_name); + uint8_t N = 0; + if (curr->child[ZERO]) N++; + if (curr->child[ONE]) N++; - if (match_len < curr_prefix_len || curr_prefix_len == key_prefix_len) { + switch (N) { + case 2: + curr->is_used = false; break; - } - - grandpa = parent; - parent = curr; - FIB_SET(curr, key_name, curr_prefix_len); - } - - if (!curr || !curr->is_used || (curr_prefix_len != key_prefix_len)) { - // the node does not exists - return; - } - - // curr has 2 children, leave it there and mark it as inner - if (curr->right && curr->left) { - curr->is_used = false; - fib->size--; - return; - } - - // curr has no children - if (!curr->right && !curr->left) { - if (!parent) { - // curr is the root and is the only node in the fib - fib->root = NULL; - fib->size--; - fib_node_free(curr); - return; - } - if (!grandpa) { - // parent is the root - if (fib->root->left == curr) - fib->root->left = NULL; - else - fib->root->right = NULL; - fib->size--; - fib_node_free(curr); - return; - } - if (!parent->is_used) { - // parent is an inner node - // remove curr and inner_node (parent), connect the other child - // of the parent to the grandpa - fib_node_t *tmp = (parent->right == curr) ? parent->left : parent->right; - - if (grandpa->right == parent) - grandpa->right = tmp; - else - grandpa->left = tmp; - - fib->size--; - fib_node_free(curr); - fib_node_free(parent); - return; - } - // parent is node not an inner_node - // just remove curr the node - if (parent->right == curr) - parent->right = NULL; - else - parent->left = NULL; - fib->size--; - fib_node_free(curr); - return; - } - - // curr has one child - if (curr->right || curr->left) { - if (!parent) { - // curr is the root - fib->root = fib->root->right ? fib->root->right : fib->root->left; - fib->size--; - fib_node_free(curr); - return; - } - // attach the child of curr to parent - fib_node_t *tmp = curr->right ? curr->right : curr->left; - - if (parent->right == curr) - parent->right = tmp; - else - parent->left = tmp; + case 1: + _fib_remove(fib, curr, search.parent); + break; - fib->size--; - fib_node_free(curr); - return; + case 0: + _fib_remove(fib, curr, search.parent); + if (!search.parent->is_used) + _fib_remove(fib, search.parent, search.gparent); + break; } } -void fib_remove(fib_t *fib, const Name *name, unsigned conn_id) { +void fib_remove(fib_t *fib, const hicn_prefix_t *prefix, unsigned conn_id) { assert(fib); - assert(name); + assert(prefix); - fib_entry_t *entry = fib_contains(fib, name); + fib_entry_t *entry = fib_contains(fib, prefix); if (!entry) return; fib_entry_nexthops_remove(entry, conn_id); @@ -382,16 +477,24 @@ static size_t fib_node_remove_connection_id(fib_node_t *node, unsigned conn_id, if (!node) return pos; if (node->is_used) { fib_entry_nexthops_remove(node->entry, conn_id); + + /* When using MAP-Me, we keep empty FIB entries */ #ifndef WITH_MAPME if (fib_entry_nexthops_len(node->entry) == 0) array[pos++] = node->entry; #endif /* WITH_MAPME */ } - pos = fib_node_remove_connection_id(node->right, conn_id, array, pos); - pos = fib_node_remove_connection_id(node->left, conn_id, array, pos); + pos = fib_node_remove_connection_id(node->child[ONE], conn_id, array, pos); + pos = fib_node_remove_connection_id(node->child[ZERO], conn_id, array, pos); return pos; } -void fib_remove_connection_id(fib_t *fib, unsigned conn_id) { +void fib_remove_entry(fib_t *fib, fib_entry_t *entry) { + fib_node_remove(fib, fib_entry_get_prefix(entry)); +} + +void fib_remove_connection(fib_t *fib, unsigned conn_id, + fib_entry_t ***removed_entries, + size_t *num_removed_entries) { assert(fib); fib_entry_t **array = malloc(sizeof(fib_entry_t *) * fib->size); @@ -399,61 +502,64 @@ void fib_remove_connection_id(fib_t *fib, unsigned conn_id) { size_t pos = 0; pos = fib_node_remove_connection_id(fib->root, conn_id, array, pos); - for (int i = 0; i < pos; i++) - fib_node_remove(fib, fib_entry_get_prefix(array[i])); - free(array); -} + if (removed_entries) { + /* + * The caller is taking charge of releasing entries (as well as the returned + * array + */ + assert(num_removed_entries); -fib_entry_t *fib_match_message(const fib_t *fib, - const msgbuf_t *interest_msgbuf) { - assert(fib); - assert(interest_msgbuf); + *removed_entries = array; + *num_removed_entries = pos; - return fib_match_bitvector( - fib, name_GetContentName(msgbuf_get_name(interest_msgbuf))); + } else { + for (int i = 0; i < pos; i++) + fib_node_remove(fib, fib_entry_get_prefix(array[i])); + } + free(array); } -fib_entry_t *fib_match_name(const fib_t *fib, const Name *name) { +fib_entry_t *fib_match_msgbuf(const fib_t *fib, const msgbuf_t *msgbuf) { assert(fib); - assert(name); + assert(msgbuf); - return fib_match_bitvector(fib, name_GetContentName(name)); + return fib_match_name(fib, msgbuf_get_name(msgbuf)); } -fib_entry_t *fib_match_bitvector(const fib_t *fib, const NameBitvector *name) { +/* + * Implementation details: + * + * fib_search returns the longest non-strict subprefix. + * - curr == NULL means no such prefix exist and we can return the parent. + * - if we have an exact match (curr_len == key_prefix_len), then we + * return curr unless is_used is false, in which case we return the parent. + * - otherwise, the parent is the longest prefix match + */ +fib_entry_t *fib_match_prefix(const fib_t *fib, const hicn_prefix_t *prefix) { assert(fib); - assert(name); - - uint32_t key_prefix_len = nameBitvector_GetLength(name); + assert(prefix); - fib_node_t *curr = fib->root; - fib_node_t *candidate = NULL; + uint32_t prefix_len = hicn_prefix_get_len(prefix); - while (curr) { - NameBitvector *curr_name = - name_GetContentName(fib_entry_get_prefix(curr->entry)); - uint32_t match_len = nameBitvector_lpm(name, curr_name); - uint32_t curr_prefix_len = nameBitvector_GetLength(curr_name); - - if (match_len < curr_prefix_len) { - // the current node does not match completelly the key, so - // return the parent of this node (saved in candidate) - break; - } - - if (curr->is_used) candidate = curr; + fib_search_t search; + fib_node_t *curr = fib_search(fib, prefix, &search); - // if we are here match_len == curr_prefix_len (can't be larger) - // so this node is actually a good candidate for a match - if (curr_prefix_len == key_prefix_len) { - // this an exact match, do not continue - break; - } - - FIB_SET(curr, name, curr_prefix_len); + if (!curr) { + /* This can happen with an empty FIB for instance */ + if (!search.parent) return NULL; + return search.parent->entry; } + if ((search.prefix_len <= prefix_len) && curr->is_used) return curr->entry; + if (search.parent) return search.parent->entry; + return NULL; +} - return candidate ? candidate->entry : NULL; +fib_entry_t *fib_match_name(const fib_t *fib, const hicn_name_t *name) { + hicn_prefix_t prefix; + const hicn_name_prefix_t *name_prefix = hicn_name_get_prefix(name); + prefix.name = *name_prefix; + prefix.len = hicn_name_prefix_get_len_bits(name_prefix); + return fib_match_prefix(fib, &prefix); } static size_t fib_node_collect_entries(fib_node_t *node, fib_entry_t **array, @@ -464,8 +570,8 @@ static size_t fib_node_collect_entries(fib_node_t *node, fib_entry_t **array, if (node->is_used) array[pos++] = node->entry; - pos = fib_node_collect_entries(node->right, array, pos); - pos = fib_node_collect_entries(node->left, array, pos); + pos = fib_node_collect_entries(node->child[ONE], array, pos); + pos = fib_node_collect_entries(node->child[ZERO], array, pos); return pos; } @@ -476,3 +582,123 @@ size_t fib_get_entry_array(const fib_t *fib, fib_entry_t ***array_p) { pos = fib_node_collect_entries(fib->root, *array_p, pos); return pos; } + +bool _fib_is_valid(const fib_node_t *node) { + if (!node) return true; + + const hicn_prefix_t *prefix = fib_entry_get_prefix(node->entry); + uint32_t prefix_len = hicn_prefix_get_len(prefix); + + for (unsigned i = 0; i < 2; i++) { + const fib_node_t *child = node->child[i]; + if (!child) continue; + const hicn_prefix_t *child_prefix = fib_entry_get_prefix(child->entry); + + uint32_t match_len = hicn_prefix_lpm(prefix, child_prefix); + if (match_len != prefix_len) return false; + if (!node->is_used && !child->is_used) return false; + if (hicn_prefix_get_bit(child_prefix, match_len) != i) return false; + if (!_fib_is_valid(child)) return false; + } + return true; +} + +/* + * @brief Check that the structure of the FIB is correct : prefixes are + * correctly nested, 0 are on the left, 1 on the right, and that we have no + * more than 1 unused prefix as parents. + */ +bool fib_is_valid(const fib_t *fib) { return _fib_is_valid(fib->root); } + +/* + * Checks whether the preorder traversal of the sub-tree corresponds to the + * prefix and used arrays, starting from pos (helper) + */ +bool __fib_check_preorder(const fib_node_t *node, + const hicn_prefix_t **prefix_array, bool *used_array, + size_t size, size_t *pos) { + /* Check left subtree... */ + fib_node_t *left = node->child[ZERO]; + if (left && !__fib_check_preorder(left, prefix_array, used_array, size, pos)) + return false; + + /* ... then current node ... */ + if (*pos > size) { + ERROR("size error"); + return false; + } + + const hicn_prefix_t *prefix = fib_entry_get_prefix(node->entry); + + if (!hicn_prefix_equals(prefix, prefix_array[*pos])) { + char buf[MAXSZ_HICN_PREFIX]; + int rc; + + ERROR("Prefix mismatch in position %d %s != %s", pos); + rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(error)"); + ERROR("Expected: %s", buf); + + rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix_array[*pos]); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(error)"); + ERROR("Expected: %s", buf); + return false; + } + + (*pos)++; + + /* ... then right subtree */ + fib_node_t *right = node->child[ONE]; + if (right && + !__fib_check_preorder(right, prefix_array, used_array, size, pos)) + return false; + + return true; +} + +/* + * Checks whether the preorder traversal of the trie + * corresponds to the prefix and used arrays. + */ +bool _fib_check_preorder(const fib_t *fib, const hicn_prefix_t **prefix_array, + bool *used_array, size_t size) { + if (!fib->root) return true; + size_t pos = 0; + if (!__fib_check_preorder(fib->root, prefix_array, used_array, size, &pos)) + return false; + /* We need to check that we don't miss elements */ + return pos == size; +} + +// XXX print empty node but not recurse +void _fib_dump(const fib_node_t *node, int start, int indent) { + char buf[MAXSZ_HICN_PREFIX]; + + if (node) { + const hicn_prefix_t *prefix = fib_entry_get_prefix(node->entry); + int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "%s %d", "(error)", rc); + } else { + snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(null)"); + } + + // Left + if (indent > 0) { + for (int i = 0; i < start - 1; i++) printf(" "); + for (int i = start + 1; i < indent; i++) printf("| "); + printf("|"); + printf("_ %s\n", buf); + } else { + printf("%s\n", buf); + } + + if (!node) return; + + _fib_dump(node->child[ZERO], start, indent + 1); + _fib_dump(node->child[ONE], start + 1, indent + 1); +} + +void fib_dump(const fib_t *fib) { _fib_dump(fib->root, 0, 0); } diff --git a/hicn-light/src/hicn/core/fib.h b/hicn-light/src/hicn/core/fib.h index c0fda960b..501935b0b 100644 --- a/hicn-light/src/hicn/core/fib.h +++ b/hicn-light/src/hicn/core/fib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -18,7 +18,7 @@ #include "fib_entry.h" #include "msgbuf.h" -#include "name.h" +#include <hicn/name.h> #define _fib_var(x) _fib_##x @@ -32,24 +32,39 @@ size_t fib_get_size(const fib_t *fib); void fib_add(fib_t *fib, fib_entry_t *node); -fib_entry_t *fib_contains(const fib_t *fib, const Name *prefix); +fib_entry_t *fib_contains(const fib_t *fib, const hicn_prefix_t *prefix); -void fib_remove(fib_t *fib, const Name *prefix, unsigned conn_id); +void fib_remove(fib_t *fib, const hicn_prefix_t *prefix, unsigned conn_id); -void fib_remove_connection_id(fib_t *fib, unsigned conn_id); +void fib_remove_entry_connection(fib_t *fib, fib_entry_t *entry, + unsigned conn_id, fib_entry_t **removed_entry); -fib_entry_t *fib_match_message(const fib_t *fib, - const msgbuf_t *interest_msgbuf); -fib_entry_t *fib_match_name(const fib_t *fib, const Name *name); -fib_entry_t *fib_match_bitvector(const fib_t *fib, const NameBitvector *name); +void fib_remove_name_connection(fib_t *fib, const hicn_prefix_t *prefix, + unsigned conn_id); + +void fib_remove_entry(fib_t *fib, fib_entry_t *entry); + +void fib_remove_connection(fib_t *fib, unsigned conn_id, + fib_entry_t ***removed_entries, + size_t *num_removed_entries); + +fib_entry_t *fib_match_msgbuf(const fib_t *fib, const msgbuf_t *msgbuf); + +fib_entry_t *fib_match_prefix(const fib_t *fib, const hicn_prefix_t *prefix); + +fib_entry_t *fib_match_name(const fib_t *fib, const hicn_name_t *name); size_t fib_get_entry_array(const fib_t *fib, fib_entry_t ***array_p); +/* + * NOTE : do not use return on the loop body to avoid leaking memory + */ #define fib_foreach_entry(FIB, ENTRY, BODY) \ do { \ fib_entry_t **_fib_var(array); \ size_t _fib_var(n) = fib_get_entry_array((FIB), &_fib_var(array)); \ size_t _fib_var(i); \ + fib_entry_t *ENTRY; \ for (_fib_var(i) = 0; _fib_var(i) < _fib_var(n); _fib_var(i)++) { \ ENTRY = _fib_var(array)[_fib_var(i)]; \ do { \ @@ -59,4 +74,13 @@ size_t fib_get_entry_array(const fib_t *fib, fib_entry_t ***array_p); free(_fib_var(array)); \ } while (0) +bool fib_is_valid(const fib_t *fib); +bool _fib_check_preorder(const fib_t *fib, const hicn_prefix_t **prefix_array, + bool *used_array, size_t size); + +#define fib_check_preorder(F, PA, UA) \ + _fib_check_preorder(F, PA, UA, sizeof(PA) / sizeof(hicn_prefix_t *)) + +void fib_dump(const fib_t *fib); + #endif /* HICNLIGHT_FIB_H */ diff --git a/hicn-light/src/hicn/core/fib_entry.c b/hicn-light/src/hicn/core/fib_entry.c index 80d337884..b588e3638 100644 --- a/hicn-light/src/hicn/core/fib_entry.c +++ b/hicn-light/src/hicn/core/fib_entry.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -18,7 +18,6 @@ #include <hicn/hicn-light/config.h> #include <hicn/core/fib_entry.h> #include <hicn/core/strategy.h> -#include <hicn/core/nameBitvector.h> #ifdef WITH_MAPME #include <hicn/core/ticks.h> @@ -38,17 +37,22 @@ #include <hicn/core/policy_stats.h> #endif /* WITH_POLICY_STATS */ -fib_entry_t *fib_entry_create(Name *name, strategy_type_t strategy_type, +fib_entry_t *fib_entry_create(const hicn_prefix_t *prefix, + strategy_type_t strategy_type, strategy_options_t *strategy_options, const forwarder_t *forwarder) { - assert(name); - assert(forwarder); + assert(prefix); + /* + * For tests, we allow forwarder to be NULL, some + * functions cannot be called but otherwise we need a main loop, etc. + */ + // assert(forwarder); fib_entry_t *entry = malloc(sizeof(fib_entry_t)); if (!entry) goto ERR_MALLOC; memset(entry, 0, sizeof(*entry)); - name_Copy(name, &entry->name); + hicn_prefix_copy(&entry->prefix, prefix); entry->nexthops = NEXTHOPS_EMPTY; fib_entry_add_strategy_options(entry, STRATEGY_TYPE_BESTPATH, NULL); @@ -148,8 +152,10 @@ void fib_entry_set_strategy(fib_entry_t *entry, strategy_type_t strategy_type, strategy_initialize(&entry->strategy, entry->forwarder); } -#ifdef WITH_POLICY - +/* + * Filters the set of nexthops passed as parameters (and not the one stored in + * the FIB entry + */ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, unsigned ingress_id, bool prefer_local) { assert(entry); @@ -165,7 +171,6 @@ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, const connection_table_t *table = forwarder_get_connection_table(entry->forwarder); connection_t *conn; - unsigned nexthop, i; uint_fast32_t flags; hicn_policy_t policy = fib_entry_get_policy(entry); @@ -205,6 +210,7 @@ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, conn = connection_table_at(table, nexthop); nexthops_disable_if(nexthops, i, (connection_is_local(conn))); +#ifdef WITH_POLICY /* Policy filtering : next hops */ nexthops_disable_if( nexthops, i, @@ -238,6 +244,7 @@ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, nexthops, i, (policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_PROHIBIT) && (connection_has_tag(conn, POLICY_TAG_TRUSTED))); +#endif /* WITH_POLICY */ }); if (nexthops_get_curlen(nexthops) == 0) { @@ -248,6 +255,7 @@ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, /* We have at least one matching next hop, implement heuristic */ +#ifdef WITH_POLICY /* * As VPN connections might trigger duplicate uses of one interface, we start * by filtering out interfaces based on trust status. @@ -329,6 +337,8 @@ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, }); if (nexthops_get_curlen(nexthops) == 0) nexthops->flags = flags; } +// XXX backup curlen ??? +#endif /* WITH_POLICY */ DEBUG("[fib_entry_filter_nexthops] before face priority num=%d/%d", nexthops_get_curlen(nexthops), nexthops_get_len(nexthops)); @@ -349,10 +359,63 @@ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, DEBUG("[fib_entry_filter_nexthops] result num=%d/%d", nexthops_get_curlen(nexthops), nexthops_get_len(nexthops)); + /* Nexthop priority */ + + /* + * Filter out nexthops with lowest strategy priority. + * Initializing at 0 allows to disable nexthops with a negative priority + */ + max_priority = 0; + nexthops_enumerate(nexthops, i, nexthop, { + (void)nexthop; + int priority = nexthops->state[i].priority; + if (priority > max_priority) max_priority = priority; + }); + nexthops_enumerate(nexthops, i, nexthop, { + int priority = nexthops->state[i].priority; + nexthops_disable_if(nexthops, i, (priority < max_priority)); + }); + + /* + * If multipath is disabled, we don't offer much choice to the forwarding + * strategy, but still go through it for accounting purposes. + */ + if ((policy.tags[POLICY_TAG_MULTIPATH].state == POLICY_STATE_PROHIBIT) || + (policy.tags[POLICY_TAG_MULTIPATH].state == POLICY_STATE_AVOID)) { + DEBUG( + "[fib_entry_get_nexthops_from_strategy] select single nexthops due to " + "multipath policy"); + nexthops_select_first(nexthops); + } + return nexthops; } /* + * Retrieve all candidate nexthops for sending mapme updates == all non local + * connections. We don't apply the policy at this stage. + */ +nexthops_t *fib_entry_get_mapme_nexthops(fib_entry_t *entry, + nexthops_t *new_nexthops) { + assert(new_nexthops); + + const connection_table_t *table = + forwarder_get_connection_table(entry->forwarder); + + /* We create a nexthop structure based on connections */ + // XXX This should be done close to where it is needed + connection_t *connection; + connection_table_foreach(table, connection, { + if (connection_is_local(connection)) continue; + new_nexthops->elts[nexthops_get_len(new_nexthops)] = + connection_table_get_connection_id(table, connection); + nexthops_inc(new_nexthops); + }); + + return new_nexthops; +} + +/* * Update available next hops following policy update. * * The last nexthop parameter is only used if needed, otherwise the pointer to @@ -397,13 +460,20 @@ nexthops_t *fib_entry_get_available_nexthops(fib_entry_t *entry, #endif } +#ifdef WITH_POLICY + hicn_policy_t fib_entry_get_policy(const fib_entry_t *entry) { return entry->policy; } void fib_entry_set_policy(fib_entry_t *entry, hicn_policy_t policy) { + INFO("fib_entry_set_policy"); entry->policy = policy; + forwarder_on_route_event(entry->forwarder, entry); + + // XXX generic mechanism to perform a mapme update +#if 0 #ifdef WITH_MAPME /* * Skip entries that do not correspond to a producer ( / have a locally @@ -411,8 +481,8 @@ void fib_entry_set_policy(fib_entry_t *entry, hicn_policy_t policy) { */ if (!fib_entry_has_local_nexthop(entry)) return; mapme_t *mapme = forwarder_get_mapme(entry->forwarder); - mapme_set_all_adjacencies(mapme, entry); #endif /* WITH_MAPME */ +#endif } #endif /* WITH_POLICY */ @@ -475,10 +545,7 @@ nexthops_t *fib_entry_get_nexthops_from_strategy(fib_entry_t *entry, * Initializing at 0 allows to disable nexthops with a negative priority */ unsigned max_priority = 0; - unsigned i; - nexthop_t nexthop; nexthops_enumerate(nexthops, i, nexthop, { - (void)nexthop; int priority = nexthops->state[i].priority; if (priority > max_priority) max_priority = priority; }); @@ -546,9 +613,9 @@ void fib_entry_on_timeout(fib_entry_t *entry, strategy_on_timeout(&entry->strategy, &entry->nexthops, timeout_nexthops); } -const Name *fib_entry_get_prefix(const fib_entry_t *entry) { +const hicn_prefix_t *fib_entry_get_prefix(const fib_entry_t *entry) { assert(entry); - return &(entry->name); + return &(entry->prefix); } /* @@ -557,7 +624,6 @@ const Name *fib_entry_get_prefix(const fib_entry_t *entry) { bool fib_entry_has_local_nexthop(const fib_entry_t *entry) { connection_table_t *table = forwarder_get_connection_table(entry->forwarder); - unsigned nexthop; nexthops_foreach(fib_entry_get_nexthops(entry), nexthop, { const connection_t *conn = connection_table_at(table, nexthop); /* Ignore non-local connections */ diff --git a/hicn-light/src/hicn/core/fib_entry.h b/hicn-light/src/hicn/core/fib_entry.h index 628c4cd4f..b625a33ef 100644 --- a/hicn-light/src/hicn/core/fib_entry.h +++ b/hicn-light/src/hicn/core/fib_entry.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -37,16 +37,20 @@ #ifndef fib_entry_h #define fib_entry_h -#include "name.h" +#include <hicn/name.h> #include "strategy.h" #include "msgbuf.h" #include "nexthops.h" #include "policy_stats.h" typedef struct { - Name name; + hicn_prefix_t prefix; unsigned refcount; nexthops_t nexthops; + + /* This is used for producer prefixes only */ + uint32_t nexthops_hash; + strategy_entry_t strategy; const void *forwarder; @@ -59,10 +63,12 @@ typedef struct { policy_stats_t policy_stats; #ifdef WITH_MAPME +#if 0 /* In case of no multipath, this stores the previous decision taken by policy. * As the list of nexthops is not expected to change, we can simply store the * flags */ uint_fast32_t prev_nexthops_flags; +#endif void *user_data; void (*user_data_release)(void **user_data); #endif /* WITH_MAPME */ @@ -73,6 +79,7 @@ typedef struct { #define fib_entry_strategy_type(fib_entry) ((fib_entry)->strategy.type) #define fib_entry_get_nexthops(fib_entry) (&(fib_entry)->nexthops) + #define fib_entry_nexthops_len(fib_entry) \ (nexthops_get_len(&(fib_entry)->nexthops)) #define fib_entry_nexthops_curlen(fib_entry) \ @@ -81,14 +88,36 @@ typedef struct { #define fib_entry_foreach_nexthop(fib_entry, nexthop, BODY) \ nexthops_foreach(fib_entry->nexthops, BODY) -#define fib_entry_nexthops_changed(fib_entry) \ - ((fib_entry)->prev_nexthops_flags == fib_entry_get_nexthops(fib_entry)->flags) - -#define fib_entry_set_prev_nexthops(fib_entry) \ - ((fib_entry)->prev_nexthops_flags = fib_entry_get_nexthops(fib_entry)->flags) +#define fib_entry_get_nexthops_hash(E) ((E)->nexthops_hash) +#define fib_entry_set_nexthops_hash(E, H) (E)->nexthops_hash = (H) + +static inline void fib_entry_set_nexthops(fib_entry_t *entry, + nexthops_t *nexthops) { + entry->nexthops = *nexthops; +} + +static inline void fib_entry_initialize_nexthops(fib_entry_t *entry) { + entry->nexthops = NEXTHOPS_EMPTY; +} + +static inline bool fib_entry_nexthops_changed(fib_entry_t *entry, + nexthops_t *nexthops) { + uint32_t old_hash = fib_entry_get_nexthops_hash(entry); + uint32_t hash = nexthops_get_hash(nexthops); + if (hash != old_hash) { + fib_entry_set_nexthops_hash(entry, hash); + return true; + } + return false; +}; struct forwarder_s; -fib_entry_t *fib_entry_create(Name *name, strategy_type_t strategy_type, + +/* + * This does a copy of the name passed as parameter + */ +fib_entry_t *fib_entry_create(const hicn_prefix_t *prefix, + strategy_type_t strategy_type, strategy_options_t *strategy_options, const struct forwarder_s *table); @@ -106,8 +135,6 @@ void fib_entry_nexthops_add(fib_entry_t *fib_entry, unsigned nexthop); void fib_entry_nexthops_remove(fib_entry_t *fib_entry, unsigned nexthop); -size_t fib_entry_NexthopCount(const fib_entry_t *fib_entry); - /** * @function fib_entry_nexthops_get * @abstract Returns the nexthop set of the FIB entry. You must Acquire if it @@ -132,6 +159,12 @@ void fib_entry_set_policy(fib_entry_t *fib_entry, hicn_policy_t policy); void fib_entry_update_stats(fib_entry_t *fib_entry, uint64_t now); #endif /* WITH_POLICY */ +nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, + unsigned ingress_id, bool prefer_local); + +nexthops_t *fib_entry_get_mapme_nexthops(fib_entry_t *entry, + nexthops_t *new_nexthops); + nexthops_t *fib_entry_get_available_nexthops(fib_entry_t *fib_entry, unsigned in_connection, nexthops_t *new_nexthops); @@ -145,7 +178,7 @@ nexthops_t *fib_entry_get_nexthops_from_strategy( * @abstract Returns a copy of the prefix. * @return A reference counted copy that you must destroy */ -const Name *fib_entry_get_prefix(const fib_entry_t *fib_entry); +const hicn_prefix_t *fib_entry_get_prefix(const fib_entry_t *fib_entry); bool fib_entry_has_local_nexthop(const fib_entry_t *entry); diff --git a/hicn-light/src/hicn/core/forwarder.c b/hicn-light/src/hicn/core/forwarder.c index 74be6431a..482e3d6f1 100644 --- a/hicn-light/src/hicn/core/forwarder.c +++ b/hicn-light/src/hicn/core/forwarder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -69,7 +69,7 @@ #endif /* WITH_POLICY_STATS */ #include <hicn/core/wldr.h> -#include <hicn/core/interest_manifest.h> +#include <hicn/interest_manifest.h> #include <hicn/util/log.h> struct forwarder_s { @@ -189,9 +189,10 @@ forwarder_t *forwarder_create(configuration_t *configuration) { vector_init(forwarder->pending_conn, MAX_MSG, 0); vector_init(forwarder->acquired_msgbuf_ids, MAX_MSG, 0); - char *n_suffixes_per_split_str = getenv("N_SUFFIXES_PER_SPIT"); + char *n_suffixes_per_split_str = getenv("N_SUFFIXES_PER_SPLIT"); if (n_suffixes_per_split_str) - N_SUFFIXES_PER_SPIT = atoi(n_suffixes_per_split_str); + configuration_set_suffixes_per_split(forwarder_get_configuration(forwarder), + atoi(n_suffixes_per_split_str)); return forwarder; @@ -239,6 +240,162 @@ void forwarder_free(forwarder_t *forwarder) { free(forwarder); } +/* + * An event occurred that might trigger an update of the FIB cache. It is + * possible that the flags have been reset following a connection add or remote. + * The objective of this function is to prepare the cache entry, and to alert of + * any change for both consumer and producer prefixes. + */ +void forwarder_on_route_event(const forwarder_t *forwarder, + fib_entry_t *entry) { + commands_notify_route(forwarder, entry); + + nexthops_t new_nexthops = NEXTHOPS_EMPTY; + nexthops_t *nexthops; + + char *prefix_type_s; + + const connection_table_t *table = + forwarder_get_connection_table(entry->forwarder); + + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); + + WITH_INFO({ + char buf[MAXSZ_HICN_PREFIX]; + hicn_prefix_snprintf(buf, MAXSZ_HICN_NAME, prefix); + INFO("fib_entry_on_event: %s", buf); + )}; + + if (!fib_entry_has_local_nexthop(entry)) { + /* Recompute FIB cache, then check whether it has changed based on hash */ + prefix_type_s = "consumer"; + nexthops = fib_entry_get_nexthops(entry); + nexthops_reset(nexthops); + fib_entry_filter_nexthops(entry, nexthops, ~0, false); + } else { + /* Check available non-local connections (on which we would send MAP-Me + * updates */ + prefix_type_s = "producer"; + + nexthops = fib_entry_get_mapme_nexthops(entry, &new_nexthops); + fib_entry_filter_nexthops(entry, nexthops, ~0, true); + +#ifdef WITH_MAPME + mapme_set_adjacencies(forwarder->mapme, entry, nexthops); +#endif /* WITH_MAPME */ + } + + if (!fib_entry_nexthops_changed(entry, nexthops)) return; + + /* Send notification */ + WITH_INFO({ + char buf[MAXSZ_HICN_PREFIX]; + hicn_prefix_snprintf(buf, MAXSZ_HICN_NAME, prefix); + INFO("Active interfaces changed for %s prefix %s", prefix_type_s, buf); + }); + + netdevice_flags_t flags = NETDEVICE_FLAGS_EMPTY; + nexthops_foreach(nexthops, nh, { + connection_t *connection = connection_table_get_by_id(table, nh); + netdevice_flags_add(flags, connection_get_interface_type(connection)); + }); + + hicn_ip_prefix_t ip_prefix; + hicn_prefix_get_ip_prefix(prefix, &ip_prefix); + commands_notify_active_interface_update(forwarder, &ip_prefix, flags); +} + +int forwarder_add_connection(const forwarder_t *forwarder, + const char *symbolic_name, face_type_t type, + address_pair_t *pair, policy_tags_t tags, + int priority, face_state_t admin_state) { + connection_table_t *table = forwarder_get_connection_table(forwarder); + connection_t *connection = connection_table_get_by_pair(table, pair); + + if (!connection) { + connection = connection_create(type, symbolic_name, pair, forwarder); + if (!connection) { + ERROR("Failed to create %s connection", face_type_str(type)); + return -1; + } + + } else { + WARN("Connection already exists"); + } + +#ifdef WITH_POLICY + connection_set_tags(connection, tags); + connection_set_priority(connection, priority); +#endif /* WITH_POLICY */ + + connection_set_admin_state(connection, admin_state); + return 0; +} + +int forwarder_remove_connection(const forwarder_t *forwarder, + unsigned connection_id, bool finalize) { + /* Remove connection from the FIB */ + forwarder_remove_connection_id_from_routes(forwarder, connection_id); + + /* Remove connection */ + connection_table_t *table = forwarder_get_connection_table(forwarder); + + /* Hook: connection deleted through the control protocol */ + connection_t *connection = connection_table_at(table, connection_id); + forwarder_on_connection_event(forwarder, connection, CONNECTION_EVENT_DELETE); + + connection_table_remove_by_id(table, connection_id); + if (finalize) connection_finalize(connection); + + return 0; +} + +/* + * This is currently called from commands.c for every command sent to update + * a connection. + */ +void forwarder_on_connection_event(const forwarder_t *forwarder, + const connection_t *connection, + connection_event_t event) { + assert(connection); + + commands_notify_connection(forwarder, event, connection); + + unsigned conn_id = connection_get_id(connection); + + /* We need to send a MapMe update on the newly selected connections for + * each concerned fib_entry : connection is involved, or no more involved */ + fib_t *fib = forwarder_get_fib(forwarder); + fib_foreach_entry(fib, entry, { + const nexthops_t *nexthops = fib_entry_get_nexthops(entry); + + if (!fib_entry_has_local_nexthop(entry)) { + /* Consumer prefix */ + /* + * A new connection has no impact until it is added to FIB, which will + * be handled in a route event + */ + if (event == CONNECTION_EVENT_CREATE) break; + + /* + * For each FIB entry, trigger an event only if the connection is part + * of nexthops */ + // XXX Replace this by a function + nexthops_foreach(nexthops, nexthop, { + if (nexthop != conn_id) continue; + forwarder_on_route_event(forwarder, entry); + break; + }); + } else { + /* Producer prefix */ + if (connection_is_local(connection)) break; + + // XXX we could optimize event more + forwarder_on_route_event(forwarder, entry); + } + }); +} + void forwarder_setup_local_listeners(forwarder_t *forwarder, uint16_t port) { assert(forwarder); listener_setup_local(forwarder, port); @@ -249,7 +406,8 @@ configuration_t *forwarder_get_configuration(forwarder_t *forwarder) { return forwarder->config; } -subscription_table_t *forwarder_get_subscriptions(forwarder_t *forwarder) { +subscription_table_t *forwarder_get_subscriptions( + const forwarder_t *forwarder) { return forwarder->subscriptions; } @@ -259,7 +417,7 @@ connection_table_t *forwarder_get_connection_table( return forwarder->connection_table; } -listener_table_t *forwarder_get_listener_table(forwarder_t *forwarder) { +listener_table_t *forwarder_get_listener_table(const forwarder_t *forwarder) { assert(forwarder); return forwarder->listener_table; } @@ -295,7 +453,8 @@ void forwarder_cs_set_size(forwarder_t *forwarder, size_t size) { if (pkt_cache_set_cs_size(forwarder->pkt_cache, size) < 0) { ERROR( "Unable to resize the CS: provided maximum size (%u) is smaller than " - "the number of elements currently stored in the CS (%u). Clear the CS " + "the number of elements currently stored in the CS (%u). Clear the " + "CS " "and retry.", size, pkt_cache_get_cs_size(forwarder->pkt_cache)); } @@ -335,11 +494,11 @@ static ssize_t forwarder_drop(forwarder_t *forwarder, off_t msgbuf_id) { const msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); switch (msgbuf_get_type(msgbuf)) { - case MSGBUF_TYPE_INTEREST: + case HICN_PACKET_TYPE_INTEREST: forwarder->stats.countInterestsDropped++; break; - case MSGBUF_TYPE_DATA: + case HICN_PACKET_TYPE_DATA: forwarder->stats.countObjectsDropped++; break; @@ -384,7 +543,7 @@ static ssize_t forwarder_forward_via_connection(forwarder_t *forwarder, // Here we need to update the path label of a data packet before send // it. The path label update can be done here because the packet is sent // directly to the socket - if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA) + if (msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA) msgbuf_update_pathlabel(msgbuf, connection_get_id(conn)); bool success = connection_send_packet(conn, msgbuf_get_packet(msgbuf), @@ -415,11 +574,11 @@ static ssize_t forwarder_forward_via_connection(forwarder_t *forwarder, } switch (msgbuf_get_type(msgbuf)) { - case MSGBUF_TYPE_INTEREST: + case HICN_PACKET_TYPE_INTEREST: forwarder->stats.countInterestForwarded++; break; - case MSGBUF_TYPE_DATA: + case HICN_PACKET_TYPE_DATA: forwarder->stats.countObjectsForwarded++; break; @@ -451,7 +610,6 @@ static unsigned forwarder_forward_to_nexthops(forwarder_t *forwarder, msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); unsigned ingressId = msgbuf_get_connection_id(msgbuf); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { // DEBUG("[forwarder_forward_to_nexthops] - nexthop = %d"); if (nexthop == ingressId) continue; @@ -469,43 +627,57 @@ static bool forwarder_forward_via_fib(forwarder_t *forwarder, off_t msgbuf_id, pkt_cache_entry_t *entry) { assert(forwarder && entry && msgbuf_id_is_valid(msgbuf_id)); + bool ret = true; + const msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder); msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); - assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST); + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST); - fib_entry_t *fib_entry = fib_match_message(forwarder->fib, msgbuf); + fib_entry_t *fib_entry = fib_match_msgbuf(forwarder->fib, msgbuf); if (!fib_entry) return false; - // DEBUG("[forwarder] Getting nexthops from strategy"); - nexthops_t *nexthops = fib_entry_get_nexthops_from_strategy( - fib_entry, msgbuf, verdict == PKT_CACHE_VERDICT_RETRANSMIT_INTEREST); + nexthops_t *nexthops = fib_entry_get_nexthops(fib_entry); + + /* Backup flags and cur_len*/ + uint_fast32_t flags = nexthops->flags; + size_t cur_len = nexthops_get_curlen(nexthops); + + /* This affects the nexthops */ + nexthops = strategy_lookup_nexthops(&fib_entry->strategy, nexthops, msgbuf); if (nexthops_get_curlen(nexthops) == 0) { ERROR("Message %p returned an empty next hop set", msgbuf); - return false; + ret = false; + goto END; } pit_entry_t *pit_entry = &entry->u.pit_entry; - if (!pit_entry) return false; + if (!pit_entry) { + ret = false; + goto END; + } pit_entry_set_fib_entry(pit_entry, fib_entry); // this requires some additional checks. It may happen that some of the output // faces selected by the forwarding strategy are not usable. So far all the // forwarding strategy return only valid faces (or an empty list) - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { // DEBUG("Adding egress to PIT for nexthop %d", nexthop); pit_entry_egress_add(pit_entry, nexthop); }); if (forwarder_forward_to_nexthops(forwarder, msgbuf_id, nexthops) <= 0) { - // this should never happen - ERROR("Message %p returned an empty next hop set", msgbuf); - return false; + ERROR("Error forwarding mMessage %p to next hops", msgbuf); + ret = false; } - return true; +END: + /* Restore flags & curlen */ + nexthops->flags = flags; + nexthops->cur_elts = cur_len; + + return ret; } #endif /* ! BYPASS_FIB */ @@ -519,7 +691,7 @@ int _forwarder_forward_upon_interest( // - Aggregation can be perfomed, do not forward if (verdict == PKT_CACHE_VERDICT_AGGREGATE_INTEREST) { forwarder_drop(forwarder, interest_msgbuf_id); - return msgbuf_get_len(msgbuf); + return (int)msgbuf_get_len(msgbuf); } // - Data packet matching the interest was found, forward reply @@ -532,12 +704,12 @@ int _forwarder_forward_upon_interest( msgbuf_reset_pathlabel(data_msgbuf); forwarder_forward_via_connection(forwarder, data_msgbuf_id, msgbuf_get_connection_id(interest_msgbuf)); - return msgbuf_get_len(msgbuf); + return (int)msgbuf_get_len(msgbuf); } // - For aggregated interest, the interest forwarding is done in // `_forwarder_forward_aggregated_interest()` - if (is_aggregated) return msgbuf_get_len(msgbuf); + if (is_aggregated) return (int)msgbuf_get_len(msgbuf); // - Try to forward the interest int rc = @@ -552,7 +724,7 @@ int _forwarder_forward_upon_interest( return -1; } - return msgbuf_get_len(msgbuf); + return (int)msgbuf_get_len(msgbuf); } static void _forwarder_update_interest_stats(forwarder_t *forwarder, @@ -601,54 +773,60 @@ static void _forwarder_update_interest_stats(forwarder_t *forwarder, } } +/** + * Return the interest manifest from the interest payload + */ static interest_manifest_header_t *_forwarder_get_interest_manifest( msgbuf_t *msgbuf) { - uint8_t *packet = msgbuf_get_packet(msgbuf); - hicn_header_t *header = (hicn_header_t *)packet; - hicn_type_t type = hicn_header_to_type(header); + uint8_t *payload; + size_t payload_size; - hicn_payload_type_t payload_type; - int rc = hicn_ops_vft[type.l1]->get_payload_type(type, &header->protocol, - &payload_type); - _ASSERT(rc == HICN_LIB_ERROR_NONE); - if (payload_type != HPT_MANIFEST) return NULL; + hicn_packet_buffer_t *pkbuf = msgbuf_get_pkbuf(msgbuf); - size_t header_length, payload_length; - rc = hicn_ops_vft[type.l1]->get_header_length(type, &header->protocol, - &header_length); + hicn_payload_type_t payload_type; + HICN_UNUSED(int rc) = hicn_packet_get_payload_type(pkbuf, &payload_type); assert(rc == HICN_LIB_ERROR_NONE); - rc = hicn_ops_vft[type.l1]->get_payload_length(type, &header->protocol, - &payload_length); - assert(rc == HICN_LIB_ERROR_NONE); + if (payload_type != HPT_MANIFEST) return NULL; - u8 *payload = (u8 *)header + header_length; - interest_manifest_header_t *int_manifest_header = - (interest_manifest_header_t *)payload; - if (!interest_manifest_is_valid(int_manifest_header, payload_length)) - return NULL; + rc = hicn_packet_get_payload(pkbuf, &payload, &payload_size, false); + _ASSERT(rc == HICN_LIB_ERROR_NONE); - return int_manifest_header; + return (interest_manifest_header_t *)payload; } // Manifest is split using splitting strategy, then every // sub-manifest is sent using the forwarding strategy defined for the prefix int _forwarder_forward_aggregated_interest( forwarder_t *forwarder, interest_manifest_header_t *int_manifest_header, - int n_suffixes_to_fwd, msgbuf_t *msgbuf, off_t msgbuf_id, - pkt_cache_entry_t **entries) { + msgbuf_t *msgbuf, off_t msgbuf_id, pkt_cache_entry_t **entries) { assert(msgbuf_id_is_valid(msgbuf_id) && - msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST); + msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST); - fib_entry_t *fib_entry = fib_match_message(forwarder->fib, msgbuf); - if (!fib_entry) return -1; + bool ret = -1; + + fib_entry_t *fib_entry = fib_match_msgbuf(forwarder->fib, msgbuf); + if (!fib_entry) goto END; + + nexthops_t *nexthops = fib_entry_get_nexthops(fib_entry); + if (nexthops_get_curlen(nexthops) == 0) { + ret = 0; + goto END; + } - int n_suffixes_per_split = N_SUFFIXES_PER_SPIT; + /* Backup flags and cur_len*/ + uint_fast32_t flags = nexthops->flags; + size_t cur_len = nexthops_get_curlen(nexthops); + + size_t n_suffixes_per_split = configuration_get_suffixes_per_split( + forwarder_get_configuration(forwarder)); + int_manifest_split_strategy_t disaggregation_strategy = + configuration_get_split_strategy(forwarder_get_configuration(forwarder)); switch (disaggregation_strategy) { - case INT_MANIFEST_SPLIT_NONE: + case INT_MANIFEST_SPLIT_STRATEGY_NONE: n_suffixes_per_split = int_manifest_header->n_suffixes + 1; - case INT_MANIFEST_SPLIT_MAX_N_SUFFIXES: { + case INT_MANIFEST_SPLIT_STRATEGY_MAX_N_SUFFIXES: { // Generate sub-manifests: same as original manifest, // but different suffix in the header and different bitmap @@ -658,11 +836,11 @@ int _forwarder_forward_aggregated_interest( // Save copy of original bitmap to use as a reference // to generate bitmaps for sub-manifests - u32 original_bitmap[BITMAP_SIZE] = {0}; + hicn_uword original_bitmap[BITMAP_SIZE] = {0}; memcpy(&original_bitmap, int_manifest_header->request_bitmap, - BITMAP_SIZE * sizeof(u32)); + BITMAP_SIZE * sizeof(hicn_uword)); - int suffix_index = 0; // Position of suffix in initial manifest + size_t suffix_index = 0; // Position of suffix in initial manifest while (suffix_index < total_suffixes) { // If more than one sub-manifest, // clone original interest manifest and update suffix @@ -677,38 +855,48 @@ int _forwarder_forward_aggregated_interest( msgbuf = clone; } - u32 curr_bitmap[BITMAP_SIZE] = {0}; - int first_suffix_index_in_submanifest = suffix_index; + hicn_uword curr_bitmap[BITMAP_SIZE] = {0}; + size_t first_suffix_index_in_submanifest = suffix_index; suffix_index = interest_manifest_update_bitmap( original_bitmap, curr_bitmap, suffix_index, total_suffixes, n_suffixes_per_split); - int first_suffix_index_in_next_submanifest = suffix_index; + size_t first_suffix_index_in_next_submanifest = suffix_index; // Update manifest bitmap in current msgbuf interest_manifest_header_t *manifest = _forwarder_get_interest_manifest(msgbuf); assert(manifest != NULL); memcpy(manifest->request_bitmap, curr_bitmap, - BITMAP_SIZE * sizeof(u32)); + BITMAP_SIZE * sizeof(hicn_uword)); WITH_TRACE({ bitmap_print(manifest->request_bitmap, BITMAP_SIZE); printf("\n"); }); - // Update PIT entries for suffixes in current sub-manifest - nexthops_t *nexthops = - fib_entry_get_nexthops_from_strategy(fib_entry, msgbuf, false); - if (nexthops_get_curlen(nexthops) == 0) return -1; + /* + * Update PIT entries for suffixes in current sub-manifest. + * + * Note that strategy lookup affects the nexthops, and we need to + *restore the initial state before every lookup + */ + nexthops->flags = flags; + nexthops->cur_elts = cur_len; + nexthops = + strategy_lookup_nexthops(&fib_entry->strategy, nexthops, msgbuf); + + if (nexthops_get_curlen(nexthops) == 0) { + ERROR("Message %p returned an empty next hop set", msgbuf); + goto RESTORE; + } - for (int i = first_suffix_index_in_submanifest; + for (size_t i = first_suffix_index_in_submanifest; i < first_suffix_index_in_next_submanifest; i++) { - if (!is_bit_set(manifest->request_bitmap, i)) continue; + if (!bitmap_is_set_no_check(manifest->request_bitmap, i)) continue; pit_entry_t *pit_entry = &(entries[i]->u.pit_entry); - if (!pit_entry) return -1; + if (!pit_entry) goto RESTORE; pit_entry_set_fib_entry(pit_entry, fib_entry); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { pit_entry_egress_add(pit_entry, nexthop); }); } @@ -722,12 +910,21 @@ int _forwarder_forward_aggregated_interest( total_len += msgbuf_get_len(msgbuf); } - return total_len; + ret = total_len; + goto END; } default: - return -1; + break; } + +RESTORE: + /* Restore flags & curlen */ + nexthops->flags = flags; + nexthops->cur_elts = cur_len; + +END: + return ret; } static ssize_t forwarder_process_single_interest(forwarder_t *forwarder, @@ -742,6 +939,7 @@ static ssize_t forwarder_process_single_interest(forwarder_t *forwarder, pkt_cache_on_interest(forwarder->pkt_cache, msgbuf_pool, msgbuf_id, &verdict, &data_msgbuf_id, &entry, msgbuf_get_name(msgbuf), forwarder->serve_from_cs); + _forwarder_update_interest_stats(forwarder, verdict, msgbuf, entry->has_expire_ts, entry->expire_ts); @@ -749,9 +947,7 @@ static ssize_t forwarder_process_single_interest(forwarder_t *forwarder, forwarder, msgbuf_pool, data_msgbuf_id, msgbuf_id, entry, verdict, false); // No route when trying to forward interest, remove from PIT - if (rc == -1) - pkt_cache_pit_remove_entry(forwarder->pkt_cache, entry, - msgbuf_get_name(msgbuf)); + if (rc == -1) pkt_cache_pit_remove_entry(forwarder->pkt_cache, entry); return msgbuf_get_len(msgbuf); } @@ -769,15 +965,16 @@ static ssize_t forwarder_process_aggregated_interest( int pos = 0; // Position of current suffix in manifest int n_suffixes_to_fwd = 0; u32 *suffix = (u32 *)(int_manifest_header + 1); - u32 seq = name_GetSegment(msgbuf_get_name(msgbuf)); + u32 seq = hicn_name_get_suffix(msgbuf_get_name(msgbuf)); - Name name_copy = EMPTY_NAME; - name_Copy(msgbuf_get_name(msgbuf), &name_copy); + hicn_name_t name_copy = HICN_NAME_EMPTY; + hicn_name_copy(&name_copy, msgbuf_get_name(msgbuf)); // The fist loop iteration handles the suffix in the header, // the following ones handle the suffiexes in the manifest while (true) { - if (!is_bit_set(int_manifest_header->request_bitmap, pos)) goto NEXT_SUFFIX; + if (!bitmap_is_set_no_check(int_manifest_header->request_bitmap, pos)) + goto NEXT_SUFFIX; // Update packet cache pkt_cache_on_interest(forwarder->pkt_cache, msgbuf_pool, msgbuf_id, @@ -794,14 +991,13 @@ static ssize_t forwarder_process_aggregated_interest( msgbuf_id, entry, verdict, true); // No route when trying to forward interest, remove from PIT - if (rc == -1) - pkt_cache_pit_remove_entry(forwarder->pkt_cache, entry, &name_copy); + if (rc == -1) pkt_cache_pit_remove_entry(forwarder->pkt_cache, entry); // Unset in bitmap if no interest forwarding needed, // otherwise increase count of suffixes to forward if (rc == -1 || verdict == PKT_CACHE_VERDICT_AGGREGATE_INTEREST || verdict == PKT_CACHE_VERDICT_FORWARD_DATA) { - unset_bit(int_manifest_header->request_bitmap, pos); + bitmap_unset_no_check(int_manifest_header->request_bitmap, pos); } else { n_suffixes_to_fwd++; } @@ -812,12 +1008,15 @@ static ssize_t forwarder_process_aggregated_interest( // Use next segment in manifest seq = *suffix; suffix++; - name_SetSegment(&name_copy, seq); + hicn_name_set_suffix(&name_copy, seq); WITH_DEBUG({ - char *nameString = name_ToString(&name_copy); - DEBUG("Next in manifest: %s", nameString); - free(nameString); + char buf[MAXSZ_HICN_PREFIX]; + int rc = + hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf)); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "(error)"); + DEBUG("Next in manifest: %s", buf); }); } @@ -825,8 +1024,7 @@ static ssize_t forwarder_process_aggregated_interest( if (n_suffixes_to_fwd == 0) return msgbuf_get_len(msgbuf); return _forwarder_forward_aggregated_interest(forwarder, int_manifest_header, - n_suffixes_to_fwd, msgbuf, - msgbuf_id, entries); + msgbuf, msgbuf_id, entries); } /** @@ -850,7 +1048,7 @@ static ssize_t forwarder_process_interest(forwarder_t *forwarder, connection_t *conn = connection_table_get_by_id(table, msgbuf_get_connection_id(msgbuf)); - assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST); + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST); u32 n_suffixes = 0; interest_manifest_header_t *int_manifest_header = @@ -863,16 +1061,20 @@ static ssize_t forwarder_process_interest(forwarder_t *forwarder, conn->stats.interests.rx_bytes += msgbuf_get_len(msgbuf); WITH_DEBUG({ - char *nameString = name_ToString(msgbuf_get_name(msgbuf)); - DEBUG("INTEREST (%s) suffixes=%u msgbuf_id=%lu ingress=%u length=%u", - nameString, n_suffixes, msgbuf_id, msgbuf_get_connection_id(msgbuf), + char buf[MAXSZ_HICN_PREFIX]; + int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf)); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "(error)"); + DEBUG("INTEREST (%s) msgbuf_id=%lu ingress=%u length=%u", buf, msgbuf_id, + msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf)); + DEBUG("INTEREST (%s) suffixes=%u msgbuf_id=%lu ingress=%u length=%u", buf, + n_suffixes, msgbuf_id, msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf)); - free(nameString); }); // Cache suffixes for current prefix to (possibly) avoid double lookups pkt_cache_save_suffixes_for_prefix( - forwarder->pkt_cache, name_GetContentName(msgbuf_get_name(msgbuf))); + forwarder->pkt_cache, hicn_name_get_prefix(msgbuf_get_name(msgbuf))); if (!int_manifest_header) return forwarder_process_single_interest(forwarder, msgbuf_pool, msgbuf, @@ -888,7 +1090,9 @@ static void _forwarder_log_on_data(forwarder_t *forwarder, DEBUG("Message added to CS from PIT"); break; case PKT_CACHE_VERDICT_STORE_DATA: - DEBUG("Message added to CS (expired or no previous interest pending)"); + DEBUG( + "Message added to CS (expired or no previous interest " + "pending)"); break; case PKT_CACHE_VERDICT_CLEAR_DATA: break; @@ -921,10 +1125,12 @@ static ssize_t forwarder_process_data(forwarder_t *forwarder, off_t msgbuf_id) { msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); WITH_DEBUG({ - char *nameString = name_ToString(msgbuf_get_name(msgbuf)); - DEBUG("DATA (%s) msgbuf_id=%lu ingress=%u length=%u", nameString, msgbuf_id, + char buf[MAXSZ_HICN_PREFIX]; + int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf)); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "(error)"); + DEBUG("DATA (%s) msgbuf_id=%lu ingress=%u length=%u", buf, msgbuf_id, msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf)); - free(nameString); }); const connection_table_t *table = forwarder_get_connection_table(forwarder); @@ -938,7 +1144,7 @@ static ssize_t forwarder_process_data(forwarder_t *forwarder, off_t msgbuf_id) { // Cache suffixes for current prefix to (possibly) avoid double lookups pkt_cache_save_suffixes_for_prefix( - forwarder->pkt_cache, name_GetContentName(msgbuf_get_name(msgbuf))); + forwarder->pkt_cache, hicn_name_get_prefix(msgbuf_get_name(msgbuf))); pkt_cache_verdict_t verdict = PKT_CACHE_VERDICT_ERROR; bool wrong_egress; @@ -955,17 +1161,13 @@ static ssize_t forwarder_process_data(forwarder_t *forwarder, off_t msgbuf_id) { forwarder->stats.countDroppedNoReversePath++; DEBUG("Message %lu did not match PIT, no reverse path", msgbuf_id); - // MOVE PROBE HOOK ELSEWHERE - // XXX relationship with forwarding strategy... insert hooks - // if the packet is a probe we need to analyze it // NOTE : probes are not stored in PIT if (msgbuf_is_probe(msgbuf)) { - fib_entry_t *entry = fib_match_message(forwarder->fib, msgbuf); + fib_entry_t *entry = fib_match_msgbuf(forwarder->fib, msgbuf); if (entry && fib_entry_strategy_type(entry) == STRATEGY_TYPE_BESTPATH) { nexthops_t probe_nexthops = NEXTHOPS_EMPTY; nexthops_add(&probe_nexthops, msgbuf_get_connection_id(msgbuf)); fib_entry_on_data(entry, &probe_nexthops, msgbuf, 0, ticks_now()); - // XXX TODO CONFIRM WE DON'T EXIT HERE ? } } forwarder_drop(forwarder, msgbuf_id); @@ -982,7 +1184,8 @@ void forwarder_flush_connections(forwarder_t *forwarder) { // DEBUG("[forwarder_flush_connections]"); const connection_table_t *table = forwarder_get_connection_table(forwarder); - for (unsigned i = 0; i < vector_len(forwarder->pending_conn); i++) { + unsigned num_pending_conn = (unsigned)vector_len(forwarder->pending_conn); + for (unsigned i = 0; i < num_pending_conn; i++) { unsigned conn_id = forwarder->pending_conn[i]; connection_t *conn = connection_table_at(table, conn_id); if (!connection_flush(conn)) { @@ -994,14 +1197,15 @@ void forwarder_flush_connections(forwarder_t *forwarder) { // DEBUG("[forwarder_flush_connections] done"); } +#if WITH_WLDR // XXX move to wldr file, worst case in connection. void forwarder_apply_wldr(const forwarder_t *forwarder, const msgbuf_t *msgbuf, connection_t *connection) { - // this are the checks needed to implement WLDR. We set wldr only on the STAs - // and we let the AP to react according to choice of the client. - // if the STA enables wldr using the set command, the AP enable wldr as well - // otherwise, if the STA disable it the AP remove wldr - // WLDR should be enabled only on the STAs using the command line + // this are the checks needed to implement WLDR. We set wldr only on the + // STAs and we let the AP to react according to choice of the client. if + // the STA enables wldr using the set command, the AP enable wldr as + // well otherwise, if the STA disable it the AP remove wldr WLDR should + // be enabled only on the STAs using the command line // TODO // disable WLDR command line on the AP if (msgbuf_has_wldr(msgbuf)) { @@ -1023,8 +1227,10 @@ void forwarder_apply_wldr(const forwarder_t *forwarder, const msgbuf_t *msgbuf, } } } +#endif -bool forwarder_add_or_update_route(forwarder_t *forwarder, ip_prefix_t *prefix, +bool forwarder_add_or_update_route(forwarder_t *forwarder, + hicn_ip_prefix_t *prefix, unsigned ingress_id) { assert(forwarder); assert(prefix); @@ -1032,7 +1238,7 @@ bool forwarder_add_or_update_route(forwarder_t *forwarder, ip_prefix_t *prefix, configuration_t *config = forwarder_get_configuration(forwarder); char prefix_s[MAXSZ_IP_PREFIX]; - int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, prefix); + int rc = hicn_ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, prefix); assert(rc < MAXSZ_IP_PREFIX); if (rc < 0) return false; @@ -1041,9 +1247,9 @@ bool forwarder_add_or_update_route(forwarder_t *forwarder, ip_prefix_t *prefix, // XXX TODO this should store options too strategy_type_t strategy_type = configuration_get_strategy(config, prefix_s); - Name name_prefix = EMPTY_NAME; - name_CreateFromAddress(&name_prefix, prefix->family, prefix->address, - prefix->len); + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&prefix->address, prefix->len, + &name_prefix); fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix); if (!entry) { entry = fib_entry_create(&name_prefix, strategy_type, NULL, forwarder); @@ -1054,17 +1260,19 @@ bool forwarder_add_or_update_route(forwarder_t *forwarder, ip_prefix_t *prefix, fib_entry_nexthops_add(entry, ingress_id); } + forwarder_on_route_event(forwarder, entry); + return true; } -bool forwarder_remove_route(forwarder_t *forwarder, ip_prefix_t *prefix, +bool forwarder_remove_route(forwarder_t *forwarder, hicn_ip_prefix_t *prefix, unsigned ingress_id) { assert(forwarder); assert(prefix); - Name name_prefix = EMPTY_NAME; - name_CreateFromAddress(&name_prefix, prefix->family, prefix->address, - prefix->len); + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&prefix->address, prefix->len, + &name_prefix); fib_remove(forwarder->fib, &name_prefix, ingress_id); return true; @@ -1072,31 +1280,32 @@ bool forwarder_remove_route(forwarder_t *forwarder, ip_prefix_t *prefix, #ifdef WITH_POLICY -bool forwarder_add_or_update_policy(forwarder_t *forwarder, ip_prefix_t *prefix, +bool forwarder_add_or_update_policy(forwarder_t *forwarder, + hicn_ip_prefix_t *prefix, hicn_policy_t *policy) { assert(forwarder); assert(prefix); assert(policy); - Name name_prefix = EMPTY_NAME; - name_CreateFromAddress(&name_prefix, prefix->family, prefix->address, - prefix->len); + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&prefix->address, prefix->len, + &name_prefix); fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix); if (!entry) return false; + fib_entry_set_policy(entry, *policy); return true; } -bool forwarder_remove_policy(forwarder_t *forwarder, ip_prefix_t *prefix) { +bool forwarder_remove_policy(forwarder_t *forwarder, hicn_ip_prefix_t *prefix) { assert(forwarder); assert(prefix); - Name name_prefix = EMPTY_NAME; - name_CreateFromAddress(&name_prefix, prefix->family, prefix->address, - prefix->len); + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&prefix->address, prefix->len, + &name_prefix); fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix); - if (!entry) return false; fib_entry_set_policy(entry, POLICY_EMPTY); @@ -1106,14 +1315,30 @@ bool forwarder_remove_policy(forwarder_t *forwarder, ip_prefix_t *prefix) { #endif /* WITH_POLICY */ -void forwarder_remove_connection_id_from_routes(forwarder_t *forwarder, +void forwarder_remove_connection_id_from_routes(const forwarder_t *forwarder, unsigned connection_id) { + fib_entry_t **removed_entries = NULL; + size_t num_removed_entries; + assert(forwarder); - fib_remove_connection_id(forwarder->fib, connection_id); + fib_remove_connection(forwarder->fib, connection_id, &removed_entries, + &num_removed_entries); + + if (num_removed_entries > 0) { + assert(removed_entries); + + for (int i = 0; i < num_removed_entries; i++) { + fib_entry_t *entry = removed_entries[i]; + forwarder_on_route_event(forwarder, entry); + fib_remove_entry(forwarder->fib, entry); + } + free(removed_entries); + } } -void forwarder_add_strategy_options(forwarder_t *forwarder, Name *name_prefix, +void forwarder_add_strategy_options(forwarder_t *forwarder, + hicn_prefix_t *name_prefix, strategy_type_t strategy_type, strategy_options_t *strategy_options) { assert(forwarder); @@ -1127,18 +1352,18 @@ void forwarder_add_strategy_options(forwarder_t *forwarder, Name *name_prefix, fib_entry_add_strategy_options(entry, strategy_type, strategy_options); } -void forwarder_set_strategy(forwarder_t *forwarder, Name *name_prefix, +void forwarder_set_strategy(forwarder_t *forwarder, hicn_prefix_t *prefix, strategy_type_t strategy_type, strategy_options_t *strategy_options) { assert(forwarder); - assert(name_prefix); + assert(prefix); assert(STRATEGY_TYPE_VALID(strategy_type)); /* strategy_options might be NULL */ - fib_entry_t *entry = fib_contains(forwarder->fib, name_prefix); + fib_entry_t *entry = fib_contains(forwarder->fib, prefix); if (!entry) { - // there is no exact match. so if the forwarding strategy is not in the list - // of strategies that can be set by the transport, return + // there is no exact match. so if the forwarding strategy is not in + // the list of strategies that can be set by the transport, return if (strategy_type != STRATEGY_TYPE_BESTPATH && strategy_type != STRATEGY_TYPE_REPLICATION) { return; @@ -1148,7 +1373,7 @@ void forwarder_set_strategy(forwarder_t *forwarder, Name *name_prefix, // no knowledge of the length of the prefix. so we apply the strategy at the // matching fib entry, which later will be the one that will be used to send // interests with this name - entry = fib_match_name(forwarder->fib, name_prefix); + entry = fib_match_prefix(forwarder->fib, prefix); if (!entry) { return; // no fib match, return } @@ -1163,10 +1388,11 @@ cs_t *forwarder_get_cs(const forwarder_t *forwarder) { return pkt_cache_get_cs(forwarder->pkt_cache); } -// IMPORTANT: Use this function ONLY for read-only operations since a realloc -// would otherwise modify the returned copy but not the original msgbuf ids -// vector in the forwarder. This constraint cannot be enforced by returning a -// (const off_t *) because the vector_t macros still cast to (void **). +// IMPORTANT: Use this function ONLY for read-only operations since a +// realloc would otherwise modify the returned copy but not the original +// msgbuf ids vector in the forwarder. This constraint cannot be enforced +// by returning a (const off_t *) because the vector_t macros still cast +// to (void **). off_t *forwarder_get_acquired_msgbuf_ids(const forwarder_t *forwarder) { return forwarder->acquired_msgbuf_ids; } @@ -1182,25 +1408,18 @@ void forwarder_acquired_msgbuf_ids_push(const forwarder_t *forwarder, // ======================================================= -fib_t *forwarder_get_fib(forwarder_t *forwarder) { return forwarder->fib; } +fib_t *forwarder_get_fib(const forwarder_t *forwarder) { + return forwarder->fib; +} msgbuf_pool_t *forwarder_get_msgbuf_pool(const forwarder_t *forwarder) { return forwarder->msgbuf_pool; } -#ifdef WITH_MAPME -void forwarder_on_connection_event(const forwarder_t *forwarder, - const connection_t *connection, - connection_event_t event) { - mapme_on_connection_event(forwarder->mapme, connection, event); -} - mapme_t *forwarder_get_mapme(const forwarder_t *forwarder) { return forwarder->mapme; } -#endif /* WITH_MAPME */ - #ifdef WITH_POLICY_STATS const policy_stats_mgr_t *forwarder_get_policy_stats_mgr( const forwarder_t *forwarder) { @@ -1209,39 +1428,6 @@ const policy_stats_mgr_t *forwarder_get_policy_stats_mgr( #endif /* WITH_POLICY_STATS */ /** - * @brief Process a packet by creating the corresponding message buffer and - * dispatching it to the forwarder for further processing. - * @param[in] forwarder Forwarder instance. - * - */ -// XXX ??? XXX = process for listener as we are resolving connection id -// - -msgbuf_type_t get_type_from_packet(uint8_t *packet) { - if (messageHandler_IsTCP(packet)) { - if (messageHandler_IsData(packet)) { - return MSGBUF_TYPE_DATA; - } else if (messageHandler_IsInterest(packet)) { - return MSGBUF_TYPE_INTEREST; - } else { - return MSGBUF_TYPE_UNDEFINED; - } - - } else if (messageHandler_IsWldrNotification(packet)) { - return MSGBUF_TYPE_WLDR_NOTIFICATION; - - } else if (mapme_match_packet(packet)) { - return MSGBUF_TYPE_MAPME; - - } else if (*packet == REQUEST_LIGHT) { - return MSGBUF_TYPE_COMMAND; - - } else { - return MSGBUF_TYPE_UNDEFINED; - } -} - -/** * @brief Finalize (i.e. close fd and free internal data structures) * the current connection ("SELF") when the command is received. * The connection cannot be removed inside the command handling @@ -1268,7 +1454,6 @@ ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener, msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); assert(msgbuf); - uint8_t *packet = msgbuf_get_packet(msgbuf); size_t size = msgbuf_get_len(msgbuf); /* Connection lookup */ @@ -1281,81 +1466,128 @@ ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener, assert((conn_id != CONNECTION_ID_UNDEFINED) || listener); +#if 0 + /* + * We have a msgbuf with payload and size, we nee to populate other + * information, including packet type etc. + */ msgbuf_type_t type = get_type_from_packet(msgbuf_get_packet(msgbuf)); forwarder->stats.countReceived++; msgbuf->type = type; +#endif + /* Initialize packet buffer stored in msgbuf through libhicn */ + msgbuf_initialize_from_packet(msgbuf); + hicn_packet_analyze(msgbuf_get_pkbuf(msgbuf)); + msgbuf->connection_id = conn_id; msgbuf->recv_ts = now; - switch (type) { - case MSGBUF_TYPE_INTEREST: + hicn_name_t name; + +RETRY: + + switch (msgbuf_get_type(msgbuf)) { + case HICN_PACKET_TYPE_INTEREST: if (!connection_id_is_valid(msgbuf->connection_id)) { char conn_name[SYMBOLIC_NAME_LEN]; int rc = connection_table_get_random_name(table, conn_name); - if (rc < 0) return 0; + if (rc < 0) { + ERROR("Could not create name for new connection"); + goto DROP; + } unsigned connection_id = listener_create_connection(listener, conn_name, pair); + if (connection_id == CONNECTION_ID_UNDEFINED) { + ERROR("Could not create new connection"); + goto DROP; + } msgbuf->connection_id = connection_id; connection = connection_table_get_by_id(table, connection_id); } msgbuf->path_label = 0; // not used for interest packets - name_create_from_interest(packet, msgbuf_get_name(msgbuf)); + hicn_interest_get_name(msgbuf_get_pkbuf(msgbuf), &name); + msgbuf_set_name(msgbuf, &name); +#ifdef WITH_WLDR forwarder_apply_wldr(forwarder, msgbuf, connection); +#endif /* WITH_WLDR */ forwarder_process_interest(forwarder, msgbuf_id); pkt_cache_log(forwarder->pkt_cache); - return size; + break; - case MSGBUF_TYPE_DATA: - if (!connection_id_is_valid(msgbuf->connection_id)) - return forwarder_drop(forwarder, msgbuf_id); + case HICN_PACKET_TYPE_DATA: + /* This include probes */ + if (!connection_id_is_valid(msgbuf->connection_id)) { + ERROR("Invalid connection for data packet"); + goto DROP; + } msgbuf_init_pathlabel(msgbuf); - name_create_from_data(packet, msgbuf_get_name(msgbuf)); + hicn_data_get_name(msgbuf_get_pkbuf(msgbuf), &name); + msgbuf_set_name(msgbuf, &name); +#ifdef WITH_WLDR forwarder_apply_wldr(forwarder, msgbuf, connection); +#endif /* WITH_WLDR */ forwarder_process_data(forwarder, msgbuf_id); pkt_cache_log(forwarder->pkt_cache); - return size; + break; - case MSGBUF_TYPE_WLDR_NOTIFICATION: - if (!connection_id_is_valid(msgbuf->connection_id)) - return forwarder_drop(forwarder, msgbuf_id); + case HICN_PACKET_TYPE_WLDR_NOTIFICATION: + if (!connection_id_is_valid(msgbuf->connection_id)) { + ERROR("Invalid connection for WLDR packet"); + goto DROP; + } connection_wldr_handle_notification(connection, msgbuf); - return size; + break; - case MSGBUF_TYPE_MAPME: + case HICN_PACKET_TYPE_MAPME: // XXX what about acks ? if (!connection_id_is_valid(msgbuf->connection_id)) { char conn_name[SYMBOLIC_NAME_LEN]; int rc = connection_table_get_random_name(table, conn_name); - if (rc < 0) return 0; + if (rc < 0) { + ERROR("Could not create name for new connection"); + goto DROP; + } - msgbuf->connection_id = + unsigned connection_id = listener_create_connection(listener, conn_name, pair); + if (connection_id == CONNECTION_ID_UNDEFINED) { + ERROR("Could not create new connection"); + goto DROP; + } + msgbuf->connection_id = connection_id; } mapme_process(forwarder->mapme, msgbuf); - return size; + break; - case MSGBUF_TYPE_COMMAND: + case HICN_PACKET_TYPE_COMMAND: // Create the connection to send the ack back if (!connection_id_is_valid(msgbuf->connection_id)) { char conn_name[SYMBOLIC_NAME_LEN]; int rc = connection_table_get_random_name(table, conn_name); - if (rc < 0) return 0; + if (rc < 0) { + ERROR("Could not create name for new connection"); + goto DROP; + } unsigned connection_id = listener_create_connection(listener, conn_name, pair); + if (connection_id == CONNECTION_ID_UNDEFINED) { + ERROR("Could not create new connection"); + goto DROP; + } msgbuf->connection_id = connection_id; connection = connection_table_get_by_id(table, connection_id); } - msg_header_t *msg = (msg_header_t *)packet; + msg_header_t *msg = (msg_header_t *)msgbuf_get_packet(msgbuf); msgbuf->command.type = msg->header.command_id; if (!command_type_is_valid(msgbuf->command.type)) { - ERROR("Invalid command"); - return 0; + ERROR("Invalid command %d", msgbuf->command.type); + goto DROP; } size = command_process_msgbuf(forwarder, msgbuf); @@ -1364,19 +1596,32 @@ ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener, return size; default: - ERROR("Invalid msgbuf type"); - forwarder_drop(forwarder, msgbuf_id); - return 0; + /* Commands are not recognized by the packet parser */ + if (msgbuf_is_command(msgbuf)) { + msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND); + goto RETRY; + } + goto DROP; } + + return size; + +DROP: + forwarder_drop(forwarder, msgbuf_id); + return 0; } void forwarder_log(forwarder_t *forwarder) { DEBUG( "Forwarder: received = %u (interest = %u, data = %u), dropped = %u " - "(interest = %u, data = %u, other = %u), forwarded = { interests = %u, " - "data = %u }, dropped = { connection_not_found = %u, send_failure = %u, " + "(interest = %u, data = %u, other = %u), forwarded = { interests = " + "%u, " + "data = %u }, dropped = { connection_not_found = %u, send_failure " + "= " + "%u, " "no_route_in_fib = %u }, interest processing = { aggregated = %u, " - "retransmitted = %u, satisfied_from_cs = %u, expired_interests = %u, " + "retransmitted = %u, satisfied_from_cs = %u, expired_interests = " + "%u, " "expired_data = %u }, data processing = { " "no_reverse_path = %u }\n", forwarder->stats.countReceived, forwarder->stats.countInterestsReceived, @@ -1396,4 +1641,4 @@ void forwarder_log(forwarder_t *forwarder) { forwarder_stats_t forwarder_get_stats(forwarder_t *forwarder) { return forwarder->stats; -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/core/forwarder.h b/hicn-light/src/hicn/core/forwarder.h index 2f940cf15..b7ce5ff4d 100644 --- a/hicn-light/src/hicn/core/forwarder.h +++ b/hicn-light/src/hicn/core/forwarder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -74,7 +74,7 @@ void forwarder_setup_local_listeners(forwarder_t *forwarder, uint16_t port); configuration_t *forwarder_get_configuration(forwarder_t *forwarder); -subscription_table_t *forwarder_get_subscriptions(forwarder_t *forwarder); +subscription_table_t *forwarder_get_subscriptions(const forwarder_t *forwarder); /** * Returns the set of currently active listeners @@ -84,7 +84,7 @@ subscription_table_t *forwarder_get_subscriptions(forwarder_t *forwarder); * @retval non-null The set of active listeners * @retval null An error */ -listener_table_t *forwarder_get_listener_table(forwarder_t *forwarder); +listener_table_t *forwarder_get_listener_table(const forwarder_t *forwarder); /** * Returns the forwrder's connection table @@ -122,40 +122,43 @@ void forwarder_cs_clear(forwarder_t *forwarder); /** * @brief Adds or updates a route on all the message processors */ -bool forwarder_add_or_update_route(forwarder_t *forwarder, ip_prefix_t *prefix, +bool forwarder_add_or_update_route(forwarder_t *forwarder, + hicn_ip_prefix_t *prefix, unsigned ingress_id); /** * @brief Removes a route from all the message processors */ -bool forwarder_remove_route(forwarder_t *forwarder, ip_prefix_t *prefix, +bool forwarder_remove_route(forwarder_t *forwarder, hicn_ip_prefix_t *prefix, unsigned ingress_id); #ifdef WITH_POLICY /** * @brief Adds or updates a policy on the message processor */ -bool forwarder_add_or_update_policy(forwarder_t *forwarder, ip_prefix_t *prefix, +bool forwarder_add_or_update_policy(forwarder_t *forwarder, + hicn_ip_prefix_t *prefix, hicn_policy_t *policy); /** * @brief Removes a policy from the message processor */ -bool forwarder_remove_policy(forwarder_t *forwarder, ip_prefix_t *prefix); +bool forwarder_remove_policy(forwarder_t *forwarder, hicn_ip_prefix_t *prefix); #endif /* WITH_POLICY */ /** * Removes a connection id from all routes */ -void forwarder_remove_connection_id_from_routes(forwarder_t *forwarder, +void forwarder_remove_connection_id_from_routes(const forwarder_t *forwarder, unsigned connection_id); -void forwarder_add_strategy_options(forwarder_t *forwarder, Name *name_prefix, +void forwarder_add_strategy_options(forwarder_t *forwarder, + hicn_prefix_t *name_prefix, strategy_type_t strategy_type, strategy_options_t *strategy_options); -void forwarder_set_strategy(forwarder_t *forwarder, Name *name_prefix, +void forwarder_set_strategy(forwarder_t *forwarder, hicn_prefix_t *prefix, strategy_type_t strategy_type, strategy_options_t *strategy_options); @@ -178,7 +181,7 @@ void forwarder_acquired_msgbuf_ids_push(const forwarder_t *forwarder, * @param[in] forwarder - Pointer to the forwarder. * @returns Pointer to the hICN FIB. */ -fib_t *forwarder_get_fib(forwarder_t *forwarder); +fib_t *forwarder_get_fib(const forwarder_t *forwarder); /** * @brief Return the forwarder packet pool. @@ -190,6 +193,16 @@ msgbuf_pool_t *forwarder_get_msgbuf_pool(const forwarder_t *forwarder); #ifdef WITH_MAPME +void forwarder_on_route_event(const forwarder_t *forwarder, fib_entry_t *entry); + +int forwarder_add_connection(const forwarder_t *forwarder, + const char *symbolic_name, face_type_t type, + address_pair_t *pair, policy_tags_t tags, + int priority, face_state_t admin_state); + +int forwarder_remove_connection(const forwarder_t *forwarder, + unsigned connection_id, bool finalize); + /** * @brief Callback fired upon addition of a new connection through the * control protocol. diff --git a/hicn-light/src/hicn/core/interest_manifest.c b/hicn-light/src/hicn/core/interest_manifest.c deleted file mode 100644 index 1be8a3fb5..000000000 --- a/hicn-light/src/hicn/core/interest_manifest.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2022 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "interest_manifest.h" - -int_manifest_split_strategy_t disaggregation_strategy = - INT_MANIFEST_SPLIT_MAX_N_SUFFIXES; -unsigned N_SUFFIXES_PER_SPIT = 256; - -bool interest_manifest_is_valid(interest_manifest_header_t *int_manifest_header, - size_t payload_length) { - if (int_manifest_header->n_suffixes == 0 || - int_manifest_header->n_suffixes > MAX_SUFFIXES_IN_MANIFEST) { - ERROR("Manifest with invalid number of suffixes (%d)", - int_manifest_header->n_suffixes); - return false; - } - - uint32_t empty_bitmap[BITMAP_SIZE] = {0}; - if (memcmp(empty_bitmap, int_manifest_header->request_bitmap, - sizeof(empty_bitmap)) == 0) { - ERROR("Manifest with empty bitmap"); - return false; - } - - if (payload_length - sizeof(interest_manifest_header_t) != - int_manifest_header->n_suffixes * sizeof(u32)) { - ERROR("Size of suffixes in intereset manifest (%d) is not equal to %d", - payload_length - sizeof(interest_manifest_header_t), - int_manifest_header->n_suffixes * sizeof(u32)); - return false; - } - - return true; -} - -int interest_manifest_update_bitmap(const u32 *initial_bitmap, - u32 *bitmap_to_update, int start, int n, - int max_suffixes) { - int i = start, n_ones = 0; - while (i < n) { - if (is_bit_set(initial_bitmap, i)) { - set_bit(bitmap_to_update, i); - n_ones++; - } - i++; - - if (n_ones == max_suffixes) break; - } - - return i; -} diff --git a/hicn-light/src/hicn/core/interest_manifest.h b/hicn-light/src/hicn/core/interest_manifest.h deleted file mode 100644 index fcb2b9897..000000000 --- a/hicn-light/src/hicn/core/interest_manifest.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2022 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef HICNLIGHT_INTEREST_MANIFEST_H -#define HICNLIGHT_INTEREST_MANIFEST_H - -#include <string.h> -#include <stdbool.h> - -#include <hicn/util/log.h> -#include <hicn/base.h> - -typedef enum { - INT_MANIFEST_SPLIT_NONE, - INT_MANIFEST_SPLIT_MAX_N_SUFFIXES -} int_manifest_split_strategy_t; - -extern int_manifest_split_strategy_t disaggregation_strategy; -extern unsigned N_SUFFIXES_PER_SPIT; - -bool interest_manifest_is_valid(interest_manifest_header_t *int_manifest_header, - size_t payload_length); - -int interest_manifest_update_bitmap(const u32 *initial_bitmap, - u32 *bitmap_to_update, int start, int n, - int max_suffixes); - -#endif /* HICNLIGHT_INTEREST_MANIFEST_H */ diff --git a/hicn-light/src/hicn/core/listener.c b/hicn-light/src/hicn/core/listener.c index 188f0c317..a3c5c8a12 100644 --- a/hicn-light/src/hicn/core/listener.c +++ b/hicn-light/src/hicn/core/listener.c @@ -247,38 +247,8 @@ unsigned listener_create_connection(listener_t *listener, connection_table_print_by_pair(table); }) -#if 0 - DEBUG("Notification for new connections"); - // Generate notification message - flag_interface_type_t interface_type = - FLAG_INTERFACE_TYPE_WIRED | FLAG_INTERFACE_TYPE_CELLULAR; - struct { - cmd_header_t header; - hc_event_interface_update_t payload; - } msg = {.header = - { - .message_type = NOTIFICATION_LIGHT, - .command_id = EVENT_INTERFACE_UPDATE, - .length = 0, - .seq_num = 0, - }, - .payload = {.interface_type = interface_type}}; - size_t size = sizeof(msg); - - // Retrieve subscribed connections - subscription_table_t *subscriptions = - forwarder_get_subscriptions(listener->forwarder); - unsigned *subscribed_conn_ids = subscription_table_get_connections_for_topic( - subscriptions, TOPIC_CONNECTION); - - // Send notification to subscribed connections - for (int i = 0; i < vector_len(subscribed_conn_ids); i++) { - DEBUG("Sending notification to connection: %u", subscribed_conn_ids[i]); - const connection_t *conn = - connection_table_at(table, subscribed_conn_ids[i]); - connection_send_packet(conn, (uint8_t *)&msg, size); - } -#endif + forwarder_on_connection_event(listener->forwarder, connection, + CONNECTION_EVENT_CREATE); return connection_id; } @@ -441,4 +411,4 @@ void listener_setup_local(forwarder_t *forwarder, uint16_t port) { address_t localhost_ipv6_addr = ADDRESS6_LOCALHOST(port); listener_create(FACE_TYPE_UDP_LISTENER, &localhost_ipv6_addr, "lo", "lo_udp6", forwarder); -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/core/listener_table.c b/hicn-light/src/hicn/core/listener_table.c index 220b738bb..c130399a5 100644 --- a/hicn-light/src/hicn/core/listener_table.c +++ b/hicn-light/src/hicn/core/listener_table.c @@ -58,7 +58,7 @@ void listener_table_free(listener_table_t *table) { kh_foreach(table->id_by_key, k_key, v, { listener = listener_table_get_by_id(table, v); name = listener_get_name(listener); - INFO("Removing listner %s [%d]", name, listener->fd); + INFO("Removing listener %s [%d]", name, listener->fd); listener_finalize(listener); }); @@ -199,4 +199,4 @@ void listener_table_print_by_name(const listener_table_t *table) { INFO("%s:%d - %s\t\t\t\t(%u, %s)", addr_str, port, face_type_str(key->type), v, k); }) -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/core/listener_table.h b/hicn-light/src/hicn/core/listener_table.h index 7e2e99d7f..27c5daa04 100644 --- a/hicn-light/src/hicn/core/listener_table.h +++ b/hicn-light/src/hicn/core/listener_table.h @@ -161,9 +161,13 @@ listener_t *_listener_table_get_by_id(listener_table_t *table, off_t id); #define listener_table_get_listener_id(table, listener) \ (listener - table->listeners) -#define listener_table_foreach(table, listener, BODY) \ - pool_foreach( \ - table->listeners, listener, do { BODY } while (0)) +#define listener_table_foreach(table, listener, BODY) \ + do { \ + listener_t *listener; \ + (void)listener; \ + pool_foreach( \ + table->listeners, listener, do { BODY } while (0)); \ + } while (0) #define listener_table_enumerate(table, i, conn, BODY) \ pool_enumerate(table->listeners, (i), (conn), BODY) diff --git a/hicn-light/src/hicn/core/mapme.c b/hicn-light/src/hicn/core/mapme.c index dfb30da5c..b151d6cb0 100644 --- a/hicn-light/src/hicn/core/mapme.c +++ b/hicn-light/src/hicn/core/mapme.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -294,15 +294,6 @@ static void mapme_create_tfib(const mapme_t *mapme, fib_entry_t *entry) { fib_entry_set_user_data(entry, tfib, (void (*)(void **))mapme_release_tfib); } -int hicn_prefix_from_name(const Name *name, hicn_prefix_t *prefix) { - NameBitvector *bv = name_GetContentName(name); - ip_prefix_t ip_prefix; - nameBitvector_ToIPAddress(bv, &ip_prefix); - - /* The name length will be equal to ip address' prefix length */ - return hicn_prefix_create_from_ip_prefix(&ip_prefix, prefix); -} - /** * @brief Update/Notification heuristic: * @@ -350,12 +341,14 @@ int mapme_send_to_nexthops(const mapme_t *mapme, fib_entry_t *entry, tfib = TFIB(entry); } - const Name *name = fib_entry_get_prefix(entry); + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); WITH_DEBUG({ - char *name_str = name_ToString(name); - DEBUG("sending IU/IN for name %s on all nexthops", name_str); - free(name_str); + char buf[MAXSZ_HICN_PREFIX]; + int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "(error)"); + DEBUG("sending IU/IN for name %s on all nexthops", buf); }) mapme_params_t params = { @@ -364,14 +357,8 @@ int mapme_send_to_nexthops(const mapme_t *mapme, fib_entry_t *entry, .seq = tfib->seq, }; - hicn_prefix_t prefix; - if (hicn_prefix_from_name(name, &prefix) < 0) { - ERROR("Failed to create lib's name"); - return -1; - } - uint8_t packet[MTU]; - size_t size = hicn_mapme_create_packet(packet, &prefix, ¶ms); + size_t size = hicn_mapme_create_packet(packet, prefix, ¶ms); if (size <= 0) { ERROR("Could not create MAP-Me packet"); return -1; @@ -379,7 +366,6 @@ int mapme_send_to_nexthops(const mapme_t *mapme, fib_entry_t *entry, connection_table_t *table = forwarder_get_connection_table(mapme->forwarder); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { INFO("sending mapme packet on connection %d", nexthop); const connection_t *conn = connection_table_get_by_id(table, nexthop); @@ -389,6 +375,7 @@ int mapme_send_to_nexthops(const mapme_t *mapme, fib_entry_t *entry, return 0; } +#if 0 /** * * Here nexthops is not necessarily FIB nexthops as we might advertise given FIB @@ -410,6 +397,7 @@ void mapme_maybe_send_to_nexthops(const mapme_t *mapme, fib_entry_t *fib_entry, mapme_send_to_nexthops(mapme, fib_entry, nexthops); } +#endif /****************************************************************************** * MAPME API @@ -423,15 +411,16 @@ int mapme_set_all_adjacencies(const mapme_t *mapme, fib_entry_t *entry) { /* Apply the policy of the fib_entry over all neighbours */ nexthops_t new_nexthops = NEXTHOPS_EMPTY; - nexthops_t *nexthops = - fib_entry_get_available_nexthops(entry, ~0, &new_nexthops); + nexthops_t *nexthops = fib_entry_get_mapme_nexthops(entry, &new_nexthops); /* We set force to true to avoid overriding the FIB cache */ - return mapme_set_adjacencies(mapme, entry, nexthops, true); + return mapme_set_adjacencies(mapme, entry, nexthops); } +// XXX this will change with the FIB cache +// XXX we are sometimes incrementing tfib seq for nothing int mapme_set_adjacencies(const mapme_t *mapme, fib_entry_t *entry, - nexthops_t *nexthops, bool force) { + nexthops_t *nexthops) { if (mapme->enabled == false) { WARN("MAP-Me is NOT enabled"); return -1; @@ -449,12 +438,7 @@ int mapme_set_adjacencies(const mapme_t *mapme, fib_entry_t *entry, nexthops_clear(&tfib->nexthops); tfib->seq++; - if (force) { - mapme_send_to_nexthops(mapme, entry, nexthops); - return 0; - } - - mapme_maybe_send_to_nexthops(mapme, entry, nexthops); + mapme_send_to_nexthops(mapme, entry, nexthops); return 0; } @@ -473,7 +457,7 @@ int mapme_update_adjacencies(const mapme_t *mapme, fib_entry_t *entry, if (inc_iu_seq) tfib->seq++; - mapme_maybe_send_to_nexthops(mapme, entry, &tfib->nexthops); + mapme_send_to_nexthops(mapme, entry, &tfib->nexthops); return 0; } @@ -490,6 +474,7 @@ int mapme_send_to_nexthop(const mapme_t *mapme, fib_entry_t *entry, return mapme_send_to_nexthops(mapme, entry, &nexthops); } +#if 0 /* * Callback called everytime a new connection is created by the control protocol */ @@ -539,9 +524,9 @@ void mapme_on_connection_event(const mapme_t *mapme, /* We need to send a MapMe update on the newly selected connections for * each concerned fib_entry : connection is involved, or no more involved */ const fib_t *fib = forwarder_get_fib(mapme->forwarder); - fib_entry_t *entry; fib_foreach_entry(fib, entry, { mapme_set_all_adjacencies(mapme, entry); }); } +#endif /*------------------------------------------------------------------------------ * Special Interest handling @@ -811,30 +796,25 @@ static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf, uint8_t *ack_packet = msgbuf_get_packet(ack); size_t size = hicn_mapme_create_ack(ack_packet, params); - if (connection_send_packet(conn_in, ack_packet, size) < 0) { + if (!connection_send_packet(conn_in, ack_packet, size)) { /* We accept the packet knowing we will get a retransmit */ ERROR("Failed to send ACK packet"); } msgbuf_pool_put(msgbuf_pool, ack); - /* process received interest */ - uint8_t *packet = msgbuf_get_packet(msgbuf); - name_create_from_interest(packet, msgbuf_get_name(msgbuf)); - Name name = EMPTY_NAME; - name_Copy(msgbuf_get_name(msgbuf), &name); - name_setLen(&name, prefix->len); - WITH_DEBUG({ - char *name_str = name_ToString(&name); - DEBUG("Ack'ed interest : connection=%d prefix=%s seq=%d", ingress_id, - name_str, params->seq); - free(name_str); + char buf[MAXSZ_HICN_PREFIX]; + int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(error)"); + DEBUG("Ack'ed interest : connection=%d prefix=%s seq=%d", ingress_id, buf, + params->seq); }); /* EPM on FIB */ const fib_t *fib = forwarder_get_fib(mapme->forwarder); - fib_entry_t *entry = fib_contains(fib, &name); + fib_entry_t *entry = fib_contains(fib, prefix); if (!entry) { #ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY if (mapme_create_fib_entry(mapme, &name, ingress_id) < 0) { @@ -883,7 +863,6 @@ static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf, * This could might optimized for situations where nothing changes, but * this is very unlikely if not impossible... * */ - unsigned prevhop; nexthops_foreach(&entry->nexthops, prevhop, { nexthops_add(&tfib->nexthops, prevhop); }); nexthops_remove(&tfib->nexthops, ingress_id); @@ -943,23 +922,17 @@ static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf, static void mapme_on_data(mapme_t *mapme, msgbuf_t *msgbuf, unsigned ingress_id, hicn_prefix_t *prefix, mapme_params_t *params) { - INFO("Receive IU/IN Ack on connection %d", ingress_id); - - uint8_t *packet = msgbuf_get_packet(msgbuf); - name_create_from_data(packet, msgbuf_get_name(msgbuf)); - Name name = EMPTY_NAME; - name_Copy(msgbuf_get_name(msgbuf), &name); - name_setLen(&name, prefix->len); - WITH_DEBUG({ - char *name_str = name_ToString(&name); - DEBUG("Received ack for name prefix=%s seq=%d on conn id=%d", name_str, + char buf[MAXSZ_HICN_PREFIX]; + int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "(error)"); + DEBUG("Received ack for name prefix=%s seq=%d on conn id=%d", buf, params->seq, ingress_id); - free(name_str); }) const fib_t *fib = forwarder_get_fib(mapme->forwarder); - fib_entry_t *entry = fib_contains(fib, &name); + fib_entry_t *entry = fib_contains(fib, prefix); if (!entry) { INFO("Ignored ACK with no corresponding FIB entry"); return; @@ -1031,6 +1004,7 @@ void mapme_process(mapme_t *mapme, msgbuf_t *msgbuf) { } } +#if 0 /* * Returns true iif the message corresponds to a MAP-Me packet */ @@ -1048,6 +1022,7 @@ bool mapme_match_packet(const uint8_t *packet) { return false; } } +#endif void mapme_set_enable(mapme_t *mapme, bool enable) { mapme->enabled = enable; } void mapme_set_discovery(mapme_t *mapme, bool enable) { diff --git a/hicn-light/src/hicn/core/mapme.h b/hicn-light/src/hicn/core/mapme.h index 8c2ca477f..188607421 100644 --- a/hicn-light/src/hicn/core/mapme.h +++ b/hicn-light/src/hicn/core/mapme.h @@ -26,7 +26,7 @@ #include <stdbool.h> #include <stdint.h> -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/ctrl/hicn-light.h> #include <hicn/hicn.h> #include "connection.h" @@ -87,7 +87,7 @@ int mapme_set_all_adjacencies(const mapme_t *mapme, fib_entry_t *entry); * @param [in] nexthops - next hops on which to send the update. */ int mapme_set_adjacencies(const mapme_t *mapme, fib_entry_t *entry, - nexthops_t *nexthops, bool force); + nexthops_t *nexthops); /** * @function mapme_update_adjacencies diff --git a/hicn-light/src/hicn/core/messageHandler.h b/hicn-light/src/hicn/core/messageHandler.h deleted file mode 100644 index fe26d0579..000000000 --- a/hicn-light/src/hicn/core/messageHandler.h +++ /dev/null @@ -1,660 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef HICNLIGHT_MESSAGE_HANDLER_H -#define HICNLIGHT_MESSAGE_HANDLER_H - -#include <stdlib.h> -#ifndef _WIN32 -#include <unistd.h> // close -#endif /* _WIN32 */ - -#include <hicn/hicn.h> - -//#include <hicn/core/connection_table.h> - -#define H(packet) ((hicn_header_t *)packet) -#define H6(packet) (H(packet)->v6.ip) -#define H6T(packet) (H(packet)->v6.tcp) -#define H4(packet) (H(packet)->v4.ip) -#define H4T(packet) (H(packet)->v4.tcp) - -#define HICN_V6_LEN(packet) (H6(packet).len) -#define HICN_V4_LEN(packet) (H4(packet).len) - -/*** codes and types ***/ -#define IPv6_TYPE 6 -#define IPv4_TYPE 4 -#define ICMP_WLDR_TYPE 42 -#define ICMP_WLDR_CODE 0 -#define ICMP_LB_TYPE 43 - -/*** masks and constants ***/ -#define PATH_LABEL_MASK 0x8000 // 1000 0000 0000 0000 -#define NOT_PATH_LABEL_MASK 0x7fff // 0111 0000 0000 0000 -#define UINT16_T_MASK 0x0000ffff // 1111 1111 1111 1111 - -/*** HICN ALLOWED PORTS ***/ -#define CONTROL_PORT 9695 -#define HTTP_PORT 8080 - -#define MIN_PROBE_SUFFIX 0xefffffff -#define MAX_PROBE_SUFFIX 0xffffffff - 1 - -// XXX Hardcoded packet format HF_INET6_TCP - -#define IPV6_DEFAULT_VERSION 6 -#define IPV6_DEFAULT_TRAFFIC_CLASS 0 -#define IPV6_DEFAULT_FLOW_LABEL 0 - -//#include <hicn/core/forwarder.h> - -//#ifdef WITH_MAPME -//#include <hicn/core/mapme.h> -//#include <hicn/socket/api.h> -//#endif /* WITH_MAPME */ - -#define BFD_PORT 3784 - -static inline uint8_t messageHandler_GetIPPacketType(const uint8_t *message) { - return HICN_IP_VERSION(message); -} - -static inline void messageHandler_UpdateTCPCheckSum(uint8_t *message, - uint16_t *old_val, - uint16_t *new_val, - uint8_t size) { - switch (messageHandler_GetIPPacketType(message)) { - case IPv4_TYPE: - for (uint8_t i = 0; i < size; i++) { - uint16_t old_csum = ~(H4T(message).csum); - uint16_t not_old_val = ~(*old_val); - uint32_t sum = (uint32_t)old_csum + not_old_val + *new_val; - - while (sum >> 16) { - sum = (sum >> 16) + (sum & UINT16_T_MASK); - } - - H4T(message).csum = ~sum; - ++old_val; - ++new_val; - } - break; - case IPv6_TYPE: - for (uint8_t i = 0; i < size; i++) { - uint16_t old_csum = ~(H6T(message).csum); - uint16_t not_old_val = ~(*old_val); - uint32_t sum = (uint32_t)old_csum + not_old_val + *new_val; - - while (sum >> 16) { - sum = (sum >> 16) + (sum & UINT16_T_MASK); - } - - H6T(message).csum = ~sum; - ++old_val; - ++new_val; - } - break; - default: - return; - } -} - -static inline void messageHandler_UpdateIPv4CheckSum(uint8_t *message, - uint16_t *old_val, - uint16_t *new_val, - uint8_t size) { - for (uint8_t i = 0; i < size; i++) { - uint16_t old_csum = ~(H4(message).csum); - uint16_t not_old_val = ~(*old_val); - uint32_t sum = (uint32_t)old_csum + not_old_val + *new_val; - - while (sum >> 16) { - sum = (sum >> 16) + (sum & UINT16_T_MASK); - } - - H4(message).csum = ~sum; - ++old_val; - ++new_val; - } -} - -static inline size_t messageHandler_GetEmptyTCPPacketSize(unsigned ipVersion) { - if (ipVersion == IPv4_TYPE) - return IPV4_HDRLEN + TCP_HDRLEN; - else if (ipVersion == IPv6_TYPE) - return IPV6_HDRLEN + TCP_HDRLEN; - else - return 0; -} - -static inline size_t messageHandler_GetICMPPacketSize(unsigned ipVersion) { - if (ipVersion == IPv4_TYPE) - return IPV4_HDRLEN + ICMP_HDRLEN; - else if (ipVersion == IPv6_TYPE) - return IPV6_HDRLEN + ICMP_HDRLEN; - else - return 0; -} - -static inline size_t messageHandler_GetIPHeaderLength(unsigned ipVersion) { - if (ipVersion == IPv4_TYPE) - return IPV4_HDRLEN; - else if (ipVersion == IPv6_TYPE) - return IPV6_HDRLEN; - else - return 0; -} - -#if 0 -static inline bool messageHandler_IsValidHicnPacket(const uint8_t *message) { - uint8_t version = messageHandler_GetIPPacketType(message); - if (version == IPv6_TYPE || version == IPv4_TYPE) { - return true; - } - return false; -} -#endif - -static inline uint8_t messageHandler_NextHeaderType(const uint8_t *message) { - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - return (uint8_t)H6(message).nxt; - case IPv4_TYPE: - return (uint8_t)H4(message).protocol; - default: - return 0; - } -} - -static inline bool messageHandler_IsTCP(const uint8_t *message) { - if (messageHandler_NextHeaderType(message) != IPPROTO_TCP) return false; - return true; -} - -static inline bool messageHandler_IsInterest(const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return false; - - bool flag; - hicn_packet_test_ece(HF_INET6_TCP, (hicn_header_t *)message, - &flag); // ECE flag is set to 0 in interest packets - if (flag == false) return true; - return false; -} - -static inline bool messageHandler_IsData(const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return false; - - bool flag; - hicn_packet_test_ece(HF_INET6_TCP, (hicn_header_t *)message, - &flag); // ECE flag is set to 1 in data packets - if (flag == true) return true; - return false; -} - -static inline bool messageHandler_IsWldrNotification(const uint8_t *message) { - // this function returns true only if the packet is an ICMP packet in Wldr - // form. type must be equal to ICMP_WLDR_TYPE and code equal to ICMP_WLDR_CODE - uint8_t next_header = messageHandler_NextHeaderType(message); - - const uint8_t *icmp_ptr; - if (next_header == IPPROTO_ICMP) { - icmp_ptr = message + IPV4_HDRLEN; - } else if (next_header == IPPROTO_ICMPV6) { - icmp_ptr = message + IPV6_HDRLEN; - } else { - return false; - } - - uint8_t type = ((_icmp_header_t *)icmp_ptr)->type; - uint8_t code = ((_icmp_header_t *)icmp_ptr)->code; - if (type == ICMP_WLDR_TYPE && code == ICMP_WLDR_CODE) { - return true; - } - - return false; -} - -static inline bool messageHandler_IsLoadBalancerProbe(const uint8_t *message) { - uint8_t next_header = messageHandler_NextHeaderType(message); - - const uint8_t *icmp_ptr; - if (next_header == IPPROTO_ICMP) { - icmp_ptr = message + IPV4_HDRLEN; - } else if (next_header == IPPROTO_ICMPV6) { - icmp_ptr = message + IPV6_HDRLEN; - } else { - return false; - } - - uint8_t type = ((_icmp_header_t *)icmp_ptr)->type; - if (type == ICMP_LB_TYPE) { - return true; - } - - return false; -} - -static inline uint16_t messageHandler_GetTotalPacketLength( - const uint8_t *message) { - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - return ntohs((uint16_t)HICN_V6_LEN(message)) + IPV6_HDRLEN; - case IPv4_TYPE: - return ntohs((uint16_t)HICN_V4_LEN(message)); - default: - return 0; - } -} - -static inline uint32_t messageHandler_GetSegment(const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return 0; - - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - return ntohl((uint32_t)H6T(message).seq); - case IPv4_TYPE: - return ntohl((uint32_t)H4T(message).seq); - default: - return 0; - } -} - -static inline uint16_t messageHandler_GetExpectedWldrLabel( - const uint8_t *message) { - const uint8_t *icmp_ptr; - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - icmp_ptr = message + IPV6_HDRLEN; - break; - case IPv4_TYPE: - icmp_ptr = message + IPV4_HDRLEN; - break; - default: - return 0; - } - - return ntohs( - ((_icmp_wldr_header_t *)icmp_ptr)->wldr_notification_lbl.expected_lbl); -} - -static inline uint16_t messageHandler_GetWldrLastReceived( - const uint8_t *message) { - const uint8_t *icmp_ptr; - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - icmp_ptr = message + IPV6_HDRLEN; - break; - case IPv4_TYPE: - icmp_ptr = message + IPV4_HDRLEN; - break; - default: - return 0; - } - - return ntohs( - ((_icmp_wldr_header_t *)icmp_ptr)->wldr_notification_lbl.received_lbl); -} - -static inline uint16_t messageHandler_GetWldrLabel(const uint8_t *message) { - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - return ntohs((uint16_t)H6T(message).window); - case IPv4_TYPE: - return ntohs((uint16_t)H4T(message).window); - default: - return 0; - } -} - -static inline void messageHandler_SetWldrLabel(uint8_t *message, - uint16_t label) { - uint16_t old_val = messageHandler_GetWldrLabel(message); - - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - H6T(message).window = htons(label); - break; - case IPv4_TYPE: - H4T(message).window = htons(label); - break; - default: - break; - } - - messageHandler_UpdateTCPCheckSum(message, &old_val, &label, 1); -} - -static inline void messageHandler_ResetWldrLabel(uint8_t *message) { - messageHandler_SetWldrLabel(message, 0); -} - -static inline bool messageHandler_HasWldr(const uint8_t *message) { - if (messageHandler_IsTCP(message)) { - uint16_t lbl = messageHandler_GetWldrLabel(message); - if (lbl != 0) { - return true; - } - } - return false; -} - -static inline uint32_t messageHandler_GetPathLabel(const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return 0; - - uint32_t path_label; - int res = hicn_data_get_path_label((hicn_header_t *)message, &path_label); - if (res < 0) return 0; - return path_label; -} - -static inline void messageHandler_SetPathLabel(uint8_t *message, - uint32_t old_path_label, - uint32_t new_path_label) { - if (!messageHandler_IsTCP(message)) return; - - hicn_data_set_path_label((hicn_header_t *)message, new_path_label); - - messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&old_path_label, - (uint16_t *)&new_path_label, 2); -} - -static inline void messageHandler_UpdatePathLabel(uint8_t *message, - uint8_t outFace) { - if (!messageHandler_IsTCP(message)) return; - - uint32_t pl_old_32bit = messageHandler_GetPathLabel(message); - uint8_t pl_old_8bit = (uint8_t)(pl_old_32bit >> 24UL); - uint32_t pl_new_32bit = - (uint32_t)((((pl_old_8bit << 1) | (pl_old_8bit >> 7)) ^ outFace) << 24UL); - - // XXX path label should be 8 bits now ? - messageHandler_SetPathLabel(message, pl_old_32bit, pl_new_32bit); -} - -static inline void messageHandler_ResetPathLabel(uint8_t *message) { - messageHandler_SetPathLabel(message, messageHandler_GetPathLabel(message), 0); -} - -static inline uint32_t messageHandler_GetInterestLifetime( - const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return 0; - - hicn_lifetime_t lifetime; - int res = hicn_interest_get_lifetime((hicn_header_t *)message, &lifetime); - if (res < 0) return 0; - return lifetime; -} - -static inline bool messageHandler_SetInterestLifetime(uint8_t *message, - u32 lifetime) { - if (!messageHandler_IsTCP(message)) return false; - - int res = hicn_interest_set_lifetime((hicn_header_t *)message, lifetime); - if (res < 0) return false; - return true; -} - -static inline bool messageHandler_SetDataExpiryTime(uint8_t *message, - u32 lifetime) { - if (!messageHandler_IsTCP(message)) return false; - - int res = hicn_data_set_expiry_time((hicn_header_t *)message, lifetime); - if (res < 0) return false; - return true; -} - -static inline bool messageHandler_HasInterestLifetime(const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return false; - - if (messageHandler_GetInterestLifetime(message) == 0) return false; - return true; -} - -static inline uint32_t messageHandler_GetContentExpiryTime( - const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return 0; - - uint32_t expirationTime; - int res = - hicn_data_get_expiry_time((hicn_header_t *)message, &expirationTime); - if (res < 0) return 0; - return expirationTime; -} - -static inline bool messageHandler_HasContentExpiryTime(const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return 0; - - uint32_t expirationTime; - int res = - hicn_data_get_expiry_time((hicn_header_t *)message, &expirationTime); - if (res < 0) return false; - - if (expirationTime == HICN_MAX_LIFETIME) return false; - - return true; -} - -static inline void *messageHandler_GetSource(const uint8_t *message) { - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - return &H6(message).saddr; - break; - case IPv4_TYPE: - return &H4(message).saddr; - break; - default: - return NULL; - } -} - -static inline void *messageHandler_GetDestination(const uint8_t *message) { - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - return &H6(message).daddr; - break; - case IPv4_TYPE: - return &H4(message).daddr; - break; - default: - return NULL; - } -} - -static inline void messageHandler_SetSource_IPv6(uint8_t *message, - struct in6_addr *address) { - if (messageHandler_IsTCP(message)) { - uint16_t *old_src = (uint16_t *)messageHandler_GetSource(message); - messageHandler_UpdateTCPCheckSum(message, old_src, (uint16_t *)address, 8); - } - H6(message).saddr.as_in6addr = *address; -} - -static inline void messageHandler_SetDestination_IPv6( - uint8_t *message, struct in6_addr *address) { - if (messageHandler_IsTCP(message)) { - uint16_t *old_dst = (uint16_t *)messageHandler_GetDestination(message); - messageHandler_UpdateTCPCheckSum(message, old_dst, (uint16_t *)address, 8); - } - H6(message).daddr.as_in6addr = *address; -} - -static inline void messageHandler_SetSource_IPv4(uint8_t *message, - uint32_t *address) { - // update tcp checksum - uint16_t *old_src = (uint16_t *)messageHandler_GetSource(message); - if (messageHandler_IsTCP(message)) { - messageHandler_UpdateTCPCheckSum(message, old_src, (uint16_t *)address, 2); - } - // update IPv4 cheksum - // the IPv4 checksum is not part of the psudo header for TCP checksum - // calculation we can update them separetelly - messageHandler_UpdateIPv4CheckSum(message, old_src, (uint16_t *)address, 2); - - H4(message).saddr.as_u32 = *address; -} - -static inline void messageHandler_SetDestination_IPv4(uint8_t *message, - uint32_t *address) { - uint16_t *old_dst = (uint16_t *)messageHandler_GetDestination(message); - if (messageHandler_IsTCP(message)) { - messageHandler_UpdateTCPCheckSum(message, old_dst, (uint16_t *)address, 2); - } - messageHandler_UpdateIPv4CheckSum(message, old_dst, (uint16_t *)address, 2); - H4(message).daddr.as_u32 = *address; -} - -static inline void messageHandler_SetWldrNotification(uint8_t *notification, - uint8_t *original, - uint16_t expected, - uint16_t received) { - hicn_header_t *h = (hicn_header_t *)notification; - switch (messageHandler_GetIPPacketType(original)) { - case IPv6_TYPE: { - *h = (hicn_header_t){.v6 = { - .ip = - (_ipv6_header_t){ - .version_class_flow = htonl( - (IPV6_DEFAULT_VERSION << 28) | - (IPV6_DEFAULT_TRAFFIC_CLASS << 20) | - (IPV6_DEFAULT_FLOW_LABEL & 0xfffff)), - .len = htons(ICMP_HDRLEN), - .nxt = IPPROTO_ICMPV6, - .hlim = 5, - }, - /* - .wldr = - { - .type = ICMP_WLDR_TYPE, - .code = ICMP_WLDR_CODE, - .wldr_notification_lbl = - { - .expected_lbl = htons(expected), - .received_lbl = htons(received), - }, - },*/ - }}; - messageHandler_SetSource_IPv6( - notification, - (struct in6_addr *)messageHandler_GetDestination(original)); - messageHandler_SetDestination_IPv6( - notification, (struct in6_addr *)messageHandler_GetSource(original)); - break; - } - case IPv4_TYPE: { - break; - } - default: - break; - } -} - -static inline void messageHandler_ModifySuffix(uint8_t *packet, - uint32_t new_suffix) { - hicn_format_t format; - hicn_name_t name; - hicn_packet_get_format((hicn_header_t *)packet, &format); - hicn_interest_get_name(format, (hicn_header_t *)packet, &name); - hicn_name_set_seq_number(&name, new_suffix); - hicn_interest_set_name(format, (hicn_header_t *)packet, &name); -} - -static inline uint8_t *messageHandler_CreateProbePacket( - hicn_format_t format, uint32_t probe_lifetime) { - size_t header_length; - hicn_packet_get_header_length_from_format(format, &header_length); - - uint8_t *pkt = (uint8_t *)calloc(header_length, 1); - - hicn_packet_init_header(format, (hicn_header_t *)pkt); - - hicn_packet_set_dst_port(format, (hicn_header_t *)pkt, BFD_PORT); - hicn_interest_set_lifetime((hicn_header_t *)pkt, probe_lifetime); - - return pkt; -} - -static inline void messageHandler_CreateProbeReply(uint8_t *probe, - hicn_format_t format) { - hicn_name_t probe_name; - hicn_interest_get_name(format, (const hicn_header_t *)probe, &probe_name); - ip_address_t probe_locator; - hicn_interest_get_locator(format, (const hicn_header_t *)probe, - &probe_locator); - - uint16_t src_prt; - uint16_t dst_prt; - hicn_packet_get_src_port(format, (const hicn_header_t *)probe, &src_prt); - hicn_packet_get_dst_port(format, (const hicn_header_t *)probe, &dst_prt); - hicn_packet_set_src_port(format, (hicn_header_t *)probe, dst_prt); - hicn_packet_set_dst_port(format, (hicn_header_t *)probe, src_prt); - - hicn_data_set_name(format, (hicn_header_t *)probe, &probe_name); - hicn_data_set_locator(format, (hicn_header_t *)probe, &probe_locator); - hicn_data_set_expiry_time((hicn_header_t *)probe, 0); -} - -static inline hicn_name_t *messageHandler_CreateProbeName( - const ip_prefix_t *address) { - hicn_name_t *name = (hicn_name_t *)calloc(sizeof(hicn_name_t), 1); - hicn_name_create_from_ip_prefix(address, 0, name); - return name; -} - -static inline void messageHandler_SetProbeName(uint8_t *probe, - hicn_format_t format, - hicn_name_t *name, - uint32_t seq) { - hicn_name_set_seq_number(name, seq); - hicn_interest_set_name(format, (hicn_header_t *)probe, name); -} - -static inline bool messageHandler_IsAProbe(const uint8_t *packet) { - hicn_format_t format; - hicn_name_t name; - uint32_t seq; - hicn_packet_get_format((hicn_header_t *)packet, &format); - hicn_data_get_name(format, (hicn_header_t *)packet, &name); - hicn_name_get_seq_number(&name, &seq); - if (seq >= MIN_PROBE_SUFFIX && seq <= MAX_PROBE_SUFFIX) return true; - return false; - -#if 0 - // old probe version - uint16_t src_prt; - uint16_t dst_prt; - hicn_packet_get_src_port (HF_INET6_TCP, (const hicn_header_t *) packet, &src_prt); - hicn_packet_get_dst_port (HF_INET6_TCP, (const hicn_header_t *) packet, &dst_prt); - - if(dst_prt == BFD_PORT){ - //interest probe - return true; - } - - if(src_prt == BFD_PORT){ - //data (could be a probe) - uint32_t expiry_time; - hicn_data_get_expiry_time ((const hicn_header_t *) packet, &expiry_time); - if(expiry_time == 0){ - //this is a probe - return true; - } - } - - return false; -#endif -} - -#endif /* HICNLIGHT_MESSAGE_HANDLER_H */ diff --git a/hicn-light/src/hicn/core/msgbuf.c b/hicn-light/src/hicn/core/msgbuf.c index 299b20f9b..c58f7a7dc 100644 --- a/hicn-light/src/hicn/core/msgbuf.c +++ b/hicn-light/src/hicn/core/msgbuf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -19,3 +19,37 @@ */ #include "msgbuf.h" +#include "../strategies/probe_generator.h" + +int msgbuf_initialize(msgbuf_t *msgbuf) { + /* + * We define the format and the storage area of the packet buffer we + * manipulate + */ + hicn_packet_buffer_t *pkbuf = msgbuf_get_pkbuf(msgbuf); + hicn_packet_set_buffer(pkbuf, msgbuf->packet, MTU, 0); + hicn_packet_init_header(pkbuf, 0); + return 0; +} + +int msgbuf_initialize_from_packet(msgbuf_t *msgbuf) { + hicn_packet_set_buffer(msgbuf_get_pkbuf(msgbuf), msgbuf->packet, MTU, + msgbuf_get_len(msgbuf)); + return 0; +} + +bool msgbuf_is_command(const msgbuf_t *msgbuf) { + return (*msgbuf->packet == REQUEST_LIGHT); +} + +bool msgbuf_is_probe(const msgbuf_t *msgbuf) { + hicn_name_t name; + hicn_name_suffix_t suffix; + + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA); + + const hicn_packet_buffer_t *pkbuf = msgbuf_get_pkbuf(msgbuf); + hicn_data_get_name(pkbuf, &name); + suffix = hicn_name_get_suffix(&name); + return (suffix >= MIN_PROBE_SUFFIX && suffix <= MAX_PROBE_SUFFIX); +} diff --git a/hicn-light/src/hicn/core/msgbuf.h b/hicn-light/src/hicn/core/msgbuf.h index e437f1d09..26fd47540 100644 --- a/hicn-light/src/hicn/core/msgbuf.h +++ b/hicn-light/src/hicn/core/msgbuf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -21,10 +21,10 @@ #ifndef HICNLIGHT_MSGBUF #define HICNLIGHT_MSGBUF -#include "name.h" +#include <hicn/name.h> #include "ticks.h" -#include "messageHandler.h" -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/hicn.h> +#include <hicn/ctrl/hicn-light.h> #define MTU 1500 #define INVALID_MSGBUF_ID ~0ul @@ -32,33 +32,19 @@ #define msgbuf_id_is_valid(msgbuf_id) \ ((unsigned long)msgbuf_id != INVALID_MSGBUF_ID) -#define foreach_msg_type \ - _(UNDEFINED) \ - _(INTEREST) \ - _(DATA) \ - _(WLDR_NOTIFICATION) \ - _(MAPME) \ - _(COMMAND) \ - _(N) - -typedef enum { -#define _(x) MSGBUF_TYPE_##x, - foreach_msg_type -#undef _ -} msgbuf_type_t; -#undef foreach_msg_type - typedef struct { - unsigned length; - msgbuf_type_t type; - unsigned connection_id; - Ticks recv_ts; - unsigned refs; - unsigned path_label; + hicn_packet_buffer_t pkbuf; + unsigned connection_id; // ingress + Ticks recv_ts; // timestamp + unsigned refs; // refcount + unsigned path_label; // XXX what is this ? + + // XXX Cache storage union { /* Interest or data packet */ struct { - Name name; + hicn_name_t name; + u32 name_hash; // XXX should be always populate when name is assigned } id; /* Command packet */ struct { @@ -68,53 +54,142 @@ typedef struct { uint8_t packet[MTU]; } msgbuf_t; -#define msgbuf_get_name(M) (&((M)->id.name)) +int msgbuf_initialize(msgbuf_t *msgbuf); +int msgbuf_initialize_from_packet(msgbuf_t *msgbuf); + +#define msgbuf_get_pkbuf(M) (&(M)->pkbuf) + +static inline hicn_packet_type_t msgbuf_get_type(const msgbuf_t *msgbuf) { + return hicn_packet_get_type(msgbuf_get_pkbuf(msgbuf)); +} + +static inline void msgbuf_set_type(msgbuf_t *msgbuf, hicn_packet_type_t type) { + hicn_packet_set_type(msgbuf_get_pkbuf(msgbuf), type); +} + +static inline const hicn_name_t *msgbuf_get_name(const msgbuf_t *msgbuf) { + hicn_packet_type_t type = msgbuf_get_type(msgbuf); + assert(type == HICN_PACKET_TYPE_INTEREST || type == HICN_PACKET_TYPE_DATA); + (void)type; + + return &msgbuf->id.name; +} + #define msgbuf_get_connection_id(M) ((M)->connection_id) -#define msgbuf_get_type(M) ((M)->type) -#define msgbuf_has_wldr(M) (messageHandler_HasWldr((M)->packet)) -#define msgbuf_get_len(M) ((M)->length) #define msgbuf_get_packet(M) ((M)->packet) #define msgbuf_get_command_type(M) ((M)->command.type) +#if WITH_WLDR +#define msgbuf_has_wldr(M) (messageHandler_HasWldr((M)->packet)) +#endif + +static inline void msgbuf_set_name(msgbuf_t *msgbuf, const hicn_name_t *name) { + msgbuf->id.name = *name; +} + +static inline size_t msgbuf_get_len(const msgbuf_t *msgbuf) { + return hicn_packet_get_len(msgbuf_get_pkbuf(msgbuf)); +} -// XXX TODO EXPLAIN THE CONSTANT -#define msgbuf_get_lifetime(M) \ - (NSEC_TO_TICKS(messageHandler_GetInterestLifetime((M)->packet) * 1000000ULL)) +static inline void msgbuf_set_len(msgbuf_t *msgbuf, size_t len) { + int rc = hicn_packet_set_len(msgbuf_get_pkbuf(msgbuf), len); + assert(rc == HICN_LIB_ERROR_NONE); // XXX + _unused(rc); +} + +static inline u32 msgbuf_get_name_hash(const msgbuf_t *msgbuf) { + hicn_packet_type_t type = msgbuf_get_type(msgbuf); + assert(type == HICN_PACKET_TYPE_INTEREST || type == HICN_PACKET_TYPE_DATA); + _unused(type); + return msgbuf->id.name_hash; +} // Lifetimes/expiry times in milliseconds -#define msgbuf_get_interest_lifetime(M) \ - (messageHandler_GetInterestLifetime((M)->packet)) -#define msgbuf_get_data_expiry_time(M) \ - (messageHandler_GetContentExpiryTime((M)->packet)) +static inline u32 msgbuf_get_interest_lifetime(const msgbuf_t *msgbuf) { + u32 lifetime; + int rc = hicn_interest_get_lifetime(msgbuf_get_pkbuf(msgbuf), &lifetime); + assert(rc == HICN_LIB_ERROR_NONE); // XXX + _unused(rc); + return lifetime; +} + +//#define msgbuf_get_lifetime(M) +// (NSEC_TO_TICKS(messageHandler_GetInterestLifetime((M)->packet) * +// 1000000ULL)) +#define msgbuf_get_lifetime msgbuf_get_interest_lifetime static inline bool msgbuf_set_interest_lifetime(msgbuf_t *msgbuf, u32 lifetime) { - return messageHandler_SetInterestLifetime(msgbuf->packet, lifetime); + int rc = hicn_interest_set_lifetime(msgbuf_get_pkbuf(msgbuf), lifetime); + return (rc == HICN_LIB_ERROR_NONE); } -static inline bool msgbuf_set_data_expiry_time(msgbuf_t *msgbuf, u32 lifetime) { - return messageHandler_SetDataExpiryTime(msgbuf->packet, lifetime); + +static inline u32 msgbuf_get_data_expiry_time(const msgbuf_t *msgbuf) { + u32 lifetime; + int rc = hicn_data_get_expiry_time(msgbuf_get_pkbuf(msgbuf), &lifetime); + assert(rc == HICN_LIB_ERROR_NONE); // XXX + _unused(rc); + return lifetime; } -#define msgbuf_is_probe(M) messageHandler_IsAProbe((M)->packet) +static inline bool msgbuf_set_data_expiry_time(msgbuf_t *msgbuf, u32 lifetime) { + int rc = hicn_data_set_expiry_time(msgbuf_get_pkbuf(msgbuf), lifetime); + return (rc == HICN_LIB_ERROR_NONE); +} /* Path label */ -#define msgbuf_init_pathlabel(M) \ - ((M)->path_label = messageHandler_GetPathLabel((M)->packet)) -#define msgbuf_update_pathlabel(M, outface) \ - { \ - messageHandler_SetPathLabel((M)->packet, \ - messageHandler_GetPathLabel((M)->packet), \ - (M)->path_label); \ - messageHandler_UpdatePathLabel((M)->packet, outface); \ - } -#define msgbuf_reset_pathlabel(M) \ - { \ - (M)->path_label = 0; \ - messageHandler_ResetPathLabel((M)->packet); \ - } +static inline void msgbuf_init_pathlabel(msgbuf_t *msgbuf) { + hicn_path_label_t pl; + int rc = hicn_data_get_path_label(msgbuf_get_pkbuf(msgbuf), &pl); + assert(rc == HICN_LIB_ERROR_NONE); + _unused(rc); + msgbuf->path_label = pl; +} + +static inline int msgbuf_get_path_label(const msgbuf_t *msgbuf, + hicn_path_label_t *pl) { + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA); + return hicn_data_get_path_label(msgbuf_get_pkbuf(msgbuf), pl); +} + +static inline int msgbuf_set_path_label(msgbuf_t *msgbuf, + hicn_path_label_t pl) { + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA); + return hicn_data_set_path_label(msgbuf_get_pkbuf(msgbuf), pl); +} + +static inline int msgbuf_update_pathlabel(msgbuf_t *msgbuf, + hicn_faceid_t outface) { + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA); + + hicn_path_label_t pl, newpl; + if (msgbuf_get_path_label(msgbuf, &pl) < 0) return -1; + + update_path_label(pl, outface, &newpl); + + return msgbuf_set_path_label(msgbuf, newpl); +} + +static inline void msgbuf_reset_pathlabel(msgbuf_t *msgbuf) { + msgbuf->path_label = 0; + hicn_data_set_path_label(msgbuf_get_pkbuf(msgbuf), 0); + // ERROR ? +} + +static inline void msgbuf_modify_suffix(msgbuf_t *msgbuf, uint32_t new_suffix) { + hicn_name_t name; + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST); + hicn_interest_get_name(msgbuf_get_pkbuf(msgbuf), &name); + hicn_name_set_suffix(&name, new_suffix); + hicn_interest_set_name(msgbuf_get_pkbuf(msgbuf), &name); +} + +bool msgbuf_is_command(const msgbuf_t *msgbuf); +bool msgbuf_is_probe(const msgbuf_t *msgbuf); /* WLDR */ +#if 0 #define msgbuf_reset_wldr_label(M) (messageHandler_ResetWldrLabel((M)->packet)) #define msgbuf_get_wldr_label(M) (messageHandler_GetWldrLabel((M)->packet)) #define msgbuf_get_wldr_expected_label(M) \ @@ -123,5 +198,6 @@ static inline bool msgbuf_set_data_expiry_time(msgbuf_t *msgbuf, u32 lifetime) { (messageHandler_GetWldrLastReceived((M)->packet)) #define msgbuf_set_wldr_label(M, label) \ (messageHandler_GetWldrLabel((M)->packet, label)) +#endif #endif /* HICNLIGHT_MSGBUF */ diff --git a/hicn-light/src/hicn/core/msgbuf_pool.c b/hicn-light/src/hicn/core/msgbuf_pool.c index a2092aaf6..892bd59a1 100644 --- a/hicn-light/src/hicn/core/msgbuf_pool.c +++ b/hicn-light/src/hicn/core/msgbuf_pool.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -19,6 +19,7 @@ */ #include <hicn/util/pool.h> +#include <hicn/util/log.h> #include "msgbuf_pool.h" msgbuf_pool_t *_msgbuf_pool_create(size_t init_size, size_t max_size) { @@ -90,16 +91,20 @@ void msgbuf_pool_release(msgbuf_pool_t *msgbuf_pool, msgbuf_t **msgbuf_ptr) { if (msgbuf->refs == 0) { WITH_TRACE({ off_t msgbuf_id = msgbuf_pool_get_id(msgbuf_pool, msgbuf); - if (msgbuf->type != MSGBUF_TYPE_INTEREST && - msgbuf->type != MSGBUF_TYPE_DATA) { + if (msgbuf_get_type(msgbuf) != HICN_PACKET_TYPE_INTEREST && + msgbuf_get_type(msgbuf) != HICN_PACKET_TYPE_DATA) { TRACE("Msgbuf %d (%p) - put to msgbuf pool", msgbuf_id, msgbuf); } else { - char *name_str = name_ToString(msgbuf_get_name(msgbuf)); + char buf[MAXSZ_HICN_NAME]; + int rc = + hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf)); + if (rc < 0 || rc >= MAXSZ_HICN_NAME) + snprintf(buf, MAXSZ_HICN_NAME, "%s", "(error)"); const char *msgbuf_type_str = - msgbuf->type == MSGBUF_TYPE_INTEREST ? "interest" : "data"; + msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST ? "interest" + : "data"; TRACE("Msgbuf %d (%p) - %s (%s) put to msgbuf pool", msgbuf_id, msgbuf, - name_str, msgbuf_type_str); - free(name_str); + buf, msgbuf_type_str); } }) diff --git a/hicn-light/src/hicn/core/name.c b/hicn-light/src/hicn/core/name.c deleted file mode 100644 index d30cebefc..000000000 --- a/hicn-light/src/hicn/core/name.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <assert.h> -#include <limits.h> -#include <hicn/hicn-light/config.h> -#include <stdbool.h> -#include <stdio.h> -#include <string.h> - -#include <hicn/core/messageHandler.h> -#include <hicn/core/name.h> -#include <hicn/util/log.h> -#include <hicn/util/hash.h> - -#define IPv6_TYPE 6 -#define IPv4_TYPE 4 - -static uint32_t _computeHash(Name *name) { - assert(name); - - uint32_t hash1 = nameBitvector_GetHash32(&(name->content_name)); - return hashlittle(&name->segment, sizeof(name->segment), hash1); -} - -// ============================================================================ - -void name_create_from_interest(const uint8_t *packet, Name *name) { - assert(packet); - assert(name); - - if (messageHandler_GetIPPacketType(packet) == IPv6_TYPE) { - nameBitvector_CreateFromIn6Addr( - &(name->content_name), - (struct in6_addr *)messageHandler_GetDestination(packet), 128); - } else if (messageHandler_GetIPPacketType(packet) == IPv4_TYPE) { - nameBitvector_CreateFromInAddr( - &(name->content_name), - *((uint32_t *)messageHandler_GetDestination(packet)), 32); - } else { - ERROR("Error: unknown message type\n"); - return; - } - - name->segment = messageHandler_GetSegment(packet); - name->name_hash = _computeHash(name); -} - -void name_create_from_data(const uint8_t *packet, Name *name) { - assert(packet); - assert(name); - - if (messageHandler_GetIPPacketType(packet) == IPv6_TYPE) { - nameBitvector_CreateFromIn6Addr( - &(name->content_name), - (struct in6_addr *)messageHandler_GetSource(packet), 128); - } else if (messageHandler_GetIPPacketType(packet) == IPv4_TYPE) { - nameBitvector_CreateFromInAddr( - &(name->content_name), *((uint32_t *)messageHandler_GetSource(packet)), - 32); - } else { - printf("Error: unknown message type\n"); - return; - } - - name->segment = messageHandler_GetSegment(packet); - name->name_hash = _computeHash(name); -} - -void name_CreateFromAddress(Name *name, int family, ip_address_t addr, - uint8_t len) { - assert(name); - - switch (family) { - case AF_INET: - nameBitvector_CreateFromInAddr(&(name->content_name), addr.v4.as_u32, - len); - break; - case AF_INET6: - nameBitvector_CreateFromIn6Addr(&(name->content_name), - &addr.v6.as_in6addr, len); - break; - default: - return; - } - - name->segment = 0; - name->name_hash = _computeHash(name); -} - -void name_Copy(const Name *original, Name *copy) { - assert(original); - assert(copy); - - nameBitvector_Copy(&(original->content_name), &(copy->content_name)); - copy->segment = original->segment; - copy->name_hash = original->name_hash; -} - -uint32_t name_HashCode(const Name *name) { - assert(name); - return name->name_hash; -} - -NameBitvector *name_GetContentName(const Name *name) { - assert(name); - return (NameBitvector *)&(name->content_name); -} - -uint32_t name_GetSegment(const Name *name) { - assert(name); - return name->segment; -} - -void name_SetSegment(Name *name, uint32_t segment) { name->segment = segment; } - -bool name_Equals(const Name *a, const Name *b) { - assert(a); - assert(b); - - if ((nameBitvector_Equals(&(a->content_name), &(b->content_name)) && - a->segment == b->segment)) - return true; - return false; -} - -int name_Compare(const Name *a, const Name *b) { - assert(a); - assert(b); - - if (a == NULL && b == NULL) { - return 0; - } - if (a == NULL) { - return -1; - } - if (b == NULL) { - return +1; - } - - int res = nameBitvector_Compare(&(a->content_name), &(b->content_name)); - - if (res != 0) { - return res; - } else { - if (a->segment < b->segment) { - return -1; - } else if (a->segment > b->segment) { - return +1; - } else { - return 0; - } - } -} - -char *name_ToString(const Name *name) { - char *output = malloc(NI_MAXHOST * 2); - address_t address; - nameBitvector_ToAddress(name_GetContentName(name), &address); - - char addr_str[NI_MAXHOST]; - int err = address_to_string(&address, addr_str, NULL); - _ASSERT(!err); - - int chars_written = - snprintf(output, NI_MAXHOST * 2, "name=%s|%u", addr_str, name->segment); - _ASSERT(chars_written > 0); - - return output; -} - -void name_setLen(Name *name, uint8_t len) { - nameBitvector_setLen(&(name->content_name), len); - name->name_hash = _computeHash(name); -} - -#ifdef WITH_POLICY -uint32_t name_GetSuffix(const Name *name) { return name->segment; } - -uint8_t name_GetLen(const Name *name) { - return nameBitvector_GetLength(&(name->content_name)); -} -#endif /* WITH_POLICY */ diff --git a/hicn-light/src/hicn/core/name.h b/hicn-light/src/hicn/core/name.h deleted file mode 100644 index 23505243b..000000000 --- a/hicn-light/src/hicn/core/name.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef name_h -#define name_h - -#include <stdbool.h> -#include <stdlib.h> - -#include "nameBitvector.h" - -typedef struct { - NameBitvector content_name; - uint32_t segment; - uint32_t name_hash; -} Name; - -#define EMPTY_NAME \ - (Name) { .content_name = EMPTY_NAME_BITVECTOR, .segment = 0, .name_hash = 0, } - -/** - * Creates a name from packet - * - */ -void name_create_from_interest(const uint8_t *packet, Name *name); -void name_create_from_data(const uint8_t *packet, Name *name); - -/** - * returns a copy of the name - */ -void name_Copy(const Name *original, Name *copy); - -/** - * A hash value for use in hash tables - * - */ -uint32_t name_HashCode(const Name *name); - -/** - * Returns the content name without the segment value - * - */ -NameBitvector *name_GetContentName(const Name *name); - -/** - * Returns the segment value - * - */ -uint32_t name_GetSegment(const Name *name); - -/** - * Set the sequence number of the name provided - * - */ -void name_SetSegment(Name *name, uint32_t segment); - -/** - * Determine if two HicnName instances are equal. - */ -bool name_Equals(const Name *a, const Name *b); - -/** - * Compares two names and returns their ordering - * - */ -int name_Compare(const Name *a, const Name *b); - -/** - * return the name in string format (bitvector + segment number) - * - */ -char *name_ToString(const Name *name); - -/** - * @function message_setNameLen - * @abstract Sets a message name length - * @param [in] message - Interest message - * @param [in] len - Name length - */ -void name_setLen(Name *name, uint8_t len); - -/** - * Creates a name from a Address - * - */ -void name_CreateFromAddress(Name *name, int family, ip_address_t addr, - uint8_t len); - -#ifdef WITH_POLICY -uint32_t name_GetSuffix(const Name *name); -uint8_t name_GetLen(const Name *name); -#endif /* WITH_POLICY */ - -#endif // name_h diff --git a/hicn-light/src/hicn/core/nameBitvector.c b/hicn-light/src/hicn/core/nameBitvector.c deleted file mode 100644 index aa431879c..000000000 --- a/hicn-light/src/hicn/core/nameBitvector.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - -#include <hicn/core/messageHandler.h> -#include <hicn/core/nameBitvector.h> - -#include <hicn/util/hash.h> -#include <hicn/ctrl/hicn-light-ng.h> - -#define DEFAULT_PORT 1234 - -const uint64_t BV_SIZE = 64; -const uint64_t WIDTH = 128; -const uint64_t ONE = 0x1; - -// address b000:0000:0000:0001:c000:0000:0000:0001 is encodend as follow -// [bits[0] uint64_t ] [bits[1] unit64_t ] -// ^ ^ ^ ^ -// 63 0 127 64 -// [1000 0000 ... 0000 1011] [1000 0000 ... 0000 0011] //binary -// 1 b 1 c //hex - -void nameBitvector_CreateFromInAddr(NameBitvector *bitvector, uint32_t addr, - uint8_t len) { - assert(bitvector); - - bitvector->bits[0] = 0; - bitvector->bits[1] = 0; - - uint8_t addr_1 = (addr & 0xff000000) >> 24; - uint8_t addr_2 = (addr & 0x00ff0000) >> 16; - uint8_t addr_3 = (addr & 0x0000ff00) >> 8; - uint8_t addr_4 = (addr & 0x000000ff); - - bitvector->bits[0] = (bitvector->bits[0] | addr_4) << 8; - bitvector->bits[0] = (bitvector->bits[0] | addr_3) << 8; - bitvector->bits[0] = (bitvector->bits[0] | addr_2) << 8; - bitvector->bits[0] = (bitvector->bits[0] | addr_1); - bitvector->bits[0] = bitvector->bits[0] << 32; - - bitvector->len = len; - - bitvector->IPversion = IPv4_TYPE; -} - -void nameBitvector_CreateFromIn6Addr(NameBitvector *bitvector, - struct in6_addr *addr, uint8_t len) { - assert(addr); - assert(bitvector); - - bitvector->bits[0] = 0; - bitvector->bits[1] = 0; - - for (int i = 0; i < 8; ++i) { - bitvector->bits[0] = (bitvector->bits[0] << 8) | addr->s6_addr[i]; - } - - for (int i = 8; i < 16; ++i) { - bitvector->bits[1] = (bitvector->bits[1] << 8) | addr->s6_addr[i]; - } - - bitvector->len = len; - - bitvector->IPversion = IPv6_TYPE; -} - -void nameBitvector_Copy(const NameBitvector *original, NameBitvector *copy) { - assert(original); - assert(copy); - - copy->bits[0] = original->bits[0]; - copy->bits[1] = original->bits[1]; - copy->len = original->len; - copy->IPversion = original->IPversion; -} - -uint8_t nameBitvector_GetLength(const NameBitvector *name) { return name->len; } - -uint32_t nameBitvector_GetHash32(const NameBitvector *name) { - return hash(&name->bits, 16); -} - -bool nameBitvector_Equals(const NameBitvector *a, const NameBitvector *b) { - if (nameBitvector_Compare(a, b) == 0) return true; - return false; -} - -int nameBitvector_Compare(const NameBitvector *a, const NameBitvector *b) { - if (a == NULL && b == NULL) { - return 0; - } - if (a == NULL) { - return -1; - } - if (b == NULL) { - return +1; - } - - if (a->bits[0] < b->bits[0]) { - return -1; - } else if (a->bits[0] > b->bits[0]) { - return +1; - } else if (a->bits[1] < b->bits[1]) { - return -1; - } else if (a->bits[1] > b->bits[1]) { - return +1; - } else if (a->len < b->len) { - return -1; - } else if (a->len > b->len) { - return +1; - } else { - return 0; - } -} - -int nameBitvector_testBit(const NameBitvector *name, uint8_t pos, bool *bit) { - if (pos >= name->len || pos > (WIDTH - 1)) return -1; - - *bit = - (name->bits[pos / BV_SIZE] & (ONE << ((BV_SIZE - 1) - (pos % BV_SIZE)))); - - return 0; -} - -// TODO XXX use ffs(ll) -uint64_t _diff_bit_log2(uint64_t val) { - // base 2 log of an uint64_t. This is the same as get the position of - // the highest bit set (or most significant bit set, MSB) - uint64_t result = 0; - - if (val & 0xFFFFFFFF00000000) { - val = val >> 32; - result = result | 32; - } - if (val & 0xFFFF0000) { - val = val >> 16; - result = result | 16; - } - if (val & 0xFF00) { - val = val >> 8; - result = result | 8; - } - if (val & 0xF0) { - val = val >> 4; - result = result | 4; - } - if (val & 0xC) { - val = val >> 2; - result = result | 2; - } - if (val & 0x2) { - val = val >> 1; - result = result | 1; - } - return result; -} - -uint32_t nameBitvector_lpm(const NameBitvector *a, const NameBitvector *b) { - uint32_t limit; - uint32_t prefix_len; - if (a->len < b->len) - limit = a->len; - else - limit = b->len; - - uint64_t diff = a->bits[0] ^ b->bits[0]; - if (diff) { - prefix_len = (uint32_t)(BV_SIZE - (_diff_bit_log2(diff) + 1)); - // printf("if 1 diff = %lu plen = %d\n", diff, prefix_len); - } else { - prefix_len = BV_SIZE; - diff = a->bits[1] ^ b->bits[1]; - if (diff) { - prefix_len += (BV_SIZE - (_diff_bit_log2(diff) + 1)); - // printf("if 2 diff = %lu plen = %d\n", diff, prefix_len); - } else { - prefix_len += BV_SIZE; - } - } - - if (prefix_len < limit) return prefix_len; - return limit; -} - -void nameBitvector_clear(NameBitvector *a, uint8_t start_from) { - for (uint8_t pos = start_from; pos < WIDTH; pos++) - a->bits[pos / BV_SIZE] &= ~(ONE << ((BV_SIZE - 1) - (pos % BV_SIZE))); -} - -int nameBitvector_ToIPAddress(const NameBitvector *name, ip_prefix_t *prefix) { - if (name->IPversion == IPv4_TYPE) { - struct in_addr *addr = (struct in_addr *)(&prefix->address.v4.buffer); - prefix->family = AF_INET; - prefix->len = IPV4_ADDR_LEN_BITS; - - uint32_t tmp_addr = name->bits[0] >> 32ULL; - uint8_t addr_1 = (tmp_addr & 0xff000000) >> 24; - uint8_t addr_2 = (tmp_addr & 0x00ff0000) >> 16; - uint8_t addr_3 = (tmp_addr & 0x0000ff00) >> 8; - uint8_t addr_4 = (tmp_addr & 0x000000ff); - - addr->s_addr = 0; - addr->s_addr = (addr->s_addr | addr_4) << 8; - addr->s_addr = (addr->s_addr | addr_3) << 8; - addr->s_addr = (addr->s_addr | addr_2) << 8; - addr->s_addr = (addr->s_addr | addr_1); - - } else { - struct in6_addr *addr = (struct in6_addr *)(&prefix->address.v6.buffer); - prefix->family = AF_INET6; - prefix->len = name->len; // IPV6_ADDR_LEN_BITS; - - for (int i = 0; i < 8; i++) { - addr->s6_addr[i] = (uint8_t)((name->bits[0] >> 8 * (7 - i)) & 0xFF); - } - - int x = 0; - for (int i = 8; i < 16; ++i) { - addr->s6_addr[i] = (uint8_t)((name->bits[1] >> 8 * (7 - x)) & 0xFF); - x++; - } - } - return true; -} - -void nameBitvector_setLen(NameBitvector *name, uint8_t len) { name->len = len; } - -void nameBitvector_ToAddress(const NameBitvector *name, address_t *address) { - if (name->IPversion == IPv4_TYPE) { - struct sockaddr_in *sin = address4(address); - sin->sin_family = AF_INET; - sin->sin_port = htons(DEFAULT_PORT); - - uint32_t tmp_addr = name->bits[0] >> 32ULL; - uint8_t addr_1 = (tmp_addr & 0xff000000) >> 24; - uint8_t addr_2 = (tmp_addr & 0x00ff0000) >> 16; - uint8_t addr_3 = (tmp_addr & 0x0000ff00) >> 8; - uint8_t addr_4 = (tmp_addr & 0x000000ff); - - sin->sin_addr.s_addr = 0; - sin->sin_addr.s_addr = (sin->sin_addr.s_addr | addr_4) << 8; - sin->sin_addr.s_addr = (sin->sin_addr.s_addr | addr_3) << 8; - sin->sin_addr.s_addr = (sin->sin_addr.s_addr | addr_2) << 8; - sin->sin_addr.s_addr = (sin->sin_addr.s_addr | addr_1); - } else { - struct sockaddr_in6 *sin6 = address6(address); - sin6->sin6_family = AF_INET6; - sin6->sin6_port = htons(DEFAULT_PORT); - sin6->sin6_scope_id = 0; - sin6->sin6_flowinfo = 0; - - for (int i = 0; i < 8; i++) { - sin6->sin6_addr.s6_addr[i] = - (uint8_t)((name->bits[0] >> 8 * (7 - i)) & 0xFF); - } - - int x = 0; - for (int i = 8; i < 16; ++i) { - sin6->sin6_addr.s6_addr[i] = - (uint8_t)((name->bits[1] >> 8 * (7 - x)) & 0xFF); - x++; - } - } -} - -char *nameBitvector_ToString(const NameBitvector *name) { - char *output = malloc(WIDTH); - - address_t address; - nameBitvector_ToAddress(name, &address); - - // XXX TODO -#if 0 - sprintf(output, "prefix: %s len: %u", addressToString(packetAddr), name->len); -#else - snprintf(output, WIDTH, "%s", "ENOIMPL"); -#endif - - return output; -} diff --git a/hicn-light/src/hicn/core/nameBitvector.h b/hicn-light/src/hicn/core/nameBitvector.h deleted file mode 100644 index 549b26679..000000000 --- a/hicn-light/src/hicn/core/nameBitvector.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef name_bitvector_h -#define name_bitvector_h - -#include <hicn/hicn.h> -#include <stdint.h> -#include <stdlib.h> - -#include "address.h" - -#define NAME_LEN 2 -typedef struct __attribute__((__packed__)) { - uint64_t bits[NAME_LEN]; - uint32_t len; - uint32_t IPversion; -} NameBitvector; -static_assert(sizeof(NameBitvector) == 24, - "Name prefix should be stored on 24 bytes"); - -#define EMPTY_NAME_BITVECTOR \ - (NameBitvector) { .bits[0] = 0, .bits[1] = 0, .len = 0, .IPversion = 0, } - -void nameBitvector_CreateFromInAddr(NameBitvector *bitvector, uint32_t addr, - uint8_t len); - -void nameBitvector_CreateFromIn6Addr(NameBitvector *bitvector, - struct in6_addr *addr, uint8_t len); - -void nameBitvector_Copy(const NameBitvector *original, NameBitvector *copy); - -uint8_t nameBitvector_GetLength(const NameBitvector *name); - -uint32_t nameBitvector_GetHash32(const NameBitvector *name); - -bool nameBitvector_Equals(const NameBitvector *a, const NameBitvector *b); - -int nameBitvector_Compare(const NameBitvector *a, const NameBitvector *b); - -int nameBitvector_testBit(const NameBitvector *name, uint8_t pos, bool *bit); - -uint32_t nameBitvector_lpm(const NameBitvector *a, const NameBitvector *b); - -void nameBitvector_clear(NameBitvector *a, uint8_t start_from); - -int nameBitvector_ToIPAddress(const NameBitvector *name, ip_prefix_t *prefix); -void nameBitvector_setLen(NameBitvector *name, uint8_t len); - -void nameBitvector_ToAddress(const NameBitvector *name, address_t *address); - -char *nameBitvector_ToString(const NameBitvector *name); - -#endif // name_bitvector_h diff --git a/hicn-light/src/hicn/core/nexthops.c b/hicn-light/src/hicn/core/nexthops.c index 190f09ab0..70089399d 100644 --- a/hicn-light/src/hicn/core/nexthops.c +++ b/hicn-light/src/hicn/core/nexthops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -18,6 +18,8 @@ * \brief Nexthops implementation */ +#include <hicn/util/hash.h> + #include "nexthops.h" int nexthops_disable(nexthops_t *nexthops, off_t offset) { @@ -34,7 +36,6 @@ void nexthops_reset(nexthops_t *nexthops) { off_t nexthops_add(nexthops_t *nexthops, nexthop_t nexthop) { off_t id; - unsigned i, n; nexthops_enumerate(nexthops, i, n, { if (n == nexthop) return i; }); @@ -45,7 +46,6 @@ off_t nexthops_add(nexthops_t *nexthops, nexthop_t nexthop) { } off_t nexthops_remove(nexthops_t *nexthops, nexthop_t nexthop) { - unsigned i, n; nexthops_enumerate(nexthops, i, n, { if (n == nexthop) { nexthops->num_elts--; @@ -59,7 +59,6 @@ off_t nexthops_remove(nexthops_t *nexthops, nexthop_t nexthop) { } bool nexthops_contains(nexthops_t *nexthops, unsigned nexthop) { - unsigned n; nexthops_foreach(nexthops, n, { if (n == nexthop) return true; }); @@ -67,7 +66,6 @@ bool nexthops_contains(nexthops_t *nexthops, unsigned nexthop) { } off_t nexthops_find(nexthops_t *nexthops, unsigned nexthop) { - unsigned i, n; nexthops_enumerate(nexthops, i, n, { if (n == nexthop) return i; }); @@ -75,7 +73,6 @@ off_t nexthops_find(nexthops_t *nexthops, unsigned nexthop) { } unsigned nexthops_get_one(nexthops_t *nexthops) { - unsigned n; nexthops_foreach(nexthops, n, { return n; }); return INVALID_NEXTHOP; } @@ -92,8 +89,6 @@ int nexthops_select(nexthops_t *nexthops, off_t i) { void nexthops_set_priority(nexthops_t *nexthops, nexthop_t nexthop, int priority) { - unsigned i; - nexthop_t nh; nexthops_enumerate(nexthops, i, nh, { if (nexthop == nh) nexthops_set_priority_by_id(nexthops, i, priority); }); @@ -112,8 +107,6 @@ void nexthops_reset_priority_by_id(nexthops_t *nexthops, off_t i) { } void nexthops_reset_priorities(nexthops_t *nexthops) { - unsigned i; - nexthop_t nh; nexthops_enumerate(nexthops, i, nh, { (void)nh; nexthops_reset_priority(nexthops, i); @@ -121,7 +114,6 @@ void nexthops_reset_priorities(nexthops_t *nexthops) { } bool nexthops_equal(nexthops_t *a, nexthops_t *b) { - unsigned n; if (nexthops_get_len(a) != nexthops_get_len(b)) return false; nexthops_foreach(a, n, { if (!nexthops_contains(b, n)) return false; @@ -139,4 +131,19 @@ void nexthops_copy(nexthops_t *src, nexthops_t *dst) { dst->cur_elts = src->cur_elts; } +/* Adapted from Jenkins hash (commutative) */ +uint32_t nexthops_get_hash(nexthops_t *nexthops) { + uint32_t hash = 0; + + nexthops_foreach(nexthops, nh, { + hash += nh; + hash += hash << 10; + hash ^= hash >> 6; + }); + hash += hash << 3; + hash ^= hash >> 11; + hash += hash << 15; + return hash; +} + #endif /* WITH_POLICY */ diff --git a/hicn-light/src/hicn/core/nexthops.h b/hicn-light/src/hicn/core/nexthops.h index 2a7fc0b32..ff83199a6 100644 --- a/hicn-light/src/hicn/core/nexthops.h +++ b/hicn-light/src/hicn/core/nexthops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -106,21 +106,24 @@ int nexthops_disable(nexthops_t *nexthops, off_t offset); void nexthops_reset(nexthops_t *nexthops); -#define nexthops_enumerate(NH, i, X, BODY) \ +#define nexthops_enumerate(NH, I, X, BODY) \ do { \ - for ((i) = 0; (i) < nexthops_get_len(NH); (i)++) { \ - if (nexthops_is_disabled((NH), (i))) continue; \ - X = (NH)->elts[(i)]; \ + nexthop_t X; \ + (void)X; \ + unsigned I; \ + (void)I; \ + for ((I) = 0; (I) < nexthops_get_len(NH); (I)++) { \ + if (nexthops_is_disabled((NH), (I))) continue; \ + X = (NH)->elts[(I)]; \ do { \ BODY \ } while (0); \ } \ } while (0) -#define nexthops_foreach(NH, X, BODY) \ - do { \ - unsigned _nexthops_var(i); \ - nexthops_enumerate((NH), _nexthops_var(i), (X), {BODY}); \ +#define nexthops_foreach(NH, X, BODY) \ + do { \ + nexthops_enumerate((NH), _nexthops_var(i), X, {BODY}); \ } while (0) off_t nexthops_add(nexthops_t *nexthops, nexthop_t nexthop); @@ -173,4 +176,6 @@ void nexthops_copy(nexthops_t *src, nexthops_t *dst); #endif /* WITH_POLICY */ +uint32_t nexthops_get_hash(nexthops_t *nexthops); + #endif /* HICNLIGHT_NEXTHOPS_H */ diff --git a/hicn-light/src/hicn/core/packet_cache.c b/hicn-light/src/hicn/core/packet_cache.c index 8bd188c8b..9d0b041c3 100644 --- a/hicn-light/src/hicn/core/packet_cache.c +++ b/hicn-light/src/hicn/core/packet_cache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -16,48 +16,121 @@ /** * \file packet_cache.c * \brief Implementation of hICN packet cache + * + * _get_suffixes : first level lookup to return the suffixes + * + * _remove_suffix : Remove suffix from the two level packet cache structure + * + * __add_suffix : Add a packet cache entry in the second level of the + * two-level data structure _add_suffix : Add a packet cache entry in the both + * the first and second level of the two-level data tructure (helper) + * + * __get_suffix : Lookup in the second level of the packet cache + * + * _get_suffix : Lookup in both the first and second levels of the packet cache + * + * ---- + * + * pkt_cache_save_suffixes_for_prefix : always done at packet reception to keep + * the latest suffixes + * + * pkt_cache_reset_suffixes_for_prefix + * + * ---- + * + * pkt_cache_allocate + * + * pkt_cache_add_to_index + * + * pkt_cache_remove_from_index + * + * pkt_cache_pit_remove_entry + * + * pkt_cache_cs_remove_entry + * + * pkt_cache_add_to_pit + * pkt_cache_add_to_cs + * + * _pkt_cache_add_to_pit + * used by pkt_cache_add_to_pit + * plt_cache_update_pit + * _pkt_cache_add_to_cs + * + * pkt_cache_pit_to_cs + * pkt_cache_cs_to_pit + * + * pkt_cache_update_pit : when an interest expired + * pkt_cache_update_cs + * + * pkt_cache_try_aggregate_in_pit + * + * + * */ #include "packet_cache.h" +const char *_pkt_cache_verdict_str[] = { +#define _(x) [PKT_CACHE_VERDICT_##x] = #x, + foreach_kh_verdict +#undef _ +}; + /****************************************************************************** * Low-level operations on the hash table ******************************************************************************/ +/** + * Free the two level packet cache structure (helper) + */ void _prefix_map_free(kh_pkt_cache_prefix_t *prefix_to_suffixes) { - const NameBitvector *key; + const hicn_name_prefix_t *key; kh_pkt_cache_suffix_t *value; kh_foreach(prefix_to_suffixes, key, value, { - free((NameBitvector *)key); + //(void)key; + free((hicn_name_prefix_t *)key); kh_destroy_pkt_cache_suffix(value); }); kh_destroy_pkt_cache_prefix(prefix_to_suffixes); } +/** + * Perform the first level lookup to return the suffixes (helper) + */ kh_pkt_cache_suffix_t *_get_suffixes(kh_pkt_cache_prefix_t *prefix_to_suffixes, - const NameBitvector *prefix) { + const hicn_name_prefix_t *prefix, + bool create) { khiter_t k = kh_get_pkt_cache_prefix(prefix_to_suffixes, prefix); - // Return suffixes found + /* Return suffixes if found... */ if (k != kh_end(prefix_to_suffixes)) { kh_pkt_cache_suffix_t *suffixes = kh_val(prefix_to_suffixes, k); return suffixes; } + if (!create) return NULL; + + /* ... otherwise populate the first level and return the newly added entry. + */ kh_pkt_cache_suffix_t *suffixes = kh_init_pkt_cache_suffix(); - NameBitvector *nb_copy = (NameBitvector *)malloc(sizeof(NameBitvector)); - *nb_copy = *prefix; + + hicn_name_prefix_t *prefix_copy = malloc(sizeof(hicn_name_prefix_t)); + *prefix_copy = *prefix; int rc; - k = kh_put_pkt_cache_prefix(prefix_to_suffixes, nb_copy, &rc); + k = kh_put_pkt_cache_prefix(prefix_to_suffixes, prefix_copy, &rc); assert(rc == KH_ADDED || rc == KH_RESET); kh_value(prefix_to_suffixes, k) = suffixes; return suffixes; } +/** + * Remove suffix from the two level packet cache structure (helper) + */ void _remove_suffix(kh_pkt_cache_prefix_t *prefixes, - const NameBitvector *prefix, uint32_t suffix) { - kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix); + const hicn_name_prefix_t *prefix, + const hicn_name_suffix_t suffix) { + kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix, false); assert(suffixes != NULL); khiter_t k = kh_get_pkt_cache_suffix(suffixes, suffix); @@ -67,60 +140,90 @@ void _remove_suffix(kh_pkt_cache_prefix_t *prefixes, // TODO(eloparco): Remove prefix if no associated suffixes? } -void __add_suffix(kh_pkt_cache_suffix_t *suffixes, uint32_t suffix, +/** + * Add a packet cache entry in the second level of the two-level data structure + * (helper) + */ +void __add_suffix(kh_pkt_cache_suffix_t *suffixes, hicn_name_suffix_t suffix, unsigned val) { + // INFO("suffix add suffixes=%p suffix=%d val=%d", suffixes, suffix, val); int rc; khiter_t k = kh_put_pkt_cache_suffix(suffixes, suffix, &rc); assert(rc == KH_ADDED || rc == KH_RESET); kh_value(suffixes, k) = val; } -void _add_suffix(kh_pkt_cache_prefix_t *prefixes, const NameBitvector *prefix, - uint32_t suffix, unsigned val) { - kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix); +/** + * Add a packet cache entry in the both the first and second level of the + * two-level data tructure (helper) + */ +void _add_suffix(kh_pkt_cache_prefix_t *prefixes, + const hicn_name_prefix_t *prefix, + const hicn_name_suffix_t suffix, unsigned val) { + kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix, true); assert(suffixes != NULL); __add_suffix(suffixes, suffix, val); } -unsigned __get_suffix(kh_pkt_cache_suffix_t *suffixes, uint32_t suffix, - int *rc) { - *rc = KH_FOUND; +/** + * Lookup in the second level of the packet cache (helper) + */ +unsigned __get_suffix(kh_pkt_cache_suffix_t *suffixes, + hicn_name_suffix_t suffix) { khiter_t k = kh_get_pkt_cache_suffix(suffixes, suffix); // Not Found if (k == kh_end(suffixes)) { - *rc = KH_NOT_FOUND; - return -1; + return HICN_INVALID_SUFFIX; } unsigned index = kh_val(suffixes, k); return index; } +unsigned _get_suffix(kh_pkt_cache_prefix_t *prefixes, + const hicn_name_prefix_t *prefix, + hicn_name_suffix_t suffix) { + /* create is false as this function is always called by lookup */ + kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix, false); + if (!suffixes) { + return HICN_INVALID_SUFFIX; + } + return __get_suffix(suffixes, suffix); +} + +/** + * Lookup in both the first and second levels of the packet cache (helper) + */ +unsigned _get_suffix_from_name(kh_pkt_cache_prefix_t *prefixes, + const hicn_name_t *name) { + const hicn_name_prefix_t *prefix = hicn_name_get_prefix(name); + const hicn_name_suffix_t suffix = hicn_name_get_suffix(name); + + return _get_suffix(prefixes, prefix, suffix); +} + void pkt_cache_save_suffixes_for_prefix(pkt_cache_t *pkt_cache, - const NameBitvector *prefix) { + const hicn_name_prefix_t *prefix) { // Cached prefix matches the current one - if (nameBitvector_Compare(&pkt_cache->cached_prefix, prefix) == 0) return; + if (hicn_name_prefix_equals(&pkt_cache->cached_prefix, prefix)) return; + + char buf[MAXSZ_HICN_PREFIX]; + hicn_name_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, &pkt_cache->cached_prefix); + hicn_name_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); // Update cached prefix information pkt_cache->cached_prefix = *prefix; pkt_cache->cached_suffixes = - _get_suffixes(pkt_cache->prefix_to_suffixes, prefix); + _get_suffixes(pkt_cache->prefix_to_suffixes, prefix, true); // XXX + // } void pkt_cache_reset_suffixes_for_prefix(pkt_cache_t *pkt_cache) { pkt_cache->cached_suffixes = NULL; } -unsigned _get_suffix(kh_pkt_cache_prefix_t *prefixes, - const NameBitvector *prefix, uint32_t suffix, int *rc) { - kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix); - assert(suffixes != NULL); - - return __get_suffix(suffixes, suffix, rc); -} - /****************************************************************************** * Public API ******************************************************************************/ @@ -136,7 +239,7 @@ pkt_cache_t *pkt_cache_create(size_t cs_size) { pkt_cache->prefix_to_suffixes = kh_init_pkt_cache_prefix(); pool_init(pkt_cache->entries, DEFAULT_PKT_CACHE_SIZE, 0); - pkt_cache->cached_prefix = EMPTY_NAME_BITVECTOR; + pkt_cache->cached_prefix = HICN_NAME_PREFIX_EMPTY; pkt_cache->cached_suffixes = NULL; return pkt_cache; @@ -157,50 +260,71 @@ void pkt_cache_free(pkt_cache_t *pkt_cache) { } kh_pkt_cache_suffix_t *pkt_cache_get_suffixes(const pkt_cache_t *pkt_cache, - const NameBitvector *prefix) { - return _get_suffixes(pkt_cache->prefix_to_suffixes, prefix); + const hicn_name_prefix_t *prefix, + bool create) { + return _get_suffixes(pkt_cache->prefix_to_suffixes, prefix, create); } -pkt_cache_entry_t *pkt_cache_allocate(pkt_cache_t *pkt_cache, - const Name *name) { +pkt_cache_entry_t *pkt_cache_allocate(pkt_cache_t *pkt_cache) { pkt_cache_entry_t *entry = NULL; pool_get(pkt_cache->entries, entry); - if (!entry) return NULL; + assert(entry); + return entry; +} +void pkt_cache_add_to_index(const pkt_cache_t *pkt_cache, + const pkt_cache_entry_t *entry) { off_t id = entry - pkt_cache->entries; + /* It is important that the name used for the index is the one in the packet + * cache entry, which is common for PIT and CS + */ + const hicn_name_t *name = &entry->name; + if (pkt_cache->cached_suffixes) { - __add_suffix(pkt_cache->cached_suffixes, name_GetSegment(name), + __add_suffix(pkt_cache->cached_suffixes, hicn_name_get_suffix(name), (unsigned int)id); } else { - _add_suffix(pkt_cache->prefix_to_suffixes, name_GetContentName(name), - name_GetSegment(name), (unsigned int)id); + _add_suffix(pkt_cache->prefix_to_suffixes, hicn_name_get_prefix(name), + hicn_name_get_suffix(name), (unsigned int)id); } +} - return entry; +/** + * Remove a name pointer to the packet cache index (helper) + */ +void pkt_cache_remove_from_index(const pkt_cache_t *pkt_cache, + const hicn_name_t *name) { + _remove_suffix(pkt_cache->prefix_to_suffixes, hicn_name_get_prefix(name), + hicn_name_get_suffix(name)); + +// TODO +#if 0 + khiter_t k = kh_get_pkt_cache_name(pkt_cache->index_by_name, name); + assert(k != kh_end(pkt_cache->index_by_name)); + kh_del(pkt_cache_name, pkt_cache->index_by_name, k); +#endif } pit_t *pkt_cache_get_pit(pkt_cache_t *pkt_cache) { return pkt_cache->pit; } cs_t *pkt_cache_get_cs(pkt_cache_t *pkt_cache) { return pkt_cache->cs; } -pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, const Name *name, +pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, + const hicn_name_t *name, msgbuf_pool_t *msgbuf_pool, pkt_cache_lookup_t *lookup_result, off_t *entry_id, bool is_serve_from_cs_enabled) { - int rc; - - unsigned index = -1; + unsigned index = HICN_INVALID_SUFFIX; if (pkt_cache->cached_suffixes) { index = - __get_suffix(pkt_cache->cached_suffixes, name_GetSegment(name), &rc); + __get_suffix(pkt_cache->cached_suffixes, hicn_name_get_suffix(name)); } else { - index = _get_suffix(pkt_cache->prefix_to_suffixes, - name_GetContentName(name), name_GetSegment(name), &rc); + index = _get_suffix_from_name(pkt_cache->prefix_to_suffixes, name); } - if (rc == KH_NOT_FOUND) { + if (index == HICN_INVALID_SUFFIX) { *lookup_result = PKT_CACHE_LU_NONE; return NULL; } @@ -237,9 +361,10 @@ void pkt_cache_cs_remove_entry(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, off_t msgbuf_id = entry->u.cs_entry.msgbuf_id; msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); - const Name *name = msgbuf_get_name(msgbuf); - _remove_suffix(pkt_cache->prefix_to_suffixes, name_GetContentName(name), - name_GetSegment(name)); + // XXX const hicn_name_t *name = msgbuf_get_name(msgbuf); + _remove_suffix(pkt_cache->prefix_to_suffixes, + hicn_name_get_prefix(&entry->name), + hicn_name_get_suffix(&entry->name)); // Do not update the LRU cache for evicted entries if (!is_evicted) cs_vft[pkt_cache->cs->type]->remove_entry(pkt_cache, entry); @@ -248,28 +373,34 @@ void pkt_cache_cs_remove_entry(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, pool_put(pkt_cache->entries, entry); WITH_DEBUG({ - char *name_str = name_ToString(msgbuf_get_name(msgbuf)); - DEBUG("Packet %s removed from CS", name_str); - free(name_str); + char buf[MAXSZ_HICN_NAME]; + int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, &entry->name); + if (rc < 0 || rc >= MAXSZ_HICN_NAME) + snprintf(buf, MAXSZ_HICN_NAME, "%s", "(error)"); + DEBUG("Packet %s removed from CS", buf); }) msgbuf_pool_release(msgbuf_pool, &msgbuf); } void pkt_cache_pit_remove_entry(pkt_cache_t *pkt_cache, - pkt_cache_entry_t *entry, const Name *name) { + pkt_cache_entry_t *entry) { assert(pkt_cache); assert(entry); assert(entry->entry_type == PKT_CACHE_PIT_TYPE); - _remove_suffix(pkt_cache->prefix_to_suffixes, name_GetContentName(name), - name_GetSegment(name)); + const hicn_name_t *name = &entry->name; + _remove_suffix(pkt_cache->prefix_to_suffixes, hicn_name_get_prefix(name), + hicn_name_get_suffix(name)); + pool_put(pkt_cache->entries, entry); WITH_DEBUG({ - char *name_str = name_ToString(name); - DEBUG("Packet %s removed from PIT", name_str); - free(name_str); + char buf[MAXSZ_HICN_NAME]; + int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, name); + if (rc < 0 || rc >= MAXSZ_HICN_NAME) + snprintf(buf, MAXSZ_HICN_NAME, "%s", "(error)"); + DEBUG("Packet %s removed from PIT", buf); }) } @@ -279,8 +410,9 @@ void _pkt_cache_add_to_cs(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, entry->u.cs_entry = (cs_entry_t){.msgbuf_id = msgbuf_id, .lru = {.prev = INVALID_ENTRY_ID, .next = INVALID_ENTRY_ID}}; - entry->create_ts = ticks_now(); - entry->expire_ts = ticks_now() + msgbuf_get_data_expiry_time(msgbuf); + Ticks now = ticks_now(); + entry->create_ts = now; + entry->expire_ts = now + msgbuf_get_data_expiry_time(msgbuf); entry->has_expire_ts = true; entry->entry_type = PKT_CACHE_CS_TYPE; @@ -299,18 +431,21 @@ void _pkt_cache_add_to_cs(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, msgbuf_pool_acquire(msgbuf); } -void pkt_cache_pit_to_cs(pkt_cache_t *pkt_cache, - pkt_cache_entry_t *interest_entry, - msgbuf_pool_t *msgbuf_pool, msgbuf_t *data_msgbuf, - off_t data_msgbuf_id, off_t entry_id) { +void pkt_cache_pit_to_cs(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, + msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf, + off_t msgbuf_id, off_t entry_id) { assert(pkt_cache); - assert(interest_entry); - assert(interest_entry->entry_type == PKT_CACHE_PIT_TYPE); + assert(entry); + assert(entry->entry_type == PKT_CACHE_PIT_TYPE); - _pkt_cache_add_to_cs(pkt_cache, interest_entry, msgbuf_pool, data_msgbuf, - data_msgbuf_id, entry_id); + _pkt_cache_add_to_cs(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id, + entry_id); } +/** + * entry : newly allocated cache entry + * msgbuf : used for name, ingress connection id and lifetime + */ void _pkt_cache_add_to_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, const msgbuf_t *msgbuf) { entry->u.pit_entry = (pit_entry_t){ @@ -366,11 +501,13 @@ void pkt_cache_update_cs(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool, pkt_cache_entry_t *pkt_cache_add_to_pit(pkt_cache_t *pkt_cache, const msgbuf_t *msgbuf, - const Name *name) { + const hicn_name_t *name) { assert(pkt_cache); - pkt_cache_entry_t *entry = pkt_cache_allocate(pkt_cache, name); + pkt_cache_entry_t *entry = pkt_cache_allocate(pkt_cache); + entry->name = *name; _pkt_cache_add_to_pit(pkt_cache, entry, msgbuf); + pkt_cache_add_to_index(pkt_cache, entry); return entry; } @@ -379,12 +516,13 @@ pkt_cache_entry_t *pkt_cache_add_to_cs(pkt_cache_t *pkt_cache, msgbuf_t *msgbuf, off_t msgbuf_id) { assert(pkt_cache); - pkt_cache_entry_t *entry = - pkt_cache_allocate(pkt_cache, msgbuf_get_name(msgbuf)); + pkt_cache_entry_t *entry = pkt_cache_allocate(pkt_cache); + const hicn_name_t *name = msgbuf_get_name(msgbuf); + entry->name = *name; off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry); _pkt_cache_add_to_cs(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id, entry_id); - + pkt_cache_add_to_index(pkt_cache, entry); return entry; } @@ -404,7 +542,8 @@ void pkt_cache_update_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, - const msgbuf_t *msgbuf, const Name *name) { + const msgbuf_t *msgbuf, + const hicn_name_t *name) { assert(pkt_cache); assert(entry); assert(entry->entry_type == PKT_CACHE_PIT_TYPE); @@ -422,15 +561,17 @@ bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache, if (is_aggregated) pit_entry_ingress_add(pit_entry, connection_id); WITH_DEBUG({ - char *name_str = name_ToString(name); + char buf[MAXSZ_HICN_NAME]; + int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf)); + if (rc < 0 || rc >= MAXSZ_HICN_NAME) + snprintf(buf, MAXSZ_HICN_NAME, "%s", "(error)"); if (is_aggregated) { - DEBUG("Interest %s already existing (expiry %lu): aggregate", name_str, + DEBUG("Interest %s already existing (expiry %lu): aggregate", buf, entry->expire_ts); } else { - DEBUG("Interest %s already existing (expiry %lu): retransmit", name_str, + DEBUG("Interest %s already existing (expiry %lu): retransmit", buf, entry->expire_ts); } - free(name_str); }) return is_aggregated; @@ -445,7 +586,7 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache, assert(msgbuf_id_is_valid(msgbuf_id)); msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); - assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA); + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA); *wrong_egress = false; off_t entry_id; @@ -487,7 +628,7 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache, entry_id); *verdict = PKT_CACHE_VERDICT_FORWARD_DATA; } else { - pkt_cache_pit_remove_entry(pkt_cache, entry, msgbuf_get_name(msgbuf)); + pkt_cache_pit_remove_entry(pkt_cache, entry); *verdict = PKT_CACHE_VERDICT_CLEAR_DATA; } @@ -503,7 +644,7 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache, entry_id); *verdict = PKT_CACHE_VERDICT_STORE_DATA; } else { - pkt_cache_pit_remove_entry(pkt_cache, entry, msgbuf_get_name(msgbuf)); + pkt_cache_pit_remove_entry(pkt_cache, entry); *verdict = PKT_CACHE_VERDICT_CLEAR_DATA; } return NULL; @@ -543,12 +684,13 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache, void pkt_cache_on_interest(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool, off_t msgbuf_id, pkt_cache_verdict_t *verdict, off_t *data_msgbuf_id, pkt_cache_entry_t **entry_ptr, - const Name *name, bool is_serve_from_cs_enabled) { + const hicn_name_t *name, + bool is_serve_from_cs_enabled) { assert(pkt_cache); assert(msgbuf_id_is_valid(msgbuf_id)); msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); - assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST); + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST); off_t entry_id; pkt_cache_lookup_t lookup_result; @@ -628,7 +770,7 @@ void pkt_cache_cs_clear(pkt_cache_t *pkt_cache) { }); // Reset cached prefix - pkt_cache->cached_prefix = EMPTY_NAME_BITVECTOR; + pkt_cache->cached_prefix = HICN_NAME_PREFIX_EMPTY; pkt_cache->cached_suffixes = NULL; // Re-create CS diff --git a/hicn-light/src/hicn/core/packet_cache.h b/hicn-light/src/hicn/core/packet_cache.h index 47926fcdc..dcbc20c7d 100644 --- a/hicn-light/src/hicn/core/packet_cache.h +++ b/hicn-light/src/hicn/core/packet_cache.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -69,6 +69,10 @@ typedef enum { #undef _ } pkt_cache_verdict_t; +extern const char *_pkt_cache_verdict_str[]; + +#define pkt_cache_verdict_str(x) _pkt_cache_verdict_str[x] + #define foreach_kh_lookup \ _(INTEREST_NOT_EXPIRED) \ _(INTEREST_EXPIRED) \ @@ -83,10 +87,12 @@ typedef enum { } pkt_cache_lookup_t; KHASH_MAP_INIT_INT(pkt_cache_suffix, unsigned); -KHASH_INIT(pkt_cache_prefix, const NameBitvector *, kh_pkt_cache_suffix_t *, 1, - nameBitvector_GetHash32, nameBitvector_Equals); +KHASH_INIT(pkt_cache_prefix, const hicn_name_prefix_t *, + kh_pkt_cache_suffix_t *, 1, hicn_name_prefix_get_hash, + hicn_name_prefix_equals); typedef struct { + hicn_name_t name; pkt_cache_entry_type_t entry_type; Ticks create_ts; @@ -109,7 +115,7 @@ typedef struct { // Cached prefix info to avoid double lookups, // used for both single interest speculation and interest manifest - NameBitvector cached_prefix; + hicn_name_prefix_t cached_prefix; kh_pkt_cache_suffix_t *cached_suffixes; } pkt_cache_t; @@ -123,12 +129,29 @@ pkt_cache_t *pkt_cache_create(size_t cs_size); /** * @brief Add an entry with the specified name to the packet cache. * - * @param[in] pkt_cache Pointer to the msgbuf pool data structure to use. + * @param[in] pkt_cache Pointer to the pool data structure to use. * @param[in, out] entry Empty entry that will be used to return the * allocated one from the msgbuf pool. - * * @param[in] name Name to use + * @param[in] name hicn_name_t to use + * + * NOTE: unlike other pools, PIT and CS entries allocation does not update the + * index as the key is a hicn_name_t * which should point to : + * - the name inside the PIT entry (which is thus not set during allocation), + * - the name inside the msgbuf_t in the CS entry, which is always available + * during the lifetime of the cache entry. + * + * The index is therefore updated in pkt_cache_add_to_pit and + * pkt_cache_add_to_cs functions. + * + * */ -pkt_cache_entry_t *pkt_cache_allocate(pkt_cache_t *pkt_cache, const Name *name); +pkt_cache_entry_t *pkt_cache_allocate(pkt_cache_t *pkt_cache); + +void pkt_cache_add_to_index(const pkt_cache_t *pkt_cache, + const pkt_cache_entry_t *entry); + +void pkt_cache_remove_from_index(const pkt_cache_t *pkt_cache, + const hicn_name_t *name); /** * @brief Free a packet cache data structure. @@ -150,8 +173,8 @@ pit_t *pkt_cache_get_pit(pkt_cache_t *pkt_cache); * @brief Get a reference to the CS data structure contained in the packet * cache. * - * @param[in] pkt_cache Pointer to the packet cache data structure to get the CS - * from. + * @param[in] pkt_cache Pointer to the packet cache data structure to get the + * CS from. */ cs_t *pkt_cache_get_cs(pkt_cache_t *pkt_cache); @@ -170,13 +193,13 @@ size_t pkt_cache_get_size(pkt_cache_t *pkt_cache); size_t pkt_cache_get_num_cs_stale_entries(pkt_cache_t *pkt_cache); /** - * @brief Change the maximum capacity of the content store (LRU eviction will be - * used after reaching the provided size) + * @brief Change the maximum capacity of the content store (LRU eviction will + * be used after reaching the provided size) * * @param[in] pkt_cache Pointer to the packet cache data structure to use * @param[in] size Maximum size of the content store - * @return int 0 if success, -1 if the provided maximum size is smaller than the - * number of elements currently stored in the CS + * @return int 0 if success, -1 if the provided maximum size is smaller than + * the number of elements currently stored in the CS */ int pkt_cache_set_cs_size(pkt_cache_t *pkt_cache, size_t size); @@ -203,8 +226,8 @@ size_t pkt_cache_get_pit_size(pkt_cache_t *pkt_cache); #define pkt_cache_at(pkt_cache, i) (pkt_cache->entries + i) /** - * @brief Retrieve from the packet cache the entry associated with the specified - * name. + * @brief Retrieve from the packet cache the entry associated with the + * specified name. * * @param[in] pkt_cache Pointer to the packet cache data structure to retrieve * the entry from @@ -217,7 +240,8 @@ size_t pkt_cache_get_pit_size(pkt_cache_t *pkt_cache); * allowed to serve contents from the CS * @return pkt_cache_entry_t* Entry retrieved, NULL if none found */ -pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, const Name *name, +pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, + const hicn_name_t *name, msgbuf_pool_t *msgbuf_pool, pkt_cache_lookup_t *lookup_result, off_t *entry_id, @@ -260,11 +284,10 @@ void pkt_cache_cs_remove_entry(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, * @brief Remove a PIT entry from the packet cache. * * @param[in] pkt_cache Pointer to the packet cache data structure to use - * @param[in] entry Pointer to the PITe entry to remove - * @param[in] name Name associated with the PIT entry to remove + * @param[in] entry Pointer to the PIT entry to remove */ void pkt_cache_pit_remove_entry(pkt_cache_t *pkt_cache, - pkt_cache_entry_t *entry, const Name *name); + pkt_cache_entry_t *entry); /** * @brief Convert a PIT entry to a CS entry. @@ -311,7 +334,7 @@ void pkt_cache_cs_to_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, */ pkt_cache_entry_t *pkt_cache_add_to_pit(pkt_cache_t *pkt_cache, const msgbuf_t *msgbuf, - const Name *name); + const hicn_name_t *name); /** * @brief Add CS entry to the packet cache. @@ -329,7 +352,8 @@ pkt_cache_entry_t *pkt_cache_add_to_cs(pkt_cache_t *pkt_cache, msgbuf_t *msgbuf, off_t msgbuf_id); /** - * @brief Update PIT entry in the packet cache in case of an expired PIT entry. + * @brief Update PIT entry in the packet cache in case of an expired PIT + * entry. * * @param[in] pkt_cache Pointer to the packet cache data structure to use * @param[in, out] entry Pointer to the PIT entry to update @@ -371,7 +395,8 @@ void pkt_cache_update_cs(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool, */ bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, - const msgbuf_t *msgbuf, const Name *name); + const msgbuf_t *msgbuf, + const hicn_name_t *name); /** * @brief Cache prefix info (prefix + associated suffixes) to speed up lookups. @@ -380,7 +405,7 @@ bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache, * @param[in] prefix Name prefix to cache */ void pkt_cache_save_suffixes_for_prefix(pkt_cache_t *pkt_cache, - const NameBitvector *prefix); + const hicn_name_prefix_t *prefix); /** * @brief Reset cached prefix info to force double lookups. @@ -393,7 +418,8 @@ void pkt_cache_reset_suffixes_for_prefix(pkt_cache_t *pkt_cache); /** * @brief Handle data packet reception. - * @details Perform packet cache lookup and execute operations based on it. If: + * @details Perform packet cache lookup and execute operations based on it. + * If: * - INTEREST not expired: Convert PIT entry to CS entry; return the * nexthops (that can be used to forward the data * packet now stored in the CS) @@ -409,7 +435,8 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache, /** * @brief Handle interest packet reception. - * @details Perform packet cache lookup and execute operations based on it. If: + * @details Perform packet cache lookup and execute operations based on it. + * If: * - No match: Do nothing * - DATA not expired: get data message from CS * - INTEREST not expired: Aggregate or retransmit the interest received; @@ -419,23 +446,28 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache, void pkt_cache_on_interest(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool, off_t msgbuf_id, pkt_cache_verdict_t *verdict, off_t *data_msgbuf_id, pkt_cache_entry_t **entry_ptr, - const Name *name, bool is_serve_from_cs_enabled); + const hicn_name_t *name, + bool is_serve_from_cs_enabled); /********* Low-level operations on the hash table *********/ #ifdef WITH_TESTS -unsigned __get_suffix(kh_pkt_cache_suffix_t *suffixes, uint32_t suffix, - int *rc); +unsigned __get_suffix(kh_pkt_cache_suffix_t *suffixes, + hicn_name_suffix_t suffix); unsigned _get_suffix(kh_pkt_cache_prefix_t *prefixes, - const NameBitvector *prefix, uint32_t suffix, int *rc); -void __add_suffix(kh_pkt_cache_suffix_t *suffixes, uint32_t suffix, + const hicn_name_prefix_t *prefix, + hicn_name_suffix_t suffix); +void __add_suffix(kh_pkt_cache_suffix_t *suffixes, hicn_name_suffix_t suffix, unsigned val); -void _add_suffix(kh_pkt_cache_prefix_t *prefixes, const NameBitvector *prefix, - uint32_t suffix, unsigned val); +void _add_suffix(kh_pkt_cache_prefix_t *prefixes, + const hicn_name_prefix_t *prefix, hicn_name_suffix_t suffix, + unsigned val); void _remove_suffix(kh_pkt_cache_prefix_t *prefixes, - const NameBitvector *prefix, uint32_t suffix); + const hicn_name_prefix_t *prefix, + hicn_name_suffix_t suffix); void _prefix_map_free(kh_pkt_cache_prefix_t *prefix_to_suffixes); kh_pkt_cache_suffix_t *_get_suffixes(kh_pkt_cache_prefix_t *prefix_to_suffixes, - const NameBitvector *prefix); + const hicn_name_prefix_t *prefix, + bool create); #endif /************** Content Store *****************************/ diff --git a/hicn-light/src/hicn/core/policy_stats.c b/hicn-light/src/hicn/core/policy_stats.c index 1acbccf69..470e74a24 100644 --- a/hicn-light/src/hicn/core/policy_stats.c +++ b/hicn-light/src/hicn/core/policy_stats.c @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifdef WITH_POLICY_STATS // This has to be included first because of _GNU_SOURCE @@ -24,7 +39,6 @@ static int policy_stats_mgr_tick(void* mgr_arg, int fd, void* data) { /* Loop over FIB entries to compute statistics from counters */ const fib_t* fib = forwarder_get_fib(mgr->forwarder); - fib_entry_t* entry; fib_foreach_entry(fib, entry, { policy_stats_update(&entry->policy_stats, &entry->policy_counters, now); @@ -59,7 +73,6 @@ void policy_stats_on_retransmission(const policy_stats_mgr_t* mgr, policy_counters_t* counters, const nexthops_t* nexthops) { connection_table_t* table = forwarder_get_connection_table(mgr->forwarder); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { #ifdef WITH_POLICY const connection_t* conn = connection_table_at(table, nexthop); @@ -97,7 +110,6 @@ void policy_stats_on_data(const policy_stats_mgr_t* mgr, policy_stats_t* stats, size_t msg_size = msgbuf_get_len(msgbuf); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { #ifdef WITH_POLICY const connection_t* conn = connection_table_at(table, nexthop); @@ -121,7 +133,6 @@ void policy_stats_on_timeout(const policy_stats_mgr_t* mgr, #ifdef WITH_POLICY connection_table_t* table = forwarder_get_connection_table(mgr->forwarder); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { const connection_t* conn = connection_table_at(table, nexthop); if (!conn) continue; diff --git a/hicn-light/src/hicn/core/strategy_vft.h b/hicn-light/src/hicn/core/strategy_vft.h index 0256cba57..55e61db17 100644 --- a/hicn-light/src/hicn/core/strategy_vft.h +++ b/hicn-light/src/hicn/core/strategy_vft.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -24,13 +24,11 @@ #include "../strategies/best_path.h" #include "../strategies/load_balancer.h" -#include "../strategies/low_latency.h" #include "../strategies/random.h" #include "../strategies/replication.h" typedef union { strategy_load_balancer_options_t load_balancer; - strategy_low_latency_options_t low_latency; strategy_random_options_t random; strategy_replication_options_t replication; strategy_bestpath_options_t bestpath; @@ -42,7 +40,6 @@ typedef struct { #endif /* WITH_POLICY */ union { strategy_load_balancer_nexthop_state_t load_balancer; - strategy_low_latency_nexthop_state_t low_latency; strategy_random_nexthop_state_t random; strategy_replication_nexthop_state_t replication; strategy_bestpath_nexthop_state_t bestpath; @@ -58,7 +55,6 @@ typedef struct { typedef union { strategy_load_balancer_state_t load_balancer; - strategy_low_latency_state_t low_latency; strategy_random_state_t random; strategy_replication_state_t replication; strategy_bestpath_state_t bestpath; diff --git a/hicn-light/src/hicn/core/subscription.c b/hicn-light/src/hicn/core/subscription.c index ad4006531..fb954a245 100644 --- a/hicn-light/src/hicn/core/subscription.c +++ b/hicn-light/src/hicn/core/subscription.c @@ -17,12 +17,6 @@ bool topics_contains(hc_topics_t topic_list, hc_topic_t topic) { #define topic_is_set(topic_list, topic_index) \ ((topic_list) & (1 << (topic_index))) -const char *event_str[] = { -#define _(x) [EVENT_##x] = #x, - foreach_event_type -#undef _ -}; - /*----------------------------------------------------------------------------* * Subscriptions *----------------------------------------------------------------------------*/ @@ -56,13 +50,13 @@ int subscription_table_add_topics_for_connection( int ret = vector_push(subscriptions->table[topic_index], connection_id); if (ret < 0) { ERROR("Unable to perform subscription for connection %d, topic %s", - connection_id, object_str(topic_index)); + connection_id, object_type_str(topic_index)); return -1; } if (num_duplicates > 0) { DEBUG("Connection %d had already a subscription for topic %s", - connection_id, object_str(topic_index)); + connection_id, object_type_str(topic_index)); is_subscription_already_present = true; } } @@ -111,14 +105,14 @@ unsigned *subscription_table_get_connections_for_topic( } void subscription_table_print(subscription_table_t *subscriptions) { - for (int topic_index = OBJECT_UNDEFINED + 1; topic_index < NUM_TOPICS; + for (int topic_index = OBJECT_TYPE_UNDEFINED + 1; topic_index < NUM_TOPICS; topic_index++) { printf("topic %s (%lu subscription/s) from connection/s: [ ", - object_str(topic_index), + object_type_str(topic_index), (unsigned long)vector_len(subscriptions->table[topic_index])); unsigned *connection_id; vector_foreach(subscriptions->table[topic_index], connection_id, { printf("%d ", *connection_id); }); printf("]\n"); } -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/io/base.c b/hicn-light/src/hicn/io/base.c index cd7362956..38d36efbe 100644 --- a/hicn-light/src/hicn/io/base.c +++ b/hicn-light/src/hicn/io/base.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -42,7 +42,7 @@ ssize_t io_read_single_fd(int fd, msgbuf_t *msgbuf, address_t *address) { return -1; } - msgbuf->length = (unsigned int)n; + msgbuf_set_len(msgbuf, (size_t)n); *address = ADDRESS_ANY(AF_UNSPEC, 0); // XXX placeholder, see hicn.c } @@ -50,12 +50,18 @@ ssize_t io_read_single_fd(int fd, msgbuf_t *msgbuf, address_t *address) { } ssize_t io_read_single_socket(int fd, msgbuf_t *msgbuf, address_t *address) { - struct sockaddr_storage *sa = &address->as_ss; + struct sockaddr *sa = &(address->as_sa); socklen_t sa_len = sizeof(sa); uint8_t *packet = msgbuf_get_packet(msgbuf); ssize_t n = recvfrom(fd, packet, MTU, 0, (struct sockaddr *)sa, &sa_len); - msgbuf->length = (unsigned int)n; + msgbuf_set_len(msgbuf, (size_t)n); + +#ifdef __APPLE__ + // set __uint8_t sin_len to 0 + uint8_t *ptr = (uint8_t *)sa; + *ptr = 0x0; +#endif /* __APPLE__ */ return n; } @@ -92,6 +98,7 @@ ssize_t io_read_batch_socket(int fd, msgbuf_t **msgbuf, address_t **address, for (;;) { n = recvmmsg(fd, msghdr, batch_size, /* flags */ 0, /* timeout */ NULL); + // INFO("Got n=%d messages", n); if (n == 0) return 0; if (n < 0) { if (errno == EINTR) continue; // XXX was break; @@ -112,7 +119,7 @@ ssize_t io_read_batch_socket(int fd, msgbuf_t **msgbuf, address_t **address, */ for (int i = 0; i < n; i++) { struct mmsghdr *msg = &msghdr[i]; - msgbuf[i]->length = msg->msg_len; + msgbuf_set_len(msgbuf[i], msg->msg_len); memcpy(address[i], msg->msg_hdr.msg_name, msg->msg_hdr.msg_namelen); } diff --git a/hicn-light/src/hicn/io/hicn.c b/hicn-light/src/hicn/io/hicn.c index d019a49c1..c5859fbe3 100644 --- a/hicn-light/src/hicn/io/hicn.c +++ b/hicn-light/src/hicn/io/hicn.c @@ -433,8 +433,8 @@ static bool connection_hicn_send(connection_t *connection, msgbuf_t *msgbuf, // return 0; //} // -static int connection_hicn_send_packet(const connection_t *connection, - const uint8_t *packet, size_t size) { +static bool connection_hicn_send_packet(const connection_t *connection, + const uint8_t *packet, size_t size) { assert(connection); assert(packet); diff --git a/hicn-light/src/hicn/io/tcp.c b/hicn-light/src/hicn/io/tcp.c index 50591c3fc..a924b6330 100644 --- a/hicn-light/src/hicn/io/tcp.c +++ b/hicn-light/src/hicn/io/tcp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -37,7 +37,6 @@ #include "../core/listener_vft.h" #include "../core/msgbuf.h" #include "../core/forwarder.h" -#include "../core/messageHandler.h" // 128 KB output queue #define OUTPUT_QUEUE_BYTES (128 * 1024) @@ -336,8 +335,8 @@ static bool connection_tcp_send(connection_t *connection, msgbuf_t *msgbuf, return true; } -static int connection_tcp_send_packet(const connection_t *connection, - const uint8_t *packet, size_t size) { +static bool connection_tcp_send_packet(const connection_t *connection, + const uint8_t *packet, size_t size) { /* Not implemented for local connections */ // XXX shall we set the pointer to NULL and add a check ? diff --git a/hicn-light/src/hicn/io/udp.c b/hicn-light/src/hicn/io/udp.c index 149d53aea..b06ee7bce 100644 --- a/hicn-light/src/hicn/io/udp.c +++ b/hicn-light/src/hicn/io/udp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -58,7 +58,6 @@ #include "../core/forwarder.h" #include "../core/listener.h" #include "../core/listener_vft.h" -#include "../core/messageHandler.h" #include "../core/msgbuf.h" //#include "../hicn-light/config.h" @@ -336,11 +335,12 @@ static int connection_udp_initialize(connection_t *connection) { static void connection_udp_finalize(connection_t *connection) { assert(connection); assert(connection->type == FACE_TYPE_UDP); - +#ifdef __linux__ connection_udp_data_t *data = connection->data; assert(data); ring_free(data->ring); +#endif /* __linux__ */ } static bool connection_udp_flush(connection_t *connection) { @@ -374,7 +374,7 @@ SEND: msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); // update path label - if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA) { + if (msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA) { msgbuf_update_pathlabel(msgbuf, connection_get_id(connection)); connection->stats.data.tx_pkts++; @@ -460,7 +460,7 @@ static bool connection_udp_send(connection_t *connection, msgbuf_t *msgbuf, #endif /* __linux__ */ /* Send one */ // update the path label befor send the packet - if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA) { + if (msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA) { msgbuf_update_pathlabel(msgbuf, connection_get_id(connection)); connection->stats.data.tx_pkts++; @@ -478,8 +478,9 @@ static bool connection_udp_send(connection_t *connection, msgbuf_t *msgbuf, return false; } else { // this print is for debugging - printf("Incorrect write length %zd, expected %u: (%d) %s\n", - writeLength, msgbuf_get_len(msgbuf), errno, strerror(errno)); + printf("Incorrect write length %zd, expected %lu: (%d) %s\n", + writeLength, (long unsigned int)msgbuf_get_len(msgbuf), errno, + strerror(errno)); return false; } } @@ -532,8 +533,8 @@ connection_udp_sendv(const connection_t * connection, struct iovec * iov, } #endif -static int connection_udp_send_packet(const connection_t *connection, - const uint8_t *packet, size_t size) { +static bool connection_udp_send_packet(const connection_t *connection, + const uint8_t *packet, size_t size) { assert(connection); assert(packet); @@ -555,16 +556,16 @@ static int connection_udp_send_packet(const connection_t *connection, ssize_t n = send(connection->fd, packet, size, 0); if (n < 0) { perror("sendto"); - return -1; + return false; } #else const address_t *remote = connection_get_remote(connection); ssize_t n = sendto(connection->fd, packet, size, 0, address_sa(remote), address_socklen(remote)); - if (n < 0) return -1; + if (n < 0) return false; #endif - return 0; + return true; } #define connection_udp_read_single \ diff --git a/hicn-light/src/hicn/socket/api.c b/hicn-light/src/hicn/socket/api.c index e39ebf4b5..db377aecd 100644 --- a/hicn-light/src/hicn/socket/api.c +++ b/hicn-light/src/hicn/socket/api.c @@ -43,7 +43,7 @@ static hicn_conf_t hicn_default_conf = { struct ip_rule_state_ { char tun_name[IF_NAMESIZE]; - ip_prefix_t prefix; + hicn_ip_prefix_t prefix; uint32_t table_id; uint8_t priority; uint8_t address_family; @@ -193,7 +193,7 @@ int hicn_socket_cmp(hicn_socket_t *a, hicn_socket_t *b) { return b->fd - a->fd; } -ip_prefix_t *hicn_socket_get_src_ip(hicn_socket_t *socket) { +hicn_ip_prefix_t *hicn_socket_get_src_ip(hicn_socket_t *socket) { if (socket->type != HS_CONNECTION) { return NULL; } @@ -241,7 +241,8 @@ int hicn_set_local_endpoint(hicn_socket_t *socket, const char *local_ip_address, */ /* Copy the local IP address inside the connection */ - rc = ip_prefix_pton(local_ip_address, &socket->connection.tun_ip_address); + rc = + hicn_ip_prefix_pton(local_ip_address, &socket->connection.tun_ip_address); if (rc < 0) { rc = HICN_SOCKET_ERROR_SOCKET_LOCAL_REPR; goto end; @@ -251,14 +252,14 @@ end: return rc; } -int hicn_get_local_address(const ip_prefix_t *remote_address, - ip_prefix_t *local_address) { +int hicn_get_local_address(const hicn_ip_prefix_t *remote_address, + hicn_ip_prefix_t *local_address) { int rc = 0; uint32_t interface_id; char remote_address_str[INET_MAX_ADDRSTRLEN + 4]; - rc = ip_prefix_ntop_short(remote_address, remote_address_str, - sizeof(remote_address_str)); + rc = hicn_ip_prefix_ntop_short(remote_address, remote_address_str, + sizeof(remote_address_str)); if (rc < 0) { rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR; goto ERR; @@ -289,7 +290,7 @@ ERR: int hicn_set_remote_endpoint(hicn_socket_t *socket, const char *remote_ip_address) { int af, rc = HICN_SOCKET_ERROR_NONE; - ip_prefix_t addr; + hicn_ip_prefix_t addr; af = get_addr_family(remote_ip_address); if ((af != AF_INET6) && (af != AF_INET)) { @@ -297,7 +298,7 @@ int hicn_set_remote_endpoint(hicn_socket_t *socket, } /* Bind local endpoint if not done yet */ - if (ip_prefix_empty(&socket->connection.tun_ip_address)) { + if (hicn_ip_prefix_empty(&socket->connection.tun_ip_address)) { char local_ip_address[INET_MAX_ADDRSTRLEN + 4]; /* Local interface id */ @@ -327,8 +328,8 @@ int hicn_set_remote_endpoint(hicn_socket_t *socket, ///// /* Convert to representation format */ - rc = - ip_prefix_ntop_short(&addr, local_ip_address, sizeof(local_ip_address)); + rc = hicn_ip_prefix_ntop_short(&addr, local_ip_address, + sizeof(local_ip_address)); if (rc < 0) { rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR; goto ERR; @@ -445,8 +446,8 @@ int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) { return rc; } - ip_prefix_t ip_prefix; - rc = ip_prefix_pton(prefix, &ip_prefix); + hicn_ip_prefix_t hicn_ip_prefix; + rc = hicn_ip_prefix_pton(prefix, &hicn_ip_prefix); if (rc < 0) { return rc; } @@ -457,7 +458,7 @@ int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) { if (punting_table_id == -1) punting_table_id = socket->connection.table_id; - rc = ops.add_prio_rule(&ip_prefix, ip_prefix.family, 0, + rc = ops.add_prio_rule(&hicn_ip_prefix, hicn_ip_prefix.family, 0, socket->connection.table_id); if (rc < 0) { return rc; @@ -467,8 +468,8 @@ int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) { sizeof(rules_to_remove[rules_counter].tun_name), "NONE"); if (rc != EOK) return -1; - rules_to_remove[rules_counter].prefix = ip_prefix; - rules_to_remove[rules_counter].address_family = ip_prefix.family; + rules_to_remove[rules_counter].prefix = hicn_ip_prefix; + rules_to_remove[rules_counter].address_family = hicn_ip_prefix.family; rules_to_remove[rules_counter].table_id = socket->connection.table_id; rules_to_remove[rules_counter].priority = 0; ++rules_counter; diff --git a/hicn-light/src/hicn/socket/api.h b/hicn-light/src/hicn/socket/api.h index a0356e035..3caf9ef1e 100644 --- a/hicn-light/src/hicn/socket/api.h +++ b/hicn-light/src/hicn/socket/api.h @@ -83,7 +83,7 @@ typedef struct hicn_socket_s { union { struct { - ip_prefix_t tun_ip_address; + hicn_ip_prefix_t tun_ip_address; uint32_t interface_id; /* ID of the corresponding table : avoid default values of 0, 32766 and @@ -162,8 +162,8 @@ void hicn_free(hicn_socket_helper_t *hicn); * * @return 0 in case of success, -1 otherwise. */ -int hicn_get_local_address(const ip_prefix_t *remote_address, - ip_prefix_t *local_address); +int hicn_get_local_address(const hicn_ip_prefix_t *remote_address, + hicn_ip_prefix_t *local_address); /* hICN socket */ diff --git a/hicn-light/src/hicn/socket/ops.h b/hicn-light/src/hicn/socket/ops.h index 1bee7c6f6..854b0c461 100644 --- a/hicn-light/src/hicn/socket/ops.h +++ b/hicn-light/src/hicn/socket/ops.h @@ -17,10 +17,10 @@ typedef struct { int (*get_output_ifid)(const char *ip_address, uint8_t address_family, uint32_t *interface_id); int (*get_ip_addr)(uint32_t interface_id, uint8_t address_family, - ip_prefix_t *ip_address); - int (*set_ip_addr)(uint32_t interface_id, ip_prefix_t *ip_address); + hicn_ip_prefix_t *ip_address); + int (*set_ip_addr)(uint32_t interface_id, hicn_ip_prefix_t *ip_address); int (*up_if)(uint32_t interface_id); - int (*add_in_route_table)(const ip_prefix_t *prefix, + int (*add_in_route_table)(const hicn_ip_prefix_t *prefix, const uint32_t interface_id, const uint8_t table_id); int (*add_in_route_table_s)(const char *prefix, const uint32_t interface_id, @@ -30,23 +30,23 @@ typedef struct { const uint8_t table_id, int default_route); int (*del_out_route)(const char *gateway, const uint8_t address_family, const uint8_t table_id); - int (*del_lo_route)(const ip_prefix_t *ip_address); + int (*del_lo_route)(const hicn_ip_prefix_t *ip_address); int (*add_rule)(const char *interface_name, const uint8_t address_family, const uint8_t table_id); int (*del_rule)(const char *interface_name, const uint8_t address_family, const uint8_t table_id); - int (*add_neigh_proxy)(const ip_prefix_t *ip_address, + int (*add_neigh_proxy)(const hicn_ip_prefix_t *ip_address, const uint32_t interface_id); - int (*add_prio_rule)(const ip_prefix_t *ip_address, + int (*add_prio_rule)(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority, const uint8_t table_id); - int (*add_lo_prio_rule)(const ip_prefix_t *ip_address, + int (*add_lo_prio_rule)(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority); - int (*del_prio_rule)(const ip_prefix_t *ip_address, + int (*del_prio_rule)(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority, const uint8_t table_id); - int (*del_lo_prio_rule)(const ip_prefix_t *ip_address, + int (*del_lo_prio_rule)(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority); } hicn_socket_ops_t; diff --git a/hicn-light/src/hicn/socket/ops_linux.c b/hicn-light/src/hicn/socket/ops_linux.c index d741fd2e6..a3675e929 100644 --- a/hicn-light/src/hicn/socket/ops_linux.c +++ b/hicn-light/src/hicn/socket/ops_linux.c @@ -62,13 +62,13 @@ int _nl_get_output_ifid(const char *ip_address, uint8_t address_family, * @see getifaddrs */ int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family, - ip_prefix_t *ip_address); + hicn_ip_prefix_t *ip_address); -int _nl_set_ip_addr(uint32_t interface_id, ip_prefix_t *ip_address); +int _nl_set_ip_addr(uint32_t interface_id, hicn_ip_prefix_t *ip_address); int _nl_up_if(uint32_t interface_id); -int _nl_add_in_route_table(const ip_prefix_t *prefix, +int _nl_add_in_route_table(const hicn_ip_prefix_t *prefix, const uint32_t interface_id, const uint8_t table_id); int _nl_add_in_route_table_s(const char *prefix, const uint32_t interface_id, const uint8_t table_id); @@ -79,25 +79,25 @@ int _nl_add_out_route(const char *gateway, const uint8_t address_family, int _nl_del_out_route(const char *gateway, const uint8_t address_family, const uint8_t table_id); -int _nl_del_lo_route(const ip_prefix_t *ip_address); +int _nl_del_lo_route(const hicn_ip_prefix_t *ip_address); int _nl_add_rule(const char *interface_name, const uint8_t address_family, const uint8_t table_id); int _nl_del_rule(const char *interface_name, const uint8_t address_family, const uint8_t table_id); -int _nl_add_neigh_proxy(const ip_prefix_t *ip_address, +int _nl_add_neigh_proxy(const hicn_ip_prefix_t *ip_address, const uint32_t interface_id); -int _nl_add_prio_rule(const ip_prefix_t *ip_address, +int _nl_add_prio_rule(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority, const uint8_t table_id); -int _nl_add_lo_prio_rule(const ip_prefix_t *ip_address, +int _nl_add_lo_prio_rule(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority); -int _nl_del_prio_rule(const ip_prefix_t *ip_address, +int _nl_del_prio_rule(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority, const uint8_t table_id); -int _nl_del_lo_prio_rule(const ip_prefix_t *ip_address, +int _nl_del_lo_prio_rule(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority); #endif /* HICN_NETLINK_H */ @@ -533,7 +533,7 @@ ERR: } int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family, - ip_prefix_t *prefix) { + hicn_ip_prefix_t *prefix) { char buffer[BUFSIZE]; struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; size_t n; @@ -602,7 +602,7 @@ ERR_SOCKET: return HICN_SOCKET_ERROR_UNSPEC; } -int _nl_set_ip_addr(uint32_t interface_id, ip_prefix_t *prefix) { +int _nl_set_ip_addr(uint32_t interface_id, hicn_ip_prefix_t *prefix) { char buffer[BUFSIZE]; struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; size_t n; @@ -622,14 +622,15 @@ int _nl_set_ip_addr(uint32_t interface_id, ip_prefix_t *prefix) { .payload.ifa_index = interface_id}; /* Set attributes = length/type/value */ - struct rtattr ifa_address = {RTA_LENGTH(ip_address_len(prefix->family)), + struct rtattr ifa_address = {RTA_LENGTH(hicn_ip_address_len(prefix->family)), IFA_ADDRESS}; - const void *address = ip_address_get_buffer(&prefix->address, prefix->family); + const void *address = + hicn_ip_address_get_buffer(&prefix->address, prefix->family); if (!address) goto ERR_ADDRESS; const struct iovec iov[] = { {&msg, sizeof(msg)}, {&ifa_address, sizeof(ifa_address)}, - {(void *)address, ip_address_len(prefix->family)}, + {(void *)address, hicn_ip_address_len(prefix->family)}, }; msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); @@ -967,7 +968,7 @@ ERR_SOCKET: * ip route del 1:2::2 dev lo table local * */ -int _nl_del_lo_route(const ip_prefix_t *prefix) { +int _nl_del_lo_route(const hicn_ip_prefix_t *prefix) { char buffer[BUFSIZE]; struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; size_t n; @@ -993,17 +994,20 @@ int _nl_del_lo_route(const ip_prefix_t *prefix) { /* Set attribute = length/type/value */ uint32_t one = 1; - struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix->family)), RTA_DST}; + struct rtattr a_dst = {RTA_LENGTH(hicn_ip_address_len(prefix->family)), + RTA_DST}; struct rtattr a_ifid_lo = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF}; - const void *address = ip_address_get_buffer(&prefix->address, prefix->family); + const void *address = + hicn_ip_address_get_buffer(&prefix->address, prefix->family); if (!address) goto ERR; - const struct iovec iov[] = {{&msg, sizeof(msg)}, - /* Ip address */ - {&a_dst, sizeof(a_dst)}, - {(void *)address, ip_address_len(prefix->family)}, - /* Interface id */ - {&a_ifid_lo, sizeof(a_ifid_lo)}, - {&one, sizeof(one)}}; + const struct iovec iov[] = { + {&msg, sizeof(msg)}, + /* Ip address */ + {&a_dst, sizeof(a_dst)}, + {(void *)address, hicn_ip_address_len(prefix->family)}, + /* Interface id */ + {&a_ifid_lo, sizeof(a_ifid_lo)}, + {&one, sizeof(one)}}; msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); @@ -1131,7 +1135,7 @@ ERR_SOCKET: * ip -6 neigh add proxy 1:2::2 dev hicnc-cons-eth0 2>&1 | grep nei * */ -int _nl_add_neigh_proxy(const ip_prefix_t *prefix, +int _nl_add_neigh_proxy(const hicn_ip_prefix_t *prefix, const uint32_t interface_id) { /* Buffer for holding the response, with appropriate casting on the header */ char buffer[BUFSIZE]; @@ -1156,9 +1160,11 @@ int _nl_add_neigh_proxy(const ip_prefix_t *prefix, }; /* Message attributes = length/type/value */ - struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix->family)), NDA_DST}; + struct rtattr a_dst = {RTA_LENGTH(hicn_ip_address_len(prefix->family)), + NDA_DST}; - const void *address = ip_address_get_buffer(&prefix->address, prefix->family); + const void *address = + hicn_ip_address_get_buffer(&prefix->address, prefix->family); if (!address) goto ERR; /* Iovec describing the packets */ @@ -1166,7 +1172,7 @@ int _nl_add_neigh_proxy(const ip_prefix_t *prefix, {&msg, sizeof(msg)}, /* Ip address */ {&a_dst, sizeof(a_dst)}, - {(void *)address, ip_address_len(prefix->family)}, + {(void *)address, hicn_ip_address_len(prefix->family)}, }; msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); @@ -1204,7 +1210,7 @@ ERR: /* ip -6 route add 0:1::/64 dev hicn-if0 table 100 */ /* ip -6 route add 0:2::/64 dev hicn-if1 table 100 */ -int _nl_add_in_route_table(const ip_prefix_t *prefix, +int _nl_add_in_route_table(const hicn_ip_prefix_t *prefix, const uint32_t interface_id, const uint8_t table_id) { /* Buffer for holding the response, with appropriate casting on the header */ @@ -1236,10 +1242,12 @@ int _nl_add_in_route_table(const ip_prefix_t *prefix, }; /* Message attributes = length/type/value */ - struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix->family)), RTA_DST}; + struct rtattr a_dst = {RTA_LENGTH(hicn_ip_address_len(prefix->family)), + RTA_DST}; struct rtattr a_oif = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF}; - const void *address = ip_address_get_buffer(&prefix->address, prefix->family); + const void *address = + hicn_ip_address_get_buffer(&prefix->address, prefix->family); if (!address) goto ERR; /* Iovec describing the packets */ @@ -1247,7 +1255,7 @@ int _nl_add_in_route_table(const ip_prefix_t *prefix, {&msg, sizeof(msg)}, /* Destination prefix / ip address */ {&a_dst, sizeof(a_dst)}, - {(void *)address, ip_address_len(prefix->family)}, + {(void *)address, hicn_ip_address_len(prefix->family)}, /* Output interface */ {&a_oif, sizeof(a_oif)}, {(void *)&interface_id, sizeof(uint32_t)}, @@ -1291,9 +1299,9 @@ ERR: int _nl_add_in_route_table_s(const char *prefix, const uint32_t interface_id, const uint8_t table_id) { int rc; - ip_prefix_t ip_address; + hicn_ip_prefix_t ip_address; - rc = ip_prefix_pton(prefix, &ip_address); + rc = hicn_ip_prefix_pton(prefix, &ip_address); if (rc < 0) { return rc; } @@ -1306,7 +1314,7 @@ int _nl_add_in_route_s(const char *prefix, const uint32_t interface_id) { } /* ip -6 rule add from b001::/16 prio 0 table 100 */ -int _nl_add_prio_rule(const ip_prefix_t *prefix, uint8_t address_family, +int _nl_add_prio_rule(const hicn_ip_prefix_t *prefix, uint8_t address_family, const uint32_t priority, const uint8_t table_id) { /* Buffer for holding the response, with appropriate casting on the header */ char buffer[BUFSIZE]; @@ -1341,18 +1349,19 @@ int _nl_add_prio_rule(const ip_prefix_t *prefix, uint8_t address_family, if (prefix) { /* Message attributes = length/type/value */ - struct rtattr a_src = {RTA_LENGTH(ip_address_len(prefix->family)), FRA_SRC}; + struct rtattr a_src = {RTA_LENGTH(hicn_ip_address_len(prefix->family)), + FRA_SRC}; struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; const void *address = - ip_address_get_buffer(&prefix->address, prefix->family); + hicn_ip_address_get_buffer(&prefix->address, prefix->family); if (!address) goto ERR; /* Iovec describing the packets */ const struct iovec iov[] = { {&msg, sizeof(msg)}, /* Source prefix / prefix */ {&a_src, sizeof(a_src)}, - {(void *)address, ip_address_len(prefix->family)}, + {(void *)address, hicn_ip_address_len(prefix->family)}, /* Priority */ {&a_prio, sizeof(a_prio)}, {(void *)&priority, sizeof(uint32_t)}, @@ -1403,13 +1412,13 @@ ERR: return HICN_SOCKET_ERROR_UNSPEC; } -int _nl_add_lo_prio_rule(const ip_prefix_t *prefix, uint8_t address_family, +int _nl_add_lo_prio_rule(const hicn_ip_prefix_t *prefix, uint8_t address_family, const uint32_t priority) { return _nl_add_prio_rule(prefix, address_family, priority, RT_TABLE_LOCAL); } /* ip -6 rule del from all prio 0 table local */ -int _nl_del_prio_rule(const ip_prefix_t *prefix, uint8_t address_family, +int _nl_del_prio_rule(const hicn_ip_prefix_t *prefix, uint8_t address_family, const uint32_t priority, const uint8_t table_id) { /* Buffer for holding the response, with appropriate casting on the header */ char buffer[BUFSIZE]; @@ -1444,11 +1453,12 @@ int _nl_del_prio_rule(const ip_prefix_t *prefix, uint8_t address_family, /* Message attributes = length/type/value */ if (prefix) { - struct rtattr a_src = {RTA_LENGTH(ip_address_len(prefix->family)), FRA_SRC}; + struct rtattr a_src = {RTA_LENGTH(hicn_ip_address_len(prefix->family)), + FRA_SRC}; struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; const void *address = - ip_address_get_buffer(&prefix->address, prefix->family); + hicn_ip_address_get_buffer(&prefix->address, prefix->family); if (!address) goto ERR; /* Iovec describing the packets */ @@ -1456,7 +1466,7 @@ int _nl_del_prio_rule(const ip_prefix_t *prefix, uint8_t address_family, {&msg, sizeof(msg)}, /* Source prefix / prefix */ {&a_src, sizeof(a_src)}, - {(void *)address, ip_address_len(prefix->family)}, + {(void *)address, hicn_ip_address_len(prefix->family)}, /* Priority */ {&a_prio, sizeof(a_prio)}, {(void *)&priority, sizeof(uint32_t)}, @@ -1509,8 +1519,8 @@ ERR: return HICN_SOCKET_ERROR_UNSPEC; } -int _nl_del_lo_prio_rule(const ip_prefix_t *ip_address, uint8_t address_family, - const uint32_t priority) { +int _nl_del_lo_prio_rule(const hicn_ip_prefix_t *ip_address, + uint8_t address_family, const uint32_t priority) { return _nl_del_prio_rule(ip_address, address_family, priority, RT_TABLE_LOCAL); } diff --git a/hicn-light/src/hicn/strategies/CMakeLists.txt b/hicn-light/src/hicn/strategies/CMakeLists.txt index 15ae93fea..434106a44 100644 --- a/hicn-light/src/hicn/strategies/CMakeLists.txt +++ b/hicn-light/src/hicn/strategies/CMakeLists.txt @@ -13,7 +13,6 @@ list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/load_balancer.h - ${CMAKE_CURRENT_SOURCE_DIR}/low_latency.h ${CMAKE_CURRENT_SOURCE_DIR}/random.h ${CMAKE_CURRENT_SOURCE_DIR}/replication.h ${CMAKE_CURRENT_SOURCE_DIR}/best_path.h @@ -23,7 +22,6 @@ list(APPEND HEADER_FILES list(APPEND SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/load_balancer.c - ${CMAKE_CURRENT_SOURCE_DIR}/low_latency.c ${CMAKE_CURRENT_SOURCE_DIR}/random.c ${CMAKE_CURRENT_SOURCE_DIR}/replication.c ${CMAKE_CURRENT_SOURCE_DIR}/best_path.c diff --git a/hicn-light/src/hicn/strategies/best_path.c b/hicn-light/src/hicn/strategies/best_path.c index 35a07c43f..9223cc8ac 100644 --- a/hicn-light/src/hicn/strategies/best_path.c +++ b/hicn-light/src/hicn/strategies/best_path.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -88,8 +88,20 @@ static void bestpath_update_remote_node(strategy_entry_t *entry, strategy_state_t *state = &entry->state.bestpath; strategy_bestpath_options_t *options = &entry->options.bestpath; off_t offset = nexthops_find(nexthops, state->best_nexthop); + + /* Backup flags and cur_len: because our code is called from + * strategy_on_data / check_stop_probing / stop_probing + * which does not expect the nexthop flags to be modified. + */ + uint_fast32_t flags = nexthops->flags; + size_t cur_len = nexthops_get_curlen(nexthops); + nexthops_select(nexthops, offset); update_remote_node_paths(nexthops, entry->forwarder, options->local_prefixes); + + /* Restore flags & curlen */ + nexthops->flags = flags; + nexthops->cur_elts = cur_len; } // probing functions @@ -104,9 +116,8 @@ static void start_probing(strategy_entry_t *entry) { static void stop_probing(strategy_entry_t *entry, nexthops_t *nexthops) { strategy_state_t *state = &entry->state.bestpath; - nexthop_t best_nexthop, nexthop; + nexthop_t best_nexthop; best_nexthop = state->best_nexthop; - unsigned i; unsigned int min_cost = ~0; unsigned current_nexthop_cost = ~0; @@ -164,8 +175,6 @@ static void send_probes(strategy_entry_t *entry, nexthops_t *nexthops, const msgbuf_t *msgbuf) { strategy_state_t *state = &entry->state.bestpath; - unsigned i; - nexthop_t nexthop; bool sent_max_probes = false; nexthops_enumerate(nexthops, i, nexthop, { if (get_sent_probes(nexthop_state(nexthops, i)) < MAX_PROBES) { @@ -241,6 +250,7 @@ static nexthops_t *strategy_bestpath_lookup_nexthops(strategy_entry_t *entry, strategy_state_t *state = &entry->state.bestpath; off_t best_nexthop_offset = nexthops_find(nexthops, state->best_nexthop); + // TODO explain the purpose of this test if (nexthops_len == 1) { nexthop_t nh = nexthops_get_one(nexthops); if (state->best_nexthop != nh) { @@ -265,7 +275,7 @@ static nexthops_t *strategy_bestpath_lookup_nexthops(strategy_entry_t *entry, // send a probe for each interest received send_probes(entry, nexthops, msgbuf); - uint32_t suffix = name_GetSuffix(msgbuf_get_name(msgbuf)); + uint32_t suffix = hicn_name_get_suffix(msgbuf_get_name(msgbuf)); if (suffix >= MIN_PROBE_SUFFIX && suffix <= MAX_PROBE_SUFFIX) { // this packet is a probe from the transport, so register it Ticks time = get_probe_send_time(state->pg, suffix); @@ -302,7 +312,7 @@ static int strategy_bestpath_on_data(strategy_entry_t *entry, strategy_state_t *state = &entry->state.bestpath; if (state->probing_state == PROBING_OFF) return 0; - uint32_t seq = name_GetSuffix(msgbuf_get_name(msgbuf)); + uint32_t seq = hicn_name_get_suffix(msgbuf_get_name(msgbuf)); if (seq >= MIN_PROBE_SUFFIX && seq <= MAX_PROBE_SUFFIX) { if (pitEntryCreation != 0) { // this is not a probe sent by the forwader. do not use it in the probing @@ -311,7 +321,6 @@ static int strategy_bestpath_on_data(strategy_entry_t *entry, return 0; } - unsigned nexthop, i; Ticks send_time = get_probe_send_time(state->pg, seq); if (send_time != 0) { Ticks rtt = ticks_now() - send_time; diff --git a/hicn-light/src/hicn/strategies/load_balancer.c b/hicn-light/src/hicn/strategies/load_balancer.c index 709efcf23..0e1a170f7 100644 --- a/hicn-light/src/hicn/strategies/load_balancer.c +++ b/hicn-light/src/hicn/strategies/load_balancer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -58,8 +58,6 @@ static inline void update_state_dec(nexthop_state_t *state) { } static inline void reset_all(nexthops_t *nexthops) { - unsigned i; - nexthop_t nexthop; nexthops_enumerate(nexthops, i, nexthop, { (void)nexthop; nexthops->state[i].load_balancer = NEXTHOP_STATE_INIT; @@ -95,9 +93,9 @@ static int strategy_load_balancer_remove_nexthop(strategy_entry_t *entry, static nexthops_t *strategy_load_balancer_lookup_nexthops( strategy_entry_t *entry, nexthops_t *nexthops, const msgbuf_t *msgbuf) { + if (nexthops_get_curlen(nexthops) == 0) return nexthops; /* Compute the sum of weights of potential next hops */ double sum = 0; - unsigned i, nexthop; nexthops_enumerate(nexthops, i, nexthop, { (void)nexthop; sum += nexthops_state(nexthops, i).load_balancer.weight; @@ -125,10 +123,7 @@ static int strategy_load_balancer_on_timeout( * nexthops, we can allow for linear search that will be very efficient * CPU-wise. */ - nexthop_t timeout_nexthop; nexthops_foreach(timeout_nexthops, timeout_nexthop, { - nexthop_t nexthop; - unsigned i; nexthops_enumerate(nexthops, i, nexthop, { if (nexthop == timeout_nexthop) update_state_dec(nexthop_state(nexthops, i)); diff --git a/hicn-light/src/hicn/strategies/local_prefixes.c b/hicn-light/src/hicn/strategies/local_prefixes.c index 23d72ae80..25927ac69 100644 --- a/hicn-light/src/hicn/strategies/local_prefixes.c +++ b/hicn-light/src/hicn/strategies/local_prefixes.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -16,13 +16,12 @@ #include "local_prefixes.h" #include <hicn/core/forwarder.h> #include <hicn/core/nexthops.h> -#include <hicn/core/name.h> #include <hicn/core/mapme.h> #define MAX_PREFIXES 10 struct local_prefixes_s { - Name local_prefixes[MAX_PREFIXES]; + hicn_prefix_t local_prefixes[MAX_PREFIXES]; unsigned len; }; @@ -38,9 +37,10 @@ unsigned local_prefixes_get_len(local_prefixes_t *prefixes) { return prefixes->len; } -bool contain_prefix(local_prefixes_t *prefixes, Name *name) { +bool contain_prefix(const local_prefixes_t *prefixes, + const hicn_prefix_t *prefix) { for (unsigned i = 0; i < prefixes->len; i++) { - if (name_Equals(&(prefixes->local_prefixes[i]), name)) return true; + if (hicn_prefix_equals(&(prefixes->local_prefixes[i]), prefix)) return true; } return false; } @@ -51,19 +51,19 @@ void local_prefixes_add_prefixes(local_prefixes_t *prefixes, unsigned i = 0; while ((i < new_prefixes->len) && (prefixes->len < MAX_PREFIXES)) { if (!contain_prefix(prefixes, &(new_prefixes->local_prefixes[i]))) { - name_Copy(&new_prefixes->local_prefixes[i], - &prefixes->local_prefixes[prefixes->len]); + hicn_prefix_copy(&prefixes->local_prefixes[prefixes->len], + &new_prefixes->local_prefixes[i]); prefixes->len++; } i++; } } -void local_prefixes_add_prefix(local_prefixes_t *prefixes, const void *prefix) { +void local_prefixes_add_prefix(local_prefixes_t *prefixes, + const hicn_prefix_t *prefix) { if (prefixes->len >= MAX_PREFIXES) return; - Name *n = (Name *)prefix; - if (!contain_prefix(prefixes, n)) { - name_Copy(n, &(prefixes->local_prefixes[prefixes->len])); + if (!contain_prefix(prefixes, prefix)) { + hicn_prefix_copy(&(prefixes->local_prefixes[prefixes->len]), prefix); prefixes->len++; } } @@ -74,8 +74,9 @@ void update_remote_node_paths(const void *nexthops, const void *forwarder, struct mapme_s *mapme = forwarder_get_mapme((forwarder_t *)forwarder); fib_t *fib = forwarder_get_fib((forwarder_t *)forwarder); for (unsigned i = 0; i < prefixes->len; i++) { - fib_entry_t *entry = fib_match_name(fib, &prefixes->local_prefixes[i]); + fib_entry_t *entry = fib_match_prefix(fib, &prefixes->local_prefixes[i]); if (!entry) continue; - mapme_set_adjacencies(mapme, entry, (nexthops_t *)nexthops, false); + // XXX we don't want to force + mapme_set_adjacencies(mapme, entry, (nexthops_t *)nexthops); } } diff --git a/hicn-light/src/hicn/strategies/local_prefixes.h b/hicn-light/src/hicn/strategies/local_prefixes.h index 833a48057..9d7d8ec78 100644 --- a/hicn-light/src/hicn/strategies/local_prefixes.h +++ b/hicn-light/src/hicn/strategies/local_prefixes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -24,6 +24,8 @@ #ifndef HICNLIGHT_LOCAL_PREFIXES_H #define HICNLIGHT_LOCAL_PREFIXES_H +#include <hicn/name.h> + typedef struct local_prefixes_s local_prefixes_t; local_prefixes_t* create_local_prefixes(); @@ -35,7 +37,8 @@ unsigned local_prefixes_get_len(local_prefixes_t* prefixes); void local_prefixes_add_prefixes(local_prefixes_t* prefixes, local_prefixes_t* new_prefixes); -void local_prefixes_add_prefix(local_prefixes_t* prefixes, const void* prefix); +void local_prefixes_add_prefix(local_prefixes_t* prefixes, + const hicn_prefix_t* prefix); void update_remote_node_paths(const void* nexthops, const void* forwarder, local_prefixes_t* prefixes); diff --git a/hicn-light/src/hicn/strategies/low_latency.c b/hicn-light/src/hicn/strategies/low_latency.c deleted file mode 100644 index 1e5a74c1a..000000000 --- a/hicn-light/src/hicn/strategies/low_latency.c +++ /dev/null @@ -1,776 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if 0 - -#include <hicn/hicn-light/config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <math.h> - -#include <hicn/base/khash.h> - -#include <parc/assert/parc_Assert.h> -#include <parc/algol/parc_HashMap.h> -#include <parc/algol/parc_Memory.h> -#include <parc/algol/parc_Object.h> -#include <parc/algol/parc_Unsigned.h> - -#include <hicn/core/messageHandler.h> - -#include "low_latency.h" - -#define STABILITY_FACTOR 15 -#define MAX_SWITCH_TRY 10 -#define MAX_LATENCY_DIFF 10 -#define MAX_TOLLERATED_LATENCY_DIFF 15 -#define MAX_ROUNDS_MP_WITHOUT_CHECK 2 -#define MAX_ROUNDS_AVOIDING_MULTIPATH 40 /* about 20 sec */ -#define MAX_ROUNDS_WITH_ERROR 4 -#define PROBE_LIFETIME 500 /* ms */ - -#define MAX_ROUNS_WITHOUT_PROBES 4 - -/* - * If we do not receives probes for 4 rounds it means that we had no responce - * from any producer for 2 sec we can say that this interface is daed - */ -#define MIN_NON_LOSSY_ROUNDS 10 - -/* - * Number of rounds in non lossy mode before switch to no lossy state - * Defaults to 10 % - */ -#define MAX_LOSS_RATE 0.10 - -/* Shorthands */ -#define nexthop_state_t strategy_low_latency_nexthop_state_t -#define state_t strategy_low_latency_state_t - -#define NEXTHOP_STATE_INIT \ - { \ - .in_use = false, .is_allowed = true, .sent_packets = 0, \ - .last_try_to_switch_round = 0, .try_to_switch_counter = 0, \ - .recevied_probes = 0, .rounds_without_probes = 0, .sent_probes = 0, \ - .lost_probes = 0, .non_lossy_rounds = MIN_NON_LOSSY_ROUNDS, \ - .avg_rtt = -1.0, .avg_rtt_in_use = -1.0, .avg_queue = 0.0001, \ - .avg_loss_rate = 0.0, \ - } - -// XXX ???? -#define STATE_INIT \ - {} - -static - void -strategy_low_latency_SendProbesCB(int fd, PARCEventType which_event, void *data) -{ - parcAssertTrue(which_event & PARCEventType_Timeout, - "Event incorrect, expecting %X set, got %X", - PARCEventType_Timeout, which_event); - - StrategyLowLatency *ll = (StrategyLowLatency *) data; - - //delete old pending probes - if(parcHashMap_Size(ll->pending_probes_ticks) != 0){ - Ticks now = forwarder_GetTicks(ll->forwarder); - PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->pending_probes_ticks); - NumberSet *to_remove = numberSet_Create(); - while(parcIterator_HasNext(iterator)) { - PARCUnsigned *parc_seq = (PARCUnsigned *) parcIterator_Next(iterator); - PARCUnsigned *parc_time = (PARCUnsigned *) parcHashMap_Get(ll->pending_probes_ticks, parc_seq); - Ticks sent_time = parcUnsigned_GetUnsigned(parc_time); - if((now - sent_time) > PROBE_LIFETIME){ - //probes to delete - numberSet_Add(to_remove, parcUnsigned_GetUnsigned(parc_seq)); - } - } - parcIterator_Release(&iterator); - - for(int i = 0; i < numberSet_Length(to_remove); i++){ - PARCUnsigned *prob_seq = parcUnsigned_Create(numberSet_GetItem(to_remove,i)); - PARCUnsigned *cid = (PARCUnsigned *) parcHashMap_Get(ll->pending_probes_faces, prob_seq); - StrategyNexthopStateLL *state = - (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid); - strategyNexthopStateLL_LostProbe(state); - parcHashMap_Remove(ll->pending_probes_ticks, prob_seq); - parcHashMap_Remove(ll->pending_probes_faces, prob_seq); - parcUnsigned_Release(&prob_seq); - } - numberSet_Release(&to_remove); - } - - ConnectionTable * ct = forwarder_GetConnectionTable(ll->forwarder); - - PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - while(parcIterator_HasNext(iterator)){ - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - Connection *conn = - (Connection *)connectionTable_FindById(ct, - parcUnsigned_GetUnsigned(cid)); - if(!conn) - continue; - - StrategyNexthopStateLL *state = - (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid); - - //probe only usable paths - if(!strategyNexthopStateLL_IsAllowed(state)) - continue; - - uint32_t seq = rand(); - messageHandler_SetProbeName(ll->probe, HF_INET6_TCP, - ll->name, seq); - connection_Probe(conn, ll->probe); - - PARCUnsigned *parc_seq = parcUnsigned_Create(seq); - Ticks now = forwarder_GetTicks(ll->forwarder); - PARCUnsigned *parc_time = parcUnsigned_Create((unsigned int)now); - parcHashMap_Put(ll->pending_probes_ticks, parc_seq, parc_time); - parcHashMap_Put(ll->pending_probes_faces, parc_seq, cid); - strategyNexthopStateLL_SentProbe(state); - parcUnsigned_Release(&parc_seq); - parcUnsigned_Release(&parc_time); - } - parcIterator_Release(&iterator); - - struct timeval timeout = {0,50000}; - parcEventTimer_Start(ll->sendProbes, &timeout); -} - -static -void -strategy_low_latency_SendMapmeUpdate(StrategyLowLatency *ll, - const NumberSet * nexthops){ - MapMe * mapme = forwarder_getMapmeInstance(ll->forwarder); - FIB * fib = forwarder_getFib((Forwarder*) ll->forwarder); - for(unsigned i = 0; i < ll->related_prefixes_len; i++){ - FibEntry *fibEntry = fib_MatchName(fib, ll->related_prefixes[i]); - if (!fibEntry) - continue; - mapme_maybe_send_to_nexthops(mapme, fibEntry, nexthops); - } -} - -static -void -strategy_low_latency_SelectBestFaces(StrategyLowLatency *ll, bool new_round) -{ - - StrategyNexthopStateLL * old_faces[2]; - old_faces[0] = ll->bestFaces[0]; - old_faces[1] = ll->bestFaces[1]; - - if(new_round){ - ll->round++; - } - - if(parcHashMap_Size(ll->strategy_state) == 0){ - ll->bestFaces[0] = NULL; - ll->bestFaces[1] = NULL; - ll->use2paths = false; - goto NEW_ROUND; - } - - if(ll->use2paths && ll->bestFaces[0] != NULL && ll->bestFaces[1] != NULL){ - //multipath case - - if(!strategyNexthopStateLL_IsLossy(ll->bestFaces[0]) - && !strategyNexthopStateLL_IsLossy(ll->bestFaces[1]) - && strategyNexthopStateLL_IsAllowed(ll->bestFaces[0]) - && strategyNexthopStateLL_IsAllowed(ll->bestFaces[1])){ - - if(ll->rounds_in_multipath < MAX_ROUNDS_MP_WITHOUT_CHECK){ - //we are at the first rounds of the multipath let's wait a bit - //(MAX_ROUNDS_MP_WITHOUT_CHECK) to make the queuing converge - ll->rounds_in_multipath++; - goto NEW_ROUND; - } - - //we need to decide if we want ot keep using two paths or not - ll->rounds_in_multipath++; - double rtt0 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]); - double rtt1 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]); - double diff = fabs(rtt0 - rtt1); - - if(diff < MAX_LATENCY_DIFF){ - //everything is working, keep using the two paths - ll->rounds_with_error = 0; - goto NEW_ROUND; - } - - //check for how many rounds we had problems - if(ll->rounds_with_error < MAX_ROUNDS_WITH_ERROR && - diff < MAX_TOLLERATED_LATENCY_DIFF){ - //we can tollerate few round with errors - ll->rounds_with_error++; - goto NEW_ROUND; - } - - //prevent the usage of multiple paths - ll->rounds_with_error = 0; - ll->avoid_multipath = true; - ll->rounds_avoiding_multipath = 0; - } //else - //at least one of the two path is lossy - //or it is not allowed by the policies. - //search for a better possibility - } - - ll->bestFaces[0] = NULL; - ll->bestFaces[1] = NULL; - - //check if there is at least one non lossy connection - PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - bool check_losses = true; - bool found_good_face = false; - while(parcIterator_HasNext(iterator) && !found_good_face){ - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - const StrategyNexthopStateLL *state = parcHashMap_Get(ll->strategy_state, cid); - if(!strategyNexthopStateLL_IsLossy(state) && - strategyNexthopStateLL_IsAllowed(state)){ - found_good_face = true; - } - } - parcIterator_Release(&iterator); - if(!found_good_face){ - // all the available faces are lossy, so we take into account only - // the latency computed with the probes - check_losses = false; - } - - if(ll->bestFaces[0] == NULL){ - //try to take a random face - PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - bool face_found = false; - while(parcIterator_HasNext(iterator) && !face_found) { - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - StrategyNexthopStateLL *state = (StrategyNexthopStateLL *) - parcHashMap_Get(ll->strategy_state, cid); - - if((check_losses && strategyNexthopStateLL_IsLossy(state)) || - !strategyNexthopStateLL_IsAllowed(state)){ - //skip the face - continue; - } - - ll->bestFaces[0] = state; - face_found = true; - } - parcIterator_Release(&iterator); - } - - if(ll->bestFaces[0] == NULL){ - //no usable face exists - ll->bestFaces[0] = NULL; - ll->bestFaces[1] = NULL; - ll->use2paths = false; - goto NEW_ROUND; - } - - double bestRtt = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]); - - if(ll->avoid_multipath) - ll->rounds_avoiding_multipath++; - - if(ll->rounds_avoiding_multipath > MAX_ROUNDS_AVOIDING_MULTIPATH){ - ll->avoid_multipath = false; - ll->rounds_avoiding_multipath = 0; - } - - iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - while (parcIterator_HasNext(iterator)) { - - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - StrategyNexthopStateLL *state = (StrategyNexthopStateLL *) - parcHashMap_Get(ll->strategy_state, cid); - double rtt = strategyNexthopStateLL_GetRTTLive(state); - - if((check_losses && strategyNexthopStateLL_IsLossy(state)) || - !strategyNexthopStateLL_IsAllowed(state)){ - //skip the face - continue; - } - - if(rtt + STABILITY_FACTOR < bestRtt){ - //maybe we found a better face - double rttInUse = strategyNexthopStateLL_GetRTTInUse(state); - unsigned try = strategyNexthopStateLL_GetTryToSwitch(state); - - //we check the rtt in use to check if the new face that we found - //gets congested when we use it to send the traffic - if(rttInUse < bestRtt || try > MAX_SWITCH_TRY){ - //we have a new best face! - strategyNexthopStateLL_ResetTryToSwitch((StrategyNexthopStateLL*) state); - bestRtt = rtt; - if(ll->bestFaces[0] != NULL) - strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[0]); - ll->bestFaces[0] = (StrategyNexthopStateLL*) state; - }else{ - //in this case we should switch but we wait MAX_SWITCH_TRY - //before switch to avoid ossillations between different paths - strategyNexthopStateLL_IncreaseTryToSwitch( - (StrategyNexthopStateLL*) state, ll->round); - } - } - } - - parcIterator_Release(&iterator); - - if(ll->bestFaces[0] == NULL){ - //we found no face so return - ll->bestFaces[0] = NULL; - ll->bestFaces[1] = NULL; - ll->use2paths = false; - goto NEW_ROUND; - } - - if(parcHashMap_Size(ll->strategy_state) == 1 || ll->avoid_multipath){ - //in this case (one face available or avoid multipath) we stop the - //search here. Just reset face 1 if needed - if(ll->bestFaces[1] != NULL){ - strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]); - ll->bestFaces[1] = NULL; - } - ll->use2paths = false; - goto NEW_ROUND; - } - - //if we are here we have more than 1 interface, so we search for a second one - //to use in case of multipath - iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - while (parcIterator_HasNext(iterator)) { - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - if(parcUnsigned_GetUnsigned(cid) != - strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])){ - - StrategyNexthopStateLL *state = (StrategyNexthopStateLL *) - parcHashMap_Get(ll->strategy_state, cid); - - if((check_losses && strategyNexthopStateLL_IsLossy(state)) || - !strategyNexthopStateLL_IsAllowed(state)){ - //skip the face - continue; - } - - if(ll->bestFaces[1] == NULL){ - //in case of 2 faces we should pass always here - ll->bestFaces[1] = state; - }else{ - //TODO this must be tested with more then 2 faces - double rtt1 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]); - double rttNewFace = strategyNexthopStateLL_GetRTTLive(state); - if(rttNewFace + STABILITY_FACTOR < rtt1){ - strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]); - ll->bestFaces[1] = state; - } - } - } - } - parcIterator_Release(&iterator); - - if(ll->bestFaces[1] != NULL){ - //we are not using the second face yet so we use the normal rtt for comparison - double rtt0 = strategyNexthopStateLL_GetRTTProbe(ll->bestFaces[0]); - double rtt1 = strategyNexthopStateLL_GetRTTProbe(ll->bestFaces[1]); - double diff = fabs(rtt0 - rtt1); - if(diff < MAX_LATENCY_DIFF) { - //let's start to use 2 paths - ll->rounds_with_error = 0; - ll->use2paths = true; - ll->rounds_in_multipath = 0; - }else{ - //we use only one path - strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]); - ll->bestFaces[1] = NULL; - ll->use2paths = false; - } - }else{ - ll->use2paths = false; - } - -NEW_ROUND: - { - Logger * log = forwarder_GetLogger(ll->forwarder); - if(log != NULL && - logger_IsLoggable(log, LoggerFacility_Strategy, PARCLogLevel_Info)){ - if(ll->use2paths){ - logger_Log(log, LoggerFacility_Strategy, PARCLogLevel_Info, - __func__, "use 2 paths. rtt face %d = %f queue = %f is_lossy = %d," - "rtt face %d = %f queue = %f is_lossy = %d\n", - strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]), - strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]), - strategyNexthopStateLL_GetQueuing(ll->bestFaces[0]), - strategyNexthopStateLL_IsLossy(ll->bestFaces[0]), - strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]), - strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]), - strategyNexthopStateLL_GetQueuing(ll->bestFaces[1]), - strategyNexthopStateLL_IsLossy(ll->bestFaces[1])); - }else{ - if(ll->bestFaces[0] != NULL){ - logger_Log(log, LoggerFacility_Strategy, - PARCLogLevel_Info, __func__, - "use 1 path. rtt face %d = %f is_lossy = %d, " - "(avoid multipath = %d)\n", - strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]), - strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]), - strategyNexthopStateLL_IsLossy(ll->bestFaces[0]), - ll->avoid_multipath); - }else{ - logger_Log(log, LoggerFacility_Strategy, PARCLogLevel_Info, - __func__, "no face to use!\n"); - } - } - } - } - - //update the round only at the end for all the faces - if(new_round){ - PARCIterator * iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - while (parcIterator_HasNext(iterator)) { - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - strategyNexthopStateLL_StartNewRound((StrategyNexthopStateLL *) - parcHashMap_Get(ll->strategy_state, cid)); - } - parcIterator_Release(&iterator); - } - - //mapme updates - //if ll->bestFaces[0] == NULL we don't have any output faces - //so don't need to send any updates since we are disconnected - if(ll->related_prefixes_len != 0){ - if(ll->bestFaces[0] != NULL){ - NumberSet *out = numberSet_Create(); - if(old_faces[0] == NULL || - (strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]) != - strategyNexthopStateLL_GetFaceId(old_faces[0]))){ - //there is a new face 0 so we need a map me update - //if ll->bestFaces[1] != NULL we need to send the update - //even if it is the same as before - numberSet_Add(out, - strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])); - if(ll->bestFaces[1] != NULL){ - numberSet_Add(out, - strategyNexthopStateLL_GetFaceId(ll->bestFaces[1])); - } - strategy_low_latency_SendMapmeUpdate(ll,out); - }else{ - if(ll->bestFaces[1] != NULL){ - if(old_faces[1] == NULL || - (strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]) != - strategyNexthopStateLL_GetFaceId(old_faces[1]))){ - //send a mapme both with face 0 and face 1 - numberSet_Add(out, - strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])); - numberSet_Add(out, - strategyNexthopStateLL_GetFaceId(ll->bestFaces[1])); - strategy_low_latency_SendMapmeUpdate(ll,out); - } - }else{ - if(old_faces[1] != NULL){ - //in the previuos round we were using two faces, now only one - //send update with only face 0 - numberSet_Add(out, - strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])); - strategy_low_latency_SendMapmeUpdate(ll,out); - } - } - } - numberSet_Release(&out); - } - } -} - -static -void -strategy_low_latency_BestFaceCB(int fd, PARCEventType which_event, void *data) -{ - parcAssertTrue(which_event & PARCEventType_Timeout, - "Event incorrect, expecting %X set, got %X", - PARCEventType_Timeout, which_event); - - StrategyLowLatency * ll = (StrategyLowLatency *) data; - strategy_low_latency_SelectBestFaces(ll, true); - - struct timeval timeout = {0, 500000}; - parcEventTimer_Start(ll->computeBestFace, &timeout); -} - -static -void -_startTimers(strategy_entry_t * entry) -{ - struct timeval timeoutProbes = {0, 10000}; - struct timeval timeoutBF = {1, 0}; - - parcEventTimer_Start(entry->state.sendProbes, &timeoutProbes); - parcEventTimer_Start(entry->state.computeBestFace, &timeoutBF); -} - -static -void -_stopTimers(strategy_entry_t * entry) -{ - parcEventTimer_Stop(entry->state.sendProbes); - parcEventTimer_Stop(entry->state.computeBestFace); -} - -static -void -strategy_low_latency_initialize(strategy_entry_t * entry) -{ - srand((unsigned int)time(NULL)); - - /* XXX TODO Three hashmaps to initialize */ - strategy->strategy_state = parcHashMap_Create(); - strategy->pending_probes_ticks = parcHashMap_Create(); - strategy->pending_probes_faces = parcHashMap_Create(); - - Dispatcher *dispatcher = forwarder_GetDispatcher((Forwarder *)ll->forwarder); - ip_prefix_t address; - nameBitvector_ToIPAddress(name_GetContentName( - fibEntry_GetPrefix(fibEntry)), &address); - - entry->state = { - .probe = messageHandler_CreateProbePacket(HF_INET6_TCP, PROBE_LIFETIME), - .name = messageHandler_CreateProbeName(&address); - .sendProbes = dispatcher_CreateTimer(dispatcher, false, - strategy_low_latency_SendProbesCB, ll); - .round = 0; - .rounds_in_multipath = 0; - .rounds_with_error = 0; - .rounds_avoiding_multipath = 0; - .use2paths = false; - .avoid_multipath = false; - .computeBestFace = dispatcher_CreateTimer(dispatcher, false, - strategy_low_latency_BestFaceCB, ll); - .related_prefixes_len = related_prefixes_len; - // XXX TODO - .related_prefixes = malloc(sizeof(Name *) * related_prefixes_len); - }; - - for(unsigned i = 0; i < entry->state.related_prefixes_len; i++){ - entry->state.related_prefixes[i] = name_Copy(related_prefixes[i]); - } -} - -static -void -strategy_low_latency_finalize(strategy_entry_t * entry) -{ - _stopTimers(entry); - - parcEventTimer_Destroy(&(strategy->sendProbes)); - parcEventTimer_Destroy(&(strategy->computeBestFace)); - - if (parcHashMap_Size(strategy->strategy_state) > 0) { - PARCIterator *it = parcHashMap_CreateKeyIterator(strategy->strategy_state); - while (parcIterator_HasNext(it)) { - PARCUnsigned *cid = parcIterator_Next(it); - StrategyNexthopStateLL *state = - (StrategyNexthopStateLL *)parcHashMap_Get(strategy->strategy_state, cid); - parcObject_Release((void**)&state); - } - parcIterator_Release(&it); - } - - parcHashMap_Release(&(strategy->strategy_state)); - parcHashMap_Release(&(strategy->pending_probes_ticks)); - parcHashMap_Release(&(strategy->pending_probes_faces)); - - parcMemory_Deallocate(&(strategy->probe)); - parcMemory_Deallocate(&(strategy->name)); - - for(unsigned i = 0; i < strategy->related_prefixes_len; i++){ - name_Release(&(strategy->related_prefixes[i])); - } - free(strategy->related_prefixes); - - parcMemory_Deallocate((void **)&strategy); - parcMemory_Deallocate((void **)&impl); - *strategyPtr = NULL; -} - -static -void -strategy_low_latency_add_nexthop(strategy_entry_t * entry, unsigned nexthop, nexthop_state_t * state) -{ - PARCUnsigned *cid = parcUnsigned_Create(connectionId); - - StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context; - - if (!parcHashMap_Contains(ll->strategy_state, cid)) { - StrategyNexthopStateLL *state = strategyNexthopStateLL_Create(connectionId); - parcHashMap_Put(ll->strategy_state, cid, state); - if(ll->bestFaces[0] == NULL){ - ll->bestFaces[0] = state; - } - } - - if(parcHashMap_Size(ll->strategy_state) >= 2){ - _startTimers(strategy); - } - - parcUnsigned_Release(&cid); -} - -static -void -strategy_low_latency_remove_nexthop(strategy_entry_t * entry, unsigned nexthop, nexthop_state_t * state) -{ - bool reset_bestFaces = false; - - if((entry->state.bestFaces[0] != NULL && - strategyNexthopStateLL_GetFaceId(entry->state.bestFaces[0]) == connectionId) || - (entry->state.bestFaces[1] != NULL && - strategyNexthopStateLL_GetFaceId(entry->state.bestFaces[1]) == connectionId)){ - reset_bestFaces = true; - } - - PARCUnsigned *cid = parcUnsigned_Create(connectionId); - - if (parcHashMap_Contains(entry->state.strategy_state, cid)) { - parcHashMap_Remove(entry->state.strategy_state, cid); - } - - if(reset_bestFaces){ - entry->state.bestFaces[0] = NULL; - entry->state.bestFaces[1] = NULL; - strategy_low_latency_SelectBestFaces(ll, false); - } - - if(parcHashMap_Size(entry->state.strategy_state) < 2){ - _stopTimers(strategy); - } - - parcUnsigned_Release(&cid); -} - -static -nexthops_t * -strategy_low_latency_lookup_nexthops(strategy_entry_t * entry, - const msgbuf_t * msgbuf) -{ - //unsigned out_connection; - NumberSet *out = numberSet_Create(); - - StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context; - - //update is_allowed flag of all the next hops - PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - while(parcIterator_HasNext(iterator)){ - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - StrategyNexthopStateLL *state = - (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid); - if(numberSet_Contains(nexthops, parcUnsigned_GetUnsigned(cid))){ - strategyNexthopStateLL_SetIsAllowed(state,true); - }else{ - strategyNexthopStateLL_SetIsAllowed(state,false); - } - } - parcIterator_Release(&iterator); - - if(ll->bestFaces[0] != NULL && - !strategyNexthopStateLL_IsAllowed(ll->bestFaces[0])){ - //if ll->bestFaces[0] is not allowed we need to find a new face - strategy_low_latency_SelectBestFaces(ll, false); - } - - //at this point ll->bestFaces[0] must be allowed - //single path case - if(ll->bestFaces[0] != NULL && (ll->bestFaces[1] == NULL || !ll->use2paths)){ - strategyNexthopStateLL_SendPacket(ll->bestFaces[0]); - numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])); - - //multipath case - }else if(ll->bestFaces[0] != NULL && ll->bestFaces[1] != NULL && ll->use2paths){ - //it may happen that ll->bestFaces[1] is not allowed, in that case we send on - //ll->bestFaces[0] until the next best face selection - if(!strategyNexthopStateLL_IsAllowed(ll->bestFaces[1])){ - strategyNexthopStateLL_SendPacket(ll->bestFaces[0]); - numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])); - }else{ - double queue0 = strategyNexthopStateLL_GetQueuing(ll->bestFaces[0]); - double queue1 = strategyNexthopStateLL_GetQueuing(ll->bestFaces[1]); - double prob0 = 0.5; - if(queue0 > 1 || queue1 > 1){ - prob0 = 1.0 - (queue0 / (queue0 + queue1)); - } - double coin = ((double) rand() / (RAND_MAX)); - if(coin < prob0){ - strategyNexthopStateLL_SendPacket(ll->bestFaces[0]); - numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])); - }else{ - strategyNexthopStateLL_SendPacket(ll->bestFaces[1]); - numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[1])); - } - } - } - return out; -} - - - -static -void -strategy_low_latency_on_data(strategy_entry_t * entry, - const nexthops_t * nexthops, const msgbuf_t * msgbuf, - Ticks pitEntryCreation, Ticks objReception) -{ - if (!msgbuf_is_probe(msgbuf)) - return; - - uint32_t seq = messageHandler_GetSegment(message_FixedHeader(objectMessage)); - if (!parcHashMap_Contains(ll->pending_probes_ticks, seq)) - return; // unexpected - - /* A single nexthop is expected */ - unsigned nexthop; - nexthops_foreach(nexthops, nexthop, { - const StrategyNexthopStateLL *state = - parcHashMap_Get(ll->strategy_state, nexthop); - if (!state) - // this may happen if we remove a face/route while downloading a file - // we should ignore this timeout - continue; - - Ticks time = parcUnsigned_GetUnsigned( - parcHashMap_Get(ll->pending_probes_ticks, seq)); - Ticks now = forwarder_GetTicks(ll->forwarder); - Ticks RTT = now - time; - if(RTT <= 0) - RTT = 1; - strategyNexthopStateLL_AddRttSample( - (StrategyNexthopStateLL *) state, (unsigned int)RTT); - parcHashMap_Remove(ll->pending_probes_ticks, seq); - } - }; -} - -static -void -strategy_low_latency_on_timeout(strategy_entry_t * entry, const nexthops_t * nexthops) -{ - /* Nothing to do */ -} - -DECLARE_STRATEGY(low_latency); - -#undef nexthop_state_t -#undef state_t - -#endif diff --git a/hicn-light/src/hicn/strategies/low_latency.h b/hicn-light/src/hicn/strategies/low_latency.h deleted file mode 100644 index 6b3001637..000000000 --- a/hicn-light/src/hicn/strategies/low_latency.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Forward on the path with lowest latency - */ - -#ifndef HICNLIGHT_STRATEGY_LOW_LATENCY_H -#define HICNLIGHT_STRATEGY_LOW_LATENCY_H - -struct name_s; - -#include <hicn/strategy.h> - -typedef struct { - void *_; -} strategy_low_latency_nexthop_state_t; - -typedef struct { - void *_; -} strategy_low_latency_state_t; - -typedef struct { - // Name ** related_prefixes; - struct name_s *related_prefixes[MAX_FWD_STRATEGY_RELATED_PREFIXES]; - unsigned related_prefixes_len; -} strategy_low_latency_options_t; - -#if 0 - -/* - * We have global state in addition to state associated for each next hop : - */ -typedef struct { - bool in_use; - bool is_allowed; // XXX TODO the policy may not allow the use of this face -// unsigned face_id; - unsigned sent_packets; - /* switch metrics */ - unsigned last_try_to_switch_round; - unsigned try_to_switch_counter; - /* probes counters */ - unsigned recevied_probes; - unsigned rounds_without_probes; - unsigned sent_probes; - unsigned lost_probes; - unsigned non_lossy_rounds; - /* Averages */ - double avg_rtt; - double avg_rtt_in_use; - double avg_queue; - double avg_loss_rate; -} strategy_low_latency_nexthop_state_t; - -typedef struct { - // hash map from connectionId to StrategyNexthopStateLL - //PARCHashMap *strategy_state; - // XXX This is now store in each nexthop state - - /* - * Hhash map from sequence number to ticks (sent time) - * - * TODO improvement: the tick and face id could be stored in the probe and - * repeated in the reply to avoid state to be maintained. - * - * Also, in case we have few probes, linear scan might be more effective - */ - PARCHashMap *pending_probes_ticks; - - /* hash map from sequence number to face id */ - PARCHashMap *pending_probes_faces; - - const Forwarder * forwarder; - PARCEventTimer *sendProbes; - PARCEventTimer *computeBestFace; - uint8_t * probe; - hicn_name_t * name; - StrategyNexthopStateLL * bestFaces[2]; - unsigned round; - unsigned rounds_in_multipath; - unsigned rounds_with_error; - unsigned rounds_avoiding_multipath; - bool use2paths; - bool avoid_multipath; -} strategy_low_latency_state_t; - -#endif - -#endif /* HICNLIGHT_STRATEGY_LOW_LATENCY_H */ diff --git a/hicn-light/src/hicn/strategies/probe_generator.c b/hicn-light/src/hicn/strategies/probe_generator.c index bc141e518..fd0bf5471 100644 --- a/hicn-light/src/hicn/strategies/probe_generator.c +++ b/hicn-light/src/hicn/strategies/probe_generator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -87,8 +87,7 @@ int generate_probe(probe_generator_t *pg, const msgbuf_t *msgbuf, uint32_t seq = get_seq_number(pg); if (seq == 0) return -1; - - messageHandler_ModifySuffix(msgbuf_get_packet(probe), seq); + msgbuf_modify_suffix(probe, seq); connection_send(conn, probe_offset, true); connection_flush(conn); add_to_map(pg, seq, ticks_now()); diff --git a/hicn-light/src/hicn/strategies/probe_generator.h b/hicn-light/src/hicn/strategies/probe_generator.h index 7a9f3a58a..065d824a1 100644 --- a/hicn-light/src/hicn/strategies/probe_generator.h +++ b/hicn-light/src/hicn/strategies/probe_generator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -20,6 +20,9 @@ #include <hicn/core/ticks.h> #include <hicn/core/msgbuf.h> +#define MIN_PROBE_SUFFIX 0xefffffff +#define MAX_PROBE_SUFFIX 0xffffffff - 1 + KHASH_MAP_INIT_INT64(bp_map, Ticks); struct forwarder_s; diff --git a/hicn-light/src/hicn/strategies/random.c b/hicn-light/src/hicn/strategies/random.c index 5b076df7c..aabae73bc 100644 --- a/hicn-light/src/hicn/strategies/random.c +++ b/hicn-light/src/hicn/strategies/random.c @@ -53,6 +53,7 @@ static int strategy_random_remove_nexthop(strategy_entry_t *entry, static nexthops_t *strategy_random_lookup_nexthops(strategy_entry_t *entry, nexthops_t *nexthops, const msgbuf_t *msgbuf) { + if (nexthops_get_curlen(nexthops) == 0) return nexthops; nexthops_select(nexthops, rand() % nexthops_get_len(nexthops)); return nexthops; } diff --git a/hicn-light/src/hicn/test/CMakeLists.txt b/hicn-light/src/hicn/test/CMakeLists.txt index 65e216c1e..cbe939297 100644 --- a/hicn-light/src/hicn/test/CMakeLists.txt +++ b/hicn-light/src/hicn/test/CMakeLists.txt @@ -1,19 +1,13 @@ -# Copyright (c) 2021 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 Cisco and/or its affiliates. include(BuildMacros) list(APPEND TESTS_SRC - test-bitmap.cc test-configuration.cc - test-hash.cc - test-khash.cc + test-fib.cc test-loop.cc - test-pool.cc test-parser.cc test-ctrl.cc - test-ring.cc - test-vector.cc - test-interest_manifest.cc test-msgbuf_pool.cc test-nexthops.cc test-connection_table.cc @@ -26,8 +20,8 @@ list(APPEND TESTS_SRC test-subscription.cc test-local_prefixes.cc test-probe_generator.cc - ${CMAKE_CURRENT_SOURCE_DIR}/../config/command_listener.c - ${CMAKE_CURRENT_SOURCE_DIR}/../config/command_route.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_listener.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_route.c main.cc ) @@ -39,6 +33,7 @@ build_executable(hicn_light_tests DEPENDS gtest ${LIBHICNCTRL_STATIC} ${LIBHICN_LIGHT_SHARED} COMPONENT ${HICN_LIGHT} DEFINITIONS "${COMPILER_DEFINITIONS}" + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) add_test_internal(hicn_light_tests) diff --git a/hicn-light/src/hicn/test/test-bitmap.cc b/hicn-light/src/hicn/test/test-bitmap.cc deleted file mode 100644 index 1fd21a1bb..000000000 --- a/hicn-light/src/hicn/test/test-bitmap.cc +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> -#include <netinet/in.h> - -extern "C" { -#define WITH_TESTS -#include <hicn/util/bitmap.h> -} - -#define DEFAULT_SIZE 10 - -class BitmapTest : public ::testing::Test { - protected: - BitmapTest() {} - - virtual ~BitmapTest() {} - - bitmap_t* bitmap; -}; - -/* - * TEST: bitmap allocation - */ -TEST_F(BitmapTest, BitmapAllocation) { - int rc; - - /* - * We take a value < 32 on purpose to avoid confusion on the choice of a 32 - * or 64 bit integer for storage - */ - size_t size_not_pow2 = DEFAULT_SIZE; - bitmap_init(bitmap, size_not_pow2, 0); - - /* - * Bitmap should have been allocated with a size rounded to the next power - * of 2 - */ - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL); - - /* By default, no element should be set */ - EXPECT_FALSE(bitmap_is_set(bitmap, 0)); - EXPECT_TRUE(bitmap_is_unset(bitmap, 0)); - - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL); - - EXPECT_FALSE(bitmap_is_set(bitmap, size_not_pow2 - 1)); - EXPECT_TRUE(bitmap_is_unset(bitmap, size_not_pow2 - 1)); - - /* Bitmap should not have been reallocated */ - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL); - - /* After setting a bit after the end, bitmap should have been reallocated */ - bitmap_set(bitmap, sizeof(bitmap[0]) * 8 - 1); - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL); - - /* After setting a bit after the end, bitmap should have been reallocated */ - rc = bitmap_set(bitmap, sizeof(bitmap[0]) * 8); - EXPECT_GE(rc, 0); - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2UL); - - rc = bitmap_set(bitmap, sizeof(bitmap[0]) * 8 + 1); - EXPECT_GE(rc, 0); - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2UL); - - bitmap_free(bitmap); - - size_t size_pow2 = 16; - - /* Limiting test for allocation size */ - bitmap_init(bitmap, size_pow2, 0); - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL); - - bitmap_free(bitmap); -} - -TEST_F(BitmapTest, BitmapSet) { - bitmap_init(bitmap, DEFAULT_SIZE, 0); - - bitmap_set(bitmap, 20); - EXPECT_TRUE(bitmap_is_set(bitmap, 20)); - EXPECT_FALSE(bitmap_is_unset(bitmap, 20)); - EXPECT_FALSE(bitmap_is_set(bitmap, 19)); - EXPECT_TRUE(bitmap_is_unset(bitmap, 19)); - - // Test edge cases (i.e. start and end of block) - off_t start_position = 0; - bitmap_set(bitmap, start_position); - EXPECT_TRUE(bitmap_is_set(bitmap, start_position)); - EXPECT_FALSE(bitmap_is_unset(bitmap, start_position)); - - off_t end_position = BITMAP_WIDTH(bitmap) - 1; - bitmap_set(bitmap, end_position); - EXPECT_TRUE(bitmap_is_set(bitmap, end_position)); - EXPECT_FALSE(bitmap_is_unset(bitmap, end_position)); - - bitmap_free(bitmap); -} - -TEST_F(BitmapTest, BitmapUnSet) { - bitmap_init(bitmap, DEFAULT_SIZE, 0); - - bitmap_set(bitmap, 20); - bitmap_set(bitmap, 19); - bitmap_unset(bitmap, 20); - EXPECT_FALSE(bitmap_is_set(bitmap, 20)); - EXPECT_TRUE(bitmap_is_unset(bitmap, 20)); - EXPECT_TRUE(bitmap_is_set(bitmap, 19)); - EXPECT_FALSE(bitmap_is_unset(bitmap, 19)); - - bitmap_free(bitmap); -} - -TEST_F(BitmapTest, BitmapSetTo) { - bitmap_init(bitmap, DEFAULT_SIZE, 0); - - bitmap_set_to(bitmap, 40); - EXPECT_TRUE(bitmap_is_set(bitmap, 20)); - EXPECT_TRUE(bitmap_is_set(bitmap, 21)); - EXPECT_TRUE(bitmap_is_unset(bitmap, 41)); - EXPECT_TRUE(bitmap_is_unset(bitmap, 42)); - - bitmap_free(bitmap); -} diff --git a/hicn-light/src/hicn/test/test-connection_table.cc b/hicn-light/src/hicn/test/test-connection_table.cc index d17de7c2c..171921b53 100644 --- a/hicn-light/src/hicn/test/test-connection_table.cc +++ b/hicn-light/src/hicn/test/test-connection_table.cc @@ -27,6 +27,7 @@ extern "C" { #define WITH_TESTS #include <hicn/core/connection_table.h> +#include <hicn/util/log.h> } #define CONNECTION_NAME "connection_name_test" @@ -275,7 +276,7 @@ TEST_F(ConnectionTableTest, GenerateConnNameExhaustion) { bool unable_to_allocate = false; // Force name exhaustion - int i, n_connections = 1 + USHRT_MAX; + int n_connections = 1 + USHRT_MAX; for (int i = 0; i <= n_connections; i++) { int rc = connection_table_get_random_name(conn_table_, conn_name); if (rc < 0) { diff --git a/hicn-light/src/hicn/test/test-ctrl.cc b/hicn-light/src/hicn/test/test-ctrl.cc index e24b47f27..f0d3e7c37 100644 --- a/hicn-light/src/hicn/test/test-ctrl.cc +++ b/hicn-light/src/hicn/test/test-ctrl.cc @@ -18,7 +18,7 @@ extern "C" { #include <hicn/util/log.h> #include <hicn/ctrl.h> -#include <hicn/config/parse.h> +#include <hicn/ctrl/parse.h> #include <hicn/ctrl/route.h> #include <hicn/util/sstrncpy.h> } @@ -27,7 +27,7 @@ class CtrlTest : public ::testing::Test { protected: CtrlTest() { log_conf.log_level = LOG_INFO; - s_ = hc_sock_create_forwarder(HICNLIGHT_NG); + s_ = hc_sock_create_forwarder(FORWARDER_TYPE_HICNLIGHT); } virtual ~CtrlTest() { hc_sock_free(s_); } @@ -40,7 +40,7 @@ class CtrlTest : public ::testing::Test { * Here we test the serialization of the commands i.e. from command * to message sent to the forwarder. */ - +#if 0 TEST_F(CtrlTest, AddValidListener) { std::string cmd = "add listener udp udp0 10.0.0.1 9695 eth0"; ASSERT_EQ(parse(cmd.c_str(), &command_), 0); @@ -81,7 +81,7 @@ TEST_F(CtrlTest, AddListenerInvalidLocalAddress) { hc_result_t *result = hc_listener_create_conf(s_, &command_.object.listener); bool success = hc_result_get_success(s_, result); - EXPECT_FALSE(success); + EXPECT_EQ(success, false); } TEST_F(CtrlTest, AddListenerEmptyLocalAddress) { @@ -193,4 +193,5 @@ TEST_F(CtrlTest, RouteNameOrID) { route.face_id = 1; snprintf(route.name, SYMBOLIC_NAME_LEN, "%s", "1test"); EXPECT_EQ(hc_route_validate(&route), -1); -}
\ No newline at end of file +} +#endif diff --git a/hicn-light/src/hicn/test/test-fib.cc b/hicn-light/src/hicn/test/test-fib.cc new file mode 100644 index 000000000..5db47415f --- /dev/null +++ b/hicn-light/src/hicn/test/test-fib.cc @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <netinet/in.h> + +extern "C" { +#define WITH_TESTS +#include <hicn/util/ip_address.h> +#include <hicn/config/configuration.h> +#include <hicn/core/forwarder.h> +#include <hicn/core/fib.h> +} + +/* + * TODO + * - test max_size + */ + +#define DEFAULT_SIZE 10 +#define ARRAY_SIZE(a) ((sizeof(a) / sizeof(*(a)))) + +class FibTest : public ::testing::Test { + protected: + FibTest() { fib = fib_create(NULL); } + virtual ~FibTest() { fib_free(fib); } + + configuration_t *configuration; + forwarder_t *forwarder; + fib_t *fib; +}; + +void _fib_add_prefix(fib_t *fib, const hicn_prefix_t *prefix) { + fib_entry_t *entry = + fib_entry_create(prefix, STRATEGY_TYPE_UNDEFINED, NULL, NULL); + fib_add(fib, entry); +} + +static const hicn_prefix_t p0010 = (hicn_prefix_t){ + .name = {.v6 = {.as_u64 = {0x1122334455667788, 0x9900aabbccddeeff}}}, + .len = 4}; + +/* TEST: Fib allocation and initialization */ +TEST_F(FibTest, FibAddOne) { + /* Empty fib should be valid */ + + const hicn_prefix_t *empty_prefix_array[] = {}; + bool empty_used_array[] = {}; + EXPECT_TRUE(fib_is_valid(fib)); + EXPECT_TRUE(fib_check_preorder(fib, empty_prefix_array, empty_used_array)); + + const hicn_prefix_t *prefix_array[] = {&p0010}; + bool used_array[] = {true}; + + for (unsigned i = 0; i < ARRAY_SIZE(prefix_array); i++) { + if (!used_array[i]) continue; + _fib_add_prefix(fib, prefix_array[i]); + } + + fib_dump(fib); + + EXPECT_TRUE(fib_is_valid(fib)); + EXPECT_TRUE(fib_check_preorder(fib, prefix_array, used_array)); + + /* Check that free indices and bitmaps are correctly updated */ +} diff --git a/hicn-light/src/hicn/test/test-interest_manifest.cc b/hicn-light/src/hicn/test/test-interest_manifest.cc deleted file mode 100644 index 6408a3f2a..000000000 --- a/hicn-light/src/hicn/test/test-interest_manifest.cc +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> - -extern "C" { -#include <hicn/core/interest_manifest.h> -} - -static constexpr size_t WORD_SIZE = 32; - -class InterestManifestTest : public ::testing::Test { - protected: - InterestManifestTest() {} - virtual ~InterestManifestTest() {} -}; - -TEST_F(InterestManifestTest, OneWordBitmapUpdate) { - u32 initial_bitmap[1]; - u32 curr_bitmap[1] = {0}; - initial_bitmap[0] = 0x00000b07; // 000000000000000000000101100000111 - - // Consume first 4 'one' bits (i.e. suffixes), reaching position 9 - int pos = 0, max_suffixes = 4; - pos = interest_manifest_update_bitmap(initial_bitmap, curr_bitmap, pos, - WORD_SIZE, max_suffixes); - EXPECT_EQ(pos, 9); - EXPECT_EQ(curr_bitmap[0], 0x00000107); - - // Consume the remaining 2 'one' bits, reaching end of bitmap - u32 curr_bitmap2[1] = {0}; - pos = interest_manifest_update_bitmap(initial_bitmap, curr_bitmap2, pos, - WORD_SIZE, max_suffixes); - EXPECT_EQ(pos, WORD_SIZE); - EXPECT_EQ(curr_bitmap2[0], 0x00000a00); - - // Consume all suffixes at once - u32 curr_bitmap3[1] = {0}; - max_suffixes = 16; - pos = interest_manifest_update_bitmap(initial_bitmap, curr_bitmap3, 0, - WORD_SIZE, max_suffixes); - EXPECT_EQ(pos, WORD_SIZE); - EXPECT_EQ(curr_bitmap3[0], initial_bitmap[0]); -} - -TEST_F(InterestManifestTest, TwoWordBitmapUpdate) { - u32 initial_bitmap[2]; - initial_bitmap[0] = 0x00000b07; - initial_bitmap[1] = 0x00000b07; - // -> 100000000000000000000101100000111000000000000000000000101100000111 - - int expected_pos[] = {34, 64}; - u32 expected_bitmap[][2] = {{0x00000b07, 0x00000003}, {0x0, 0x00000b04}}; - - // Loop to consume all suffixes - int pos = 0, max_suffixes = 8, i = 0, len = WORD_SIZE * 2; - while (pos != len) { - u32 curr_bitmap[2] = {0}; - pos = interest_manifest_update_bitmap(initial_bitmap, curr_bitmap, pos, len, - max_suffixes); - - EXPECT_EQ(pos, expected_pos[i]); - EXPECT_EQ(curr_bitmap[0], expected_bitmap[i][0]); - EXPECT_EQ(curr_bitmap[1], expected_bitmap[i][1]); - i++; - } -}
\ No newline at end of file diff --git a/hicn-light/src/hicn/test/test-khash.cc b/hicn-light/src/hicn/test/test-khash.cc deleted file mode 100644 index f437f8858..000000000 --- a/hicn-light/src/hicn/test/test-khash.cc +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> -#include <netinet/in.h> - -extern "C" { -#include <hicn/util/khash.h> -} - -KHASH_MAP_INIT_INT(int, unsigned char) - -typedef struct { - unsigned key; - unsigned char val; -} int_unpack_t; - -typedef struct { - unsigned key; - unsigned char val; -} __attribute__((__packed__)) int_packed_t; - -#define hash_eq(a, b) ((a).key == (b).key) -#define hash_func(a) ((a).key) - -KHASH_INIT(iun, int_unpack_t, char, 0, hash_func, hash_eq) -KHASH_INIT(ipk, int_packed_t, char, 0, hash_func, hash_eq) - -class KHashTest : public ::testing::Test { - protected: - KHashTest() {} - - virtual ~KHashTest() { - // You can do clean-up work that doesn't throw exceptions here. - } - - // If the constructor and destructor are not enough for setting up - // and cleaning up each test, you can define the following methods: - - virtual void SetUp() { khash = kh_init(int); } - - virtual void TearDown() { kh_destroy(int, khash); } - khash_t(int) * khash; -}; - -TEST_F(KHashTest, KhashIntSize) { - int ret; - int k; - int size = kh_size(khash); - - EXPECT_EQ(size, 0); - k = kh_put(int, khash, 10, &ret); - if (ret == 1) { - kh_val(khash, k) = 10; - } - size = kh_size(khash); - EXPECT_EQ(size, 1); -} - -TEST_F(KHashTest, KhashIntPut) { - int ret; - int k; - k = kh_put(int, khash, 10, &ret); - if (ret == 1) { - kh_val(khash, k) = 10; - } - int size = kh_size(khash); - EXPECT_EQ(size, 1); - k = kh_put(int, khash, 20, &ret); - if (ret == 1) { - kh_val(khash, k) = 20; - } - size = kh_size(khash); - EXPECT_EQ(size, 2); -} - -TEST_F(KHashTest, KhashCheckValue) { - int ret; - int k; - k = kh_put(int, khash, 10, &ret); - if (ret == 1) { - kh_val(khash, k) = 100; - } - k = kh_put(int, khash, 20, &ret); - if (ret == 1) { - kh_val(khash, k) = 200; - } - - k = kh_put(int, khash, 10, &ret); - int val = -1; - if (!ret) val = kh_val(khash, k); - EXPECT_EQ(val, 100); - - k = kh_put(int, khash, 20, &ret); - val = -1; - if (!ret) val = kh_val(khash, k); - EXPECT_EQ(val, 200); -} - -// Check that there are no collisions in case of same key hash -typedef struct { - int x; -} Key; -#define hash_key(key) 1 // Hash is always 1 to simulate collisions -#define key_hash_eq(a, b) (a->x == b->x) // Function used in case of collisions -KHASH_INIT(test_map, const Key *, unsigned, 1, hash_key, key_hash_eq); - -TEST_F(KHashTest, Collisions) { - int ret; - khiter_t k; - - kh_test_map_t *map = kh_init(test_map); - Key key1 = {.x = 10}; - Key key2 = {.x = 11}; - - k = kh_put_test_map(map, &key1, &ret); - EXPECT_EQ(ret, 1); - kh_val(map, k) = 15; - - k = kh_put_test_map(map, &key2, &ret); - EXPECT_EQ(ret, 1); - kh_val(map, k) = 27; - - k = kh_get_test_map(map, &key1); - ASSERT_NE(k, kh_end(map)); - unsigned val = kh_val(map, k); - EXPECT_EQ(val, 15u); - - k = kh_get_test_map(map, &key2); - ASSERT_NE(k, kh_end(map)); - val = kh_val(map, k); - EXPECT_EQ(val, 27u); - - kh_destroy_test_map(map); -} diff --git a/hicn-light/src/hicn/test/test-listener_table.cc b/hicn-light/src/hicn/test/test-listener_table.cc index b2ed0c276..f4af02ee1 100644 --- a/hicn-light/src/hicn/test/test-listener_table.cc +++ b/hicn-light/src/hicn/test/test-listener_table.cc @@ -27,6 +27,7 @@ extern "C" { #define WITH_TESTS #include <hicn/core/listener_table.h> +#include <hicn/util/log.h> } #define LISTENER_NAME "listener_name_test" @@ -217,7 +218,6 @@ TEST_F(ListenerTableTest, Iterate) { listener_2->key = key_2; // Iterate over the listener table and count the listeners - listener_t *l; int count = 0; listener_table_foreach(listener_table_, l, { count++; }); EXPECT_EQ(count, 2); diff --git a/hicn-light/src/hicn/test/test-local_prefixes.cc b/hicn-light/src/hicn/test/test-local_prefixes.cc index 80eb46501..52b1c746e 100644 --- a/hicn-light/src/hicn/test/test-local_prefixes.cc +++ b/hicn-light/src/hicn/test/test-local_prefixes.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -28,7 +28,6 @@ extern "C" { #define WITH_TESTS #include <hicn/strategies/local_prefixes.h> #include <hicn/core/strategy.h> -#include <hicn/core/name.h> } const char *name_str1 = "b001::0"; @@ -51,53 +50,65 @@ class LocalPrefixesTest : public ::testing::Test { }; TEST_F(LocalPrefixesTest, LocalPrefixesAddName) { + int rc; local_prefixes_t *lp = create_local_prefixes(); EXPECT_FALSE(lp == nullptr); - ip_address_t result; - inet_pton(AF_INET6, name_str1, (struct in6_addr *)&result); - Name name1; - name_CreateFromAddress(&name1, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str2, (struct in6_addr *)&result); - Name name2; - name_CreateFromAddress(&name2, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str3, (struct in6_addr *)&result); - Name name3; - name_CreateFromAddress(&name3, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str4, (struct in6_addr *)&result); - Name name4; - name_CreateFromAddress(&name4, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str5, (struct in6_addr *)&result); - Name name5; - name_CreateFromAddress(&name5, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str6, (struct in6_addr *)&result); - Name name6; - name_CreateFromAddress(&name6, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str7, (struct in6_addr *)&result); - Name name7; - name_CreateFromAddress(&name7, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str8, (struct in6_addr *)&result); - Name name8; - name_CreateFromAddress(&name8, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str9, (struct in6_addr *)&result); - Name name9; - name_CreateFromAddress(&name9, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str10, (struct in6_addr *)&result); - Name name10; - name_CreateFromAddress(&name10, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str11, (struct in6_addr *)&result); - Name name11; - name_CreateFromAddress(&name11, AF_INET6, result, 128); + hicn_ip_address_t result = IP_ADDRESS_EMPTY; + hicn_ip_address_pton(name_str1, &result); + hicn_prefix_t name1; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name1); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str2, &result); + hicn_prefix_t name2; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name2); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str3, &result); + hicn_prefix_t name3; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name3); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str4, &result); + hicn_prefix_t name4; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name4); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str5, &result); + hicn_prefix_t name5; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name5); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str6, &result); + hicn_prefix_t name6; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name6); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str7, &result); + hicn_prefix_t name7; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name7); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str8, &result); + hicn_prefix_t name8; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name8); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str9, &result); + hicn_prefix_t name9; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name9); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str10, &result); + hicn_prefix_t name10; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name10); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str11, &result); + hicn_prefix_t name11; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name11); + EXPECT_EQ(rc, 0); local_prefixes_add_prefix(lp, &name1); EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)1); @@ -142,29 +153,34 @@ TEST_F(LocalPrefixesTest, LocalPrefixesAddName) { } TEST_F(LocalPrefixesTest, LocalPrefixesAddPrefixes) { + int rc; local_prefixes_t *lp = create_local_prefixes(); EXPECT_FALSE(lp == nullptr); - ip_address_t result; + hicn_ip_address_t result; local_prefixes_t *lp1 = create_local_prefixes(); EXPECT_FALSE(lp1 == nullptr); - inet_pton(AF_INET6, name_str1, (struct in6_addr *)&result); - Name name1; - name_CreateFromAddress(&name1, AF_INET6, result, 128); + hicn_ip_address_pton(name_str1, &result); + hicn_prefix_t name1; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name1); + EXPECT_EQ(rc, 0); - inet_pton(AF_INET6, name_str2, (struct in6_addr *)&result); - Name name2; - name_CreateFromAddress(&name2, AF_INET6, result, 128); + hicn_ip_address_pton(name_str2, &result); + hicn_prefix_t name2; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name2); + EXPECT_EQ(rc, 0); - inet_pton(AF_INET6, name_str3, (struct in6_addr *)&result); - Name name3; - name_CreateFromAddress(&name3, AF_INET6, result, 128); + hicn_ip_address_pton(name_str3, &result); + hicn_prefix_t name3; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name3); + EXPECT_EQ(rc, 0); - inet_pton(AF_INET6, name_str4, (struct in6_addr *)&result); - Name name4; - name_CreateFromAddress(&name4, AF_INET6, result, 128); + hicn_ip_address_pton(name_str4, &result); + hicn_prefix_t name4; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name4); + EXPECT_EQ(rc, 0); local_prefixes_add_prefix(lp1, &name1); local_prefixes_add_prefix(lp1, &name2); @@ -182,33 +198,40 @@ TEST_F(LocalPrefixesTest, LocalPrefixesAddPrefixes) { local_prefixes_t *lp2 = create_local_prefixes(); EXPECT_FALSE(lp2 == nullptr); - inet_pton(AF_INET6, name_str5, (struct in6_addr *)&result); - Name name5; - name_CreateFromAddress(&name5, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str6, (struct in6_addr *)&result); - Name name6; - name_CreateFromAddress(&name6, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str7, (struct in6_addr *)&result); - Name name7; - name_CreateFromAddress(&name7, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str8, (struct in6_addr *)&result); - Name name8; - name_CreateFromAddress(&name8, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str9, (struct in6_addr *)&result); - Name name9; - name_CreateFromAddress(&name9, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str10, (struct in6_addr *)&result); - Name name10; - name_CreateFromAddress(&name10, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str11, (struct in6_addr *)&result); - Name name11; - name_CreateFromAddress(&name11, AF_INET6, result, 128); + hicn_ip_address_pton(name_str5, &result); + hicn_prefix_t name5; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name5); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str6, &result); + hicn_prefix_t name6; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name6); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str7, &result); + hicn_prefix_t name7; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name7); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str8, &result); + hicn_prefix_t name8; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name8); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str9, &result); + hicn_prefix_t name9; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name9); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str10, &result); + hicn_prefix_t name10; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name10); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str11, &result); + hicn_prefix_t name11; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name11); + EXPECT_EQ(rc, 0); local_prefixes_add_prefix(lp2, &name5); local_prefixes_add_prefix(lp2, &name6); diff --git a/hicn-light/src/hicn/test/test-msgbuf_pool.cc b/hicn-light/src/hicn/test/test-msgbuf_pool.cc index e9c8e6424..0a78a7a5d 100644 --- a/hicn-light/src/hicn/test/test-msgbuf_pool.cc +++ b/hicn-light/src/hicn/test/test-msgbuf_pool.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -100,7 +100,7 @@ TEST_F(MsgbufPoolTest, AcquireMsgbuf) { // Get msgbuf from msgbuf_pool off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf); - msgbuf->type = MSGBUF_TYPE_COMMAND; + msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND); EXPECT_NE(msgbuf, nullptr); EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0); @@ -119,7 +119,7 @@ TEST_F(MsgbufPoolTest, ReleaseMsgbuf) { // Get msgbuf from msgbuf_pool off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf); - msgbuf->type = MSGBUF_TYPE_COMMAND; + msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND); EXPECT_NE(msgbuf, nullptr); EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0); @@ -137,7 +137,7 @@ TEST_F(MsgbufPoolTest, ReleaseNotAcquiredMsgbuf) { // Get valid msgbuf from msgbuf_pool off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf); - msgbuf->type = MSGBUF_TYPE_COMMAND; + msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND); EXPECT_NE(msgbuf, nullptr); EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0); @@ -157,7 +157,7 @@ TEST_F(MsgbufPoolTest, MultipleAcquireAndReleaseMsgbuf) { // Get msgbuf from msgbuf_pool off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf); - msgbuf->type = MSGBUF_TYPE_COMMAND; + msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND); EXPECT_NE(msgbuf, nullptr); EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0); @@ -177,7 +177,7 @@ TEST_F(MsgbufPoolTest, MultipleAcquireAndReleaseMsgbuf) { TEST_F(MsgbufPoolTest, CloneMsgbuf) { msgbuf_t *msgbuf = NULL; off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf); - msgbuf->type = MSGBUF_TYPE_COMMAND; + msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND); EXPECT_NE(msgbuf, nullptr); EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0); diff --git a/hicn-light/src/hicn/test/test-packet_cache.cc b/hicn-light/src/hicn/test/test-packet_cache.cc index 0b4b214f0..76fdb4516 100644 --- a/hicn-light/src/hicn/test/test-packet_cache.cc +++ b/hicn-light/src/hicn/test/test-packet_cache.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -31,8 +31,6 @@ static constexpr unsigned MSGBUF_ID = 0; static constexpr unsigned MSGBUF_ID_2 = 1; static constexpr unsigned MSGBUF_ID_3 = 2; static constexpr unsigned FIVE_SECONDS = 5000; -static constexpr unsigned IPV4_LEN = 32; -static constexpr unsigned IPV6_LEN = 128; static constexpr int N_OPS = 50000; @@ -40,39 +38,50 @@ class PacketCacheTest : public ::testing::Test { protected: PacketCacheTest() { pkt_cache = pkt_cache_create(CS_SIZE); - name = (Name *)malloc(sizeof(Name)); - name_CreateFromAddress(name, AF_INET, IPV4_ANY, IPV4_LEN); + int rc = hicn_name_create_from_ip_address(IPV4_ANY, 0, &name); + EXPECT_EQ(rc, 0); msgbuf_pool = msgbuf_pool_create(); - msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, name); + msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &name); } virtual ~PacketCacheTest() { - free(name); msgbuf_pool_free(msgbuf_pool); pkt_cache_free(pkt_cache); } msgbuf_t *msgbuf_create(msgbuf_pool_t *msgbuf_pool, unsigned conn_id, - Name *name, + hicn_name_t *name, std::optional<Ticks> lifetime = FIVE_SECONDS) { msgbuf_t *msgbuf; msgbuf_pool_get(msgbuf_pool, &msgbuf); msgbuf->connection_id = conn_id; - name_Copy(name, msgbuf_get_name(msgbuf)); - hicn_packet_init_header(HF_INET6_TCP, - (hicn_header_t *)msgbuf_get_packet(msgbuf)); + msgbuf_set_name(msgbuf, name); + + hicn_packet_set_format(msgbuf_get_pkbuf(msgbuf), + HICN_PACKET_FORMAT_IPV6_TCP); + hicn_packet_set_type(msgbuf_get_pkbuf(msgbuf), HICN_PACKET_TYPE_INTEREST); + + hicn_packet_buffer_t *pkbuf = msgbuf_get_pkbuf(msgbuf); + hicn_packet_set_buffer(pkbuf, msgbuf->packet, MTU, 0); + + int rc = hicn_packet_init_header(msgbuf_get_pkbuf(msgbuf), 0); + EXPECT_EQ(rc, 0); + + // Same as 'msgbuf_set_data_expiry_time', + // it would write in the same field msgbuf_set_interest_lifetime(msgbuf, *lifetime); return msgbuf; } - Name get_name_from_prefix(const char *prefix_str) { - ip_address_t prefix; + hicn_name_t get_name_from_prefix(const char *prefix_str) { + hicn_ip_address_t prefix; inet_pton(AF_INET6, prefix_str, (struct in6_addr *)&prefix); - Name name; - name_CreateFromAddress(&name, AF_INET6, prefix, IPV6_LEN); + hicn_name_t name; + int rc = hicn_name_create_from_ip_address(prefix, 0, &name); + EXPECT_EQ(rc, 0); return name; } @@ -80,39 +89,33 @@ class PacketCacheTest : public ::testing::Test { pkt_cache_t *pkt_cache; pkt_cache_entry_t *entry = nullptr; msgbuf_pool_t *msgbuf_pool; - Name *name; + hicn_name_t name; msgbuf_t *msgbuf; }; TEST_F(PacketCacheTest, LowLevelOperations) { - int rc; kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix(); - NameBitvector *prefix = name_GetContentName(name); + const hicn_name_prefix_t *prefix = hicn_name_get_prefix(&name); _add_suffix(prefix_to_suffixes, prefix, 1, 11); _add_suffix(prefix_to_suffixes, prefix, 2, 22); - unsigned id = _get_suffix(prefix_to_suffixes, prefix, 1, &rc); - EXPECT_EQ(rc, KH_FOUND); - EXPECT_EQ(id, 11); + unsigned id = _get_suffix(prefix_to_suffixes, prefix, 1); + EXPECT_EQ(id, 11UL); - id = _get_suffix(prefix_to_suffixes, prefix, 2, &rc); - EXPECT_EQ(rc, KH_FOUND); - EXPECT_EQ(id, 22); + id = _get_suffix(prefix_to_suffixes, prefix, 2); + EXPECT_EQ(id, 22UL); - id = _get_suffix(prefix_to_suffixes, prefix, 5, &rc); - EXPECT_EQ(rc, KH_NOT_FOUND); - EXPECT_EQ(id, -1); + id = _get_suffix(prefix_to_suffixes, prefix, 5); + EXPECT_EQ(id, HICN_INVALID_SUFFIX); _add_suffix(prefix_to_suffixes, prefix, 5, 55); - id = _get_suffix(prefix_to_suffixes, prefix, 5, &rc); - EXPECT_EQ(rc, KH_FOUND); - EXPECT_EQ(id, 55); + id = _get_suffix(prefix_to_suffixes, prefix, 5); + EXPECT_EQ(id, 55UL); _remove_suffix(prefix_to_suffixes, prefix, 2); _add_suffix(prefix_to_suffixes, prefix, 2, 222); - id = _get_suffix(prefix_to_suffixes, prefix, 2, &rc); - EXPECT_EQ(rc, KH_FOUND); - EXPECT_EQ(id, 222); + id = _get_suffix(prefix_to_suffixes, prefix, 2); + EXPECT_EQ(id, 222UL); _prefix_map_free(prefix_to_suffixes); } @@ -133,15 +136,17 @@ TEST_F(PacketCacheTest, CreatePacketCache) { TEST_F(PacketCacheTest, AddPacketCacheEntry) { // Add entry to the packet cache - entry = pkt_cache_allocate(pkt_cache, name); + entry = pkt_cache_allocate(pkt_cache); EXPECT_NE(entry, nullptr); + entry->name = name; ASSERT_EQ(pkt_cache_get_size(pkt_cache), 1u); + pkt_cache_add_to_index(pkt_cache, entry); // Get entry by name pkt_cache_lookup_t lookup_result; off_t entry_id; - pkt_cache_entry_t *entry = pkt_cache_lookup(pkt_cache, name, msgbuf_pool, - &lookup_result, &entry_id, true); + pkt_cache_lookup(pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, + true); EXPECT_NE(lookup_result, PKT_CACHE_LU_NONE); } @@ -165,7 +170,7 @@ TEST_F(PacketCacheTest, GetPIT) { TEST_F(PacketCacheTest, LookupEmpty) { pkt_cache_lookup_t lookup_result; off_t entry_id; - pkt_cache_entry_t *entry = pkt_cache_lookup(pkt_cache, name, msgbuf_pool, + pkt_cache_entry_t *entry = pkt_cache_lookup(pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_NONE); @@ -174,15 +179,17 @@ TEST_F(PacketCacheTest, LookupEmpty) { TEST_F(PacketCacheTest, AddEntryAndLookup) { // Add entry to the packet cache - entry = pkt_cache_allocate(pkt_cache, name); + entry = pkt_cache_allocate(pkt_cache); + entry->name = name; entry->entry_type = PKT_CACHE_PIT_TYPE; ASSERT_NE(entry, nullptr); + pkt_cache_add_to_index(pkt_cache, entry); // Perform lookup pkt_cache_lookup_t lookup_result; off_t entry_id; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_TRUE(lookup_result == PKT_CACHE_LU_INTEREST_NOT_EXPIRED || lookup_result == PKT_CACHE_LU_INTEREST_EXPIRED); @@ -192,7 +199,7 @@ TEST_F(PacketCacheTest, AddEntryAndLookup) { TEST_F(PacketCacheTest, AddToPIT) { // Check if entry properly created - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); ASSERT_NE(entry, nullptr); EXPECT_EQ(entry->entry_type, PKT_CACHE_PIT_TYPE); EXPECT_TRUE(pit_entry_ingress_contains(&entry->u.pit_entry, CONN_ID)); @@ -203,7 +210,7 @@ TEST_F(PacketCacheTest, AddToPIT) { pkt_cache_lookup_t lookup_result; off_t entry_id; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } @@ -229,14 +236,14 @@ TEST_F(PacketCacheTest, AddToCS) { // Check if hashtable correctly updated pkt_cache_lookup_t lookup_result; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_DATA_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } TEST_F(PacketCacheTest, PitToCS) { // Prepare PIT entry - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry); ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u); ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u); @@ -261,7 +268,7 @@ TEST_F(PacketCacheTest, PitToCS) { // Check if hashtable correctly updated pkt_cache_lookup_t lookup_result; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_DATA_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } @@ -286,18 +293,19 @@ TEST_F(PacketCacheTest, CsToPIT) { // Check if hashtable correctly updated pkt_cache_lookup_t lookup_result; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } TEST_F(PacketCacheTest, UpdateInPIT) { // Prepare PIT entry - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry); - Name new_name; - name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN); + hicn_name_t new_name; + int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name); + EXPECT_EQ(rc, 0); msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name); // Check if entry properly updated @@ -311,7 +319,7 @@ TEST_F(PacketCacheTest, UpdateInPIT) { // Check if hashtable correctly updated pkt_cache_lookup_t lookup_result; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } @@ -322,8 +330,9 @@ TEST_F(PacketCacheTest, UpdateInCS) { pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID); off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry); - Name new_name; - name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN); + hicn_name_t new_name; + int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name); + EXPECT_EQ(rc, 0); msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name); // Check if entry properly updated @@ -338,18 +347,18 @@ TEST_F(PacketCacheTest, UpdateInCS) { // Check if hashtable correctly updated pkt_cache_lookup_t lookup_result; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_DATA_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } TEST_F(PacketCacheTest, RemoveFromPIT) { // Prepare PIT entry - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u); ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u); - pkt_cache_pit_remove_entry(pkt_cache, entry, name); + pkt_cache_pit_remove_entry(pkt_cache, entry); ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u); ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u); @@ -357,7 +366,7 @@ TEST_F(PacketCacheTest, RemoveFromPIT) { pkt_cache_lookup_t lookup_result; off_t entry_id; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_NONE); EXPECT_EQ(lu_entry, nullptr); } @@ -383,15 +392,16 @@ TEST_F(PacketCacheTest, RemoveFromCS) { pkt_cache_lookup_t lookup_result; off_t entry_id; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_NONE); EXPECT_EQ(lu_entry, nullptr); } TEST_F(PacketCacheTest, AddTwoEntriesToCS) { // Prepare another msgbuf - Name new_name; - name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN); + hicn_name_t new_name; + int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name); + EXPECT_EQ(rc, 0); msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name); pkt_cache_entry_t *entry_1 = @@ -412,16 +422,17 @@ TEST_F(PacketCacheTest, AddTwoEntriesToCS) { TEST_F(PacketCacheTest, AggregateInPIT) { // Prepare another msgbuf - Name new_name; - name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN); + hicn_name_t new_name; + int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name); + EXPECT_EQ(rc, 0); msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name); // Check if entry properly created (use sleep to get an updated ts) - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); Ticks old_lifetime = entry->expire_ts; std::this_thread::sleep_for(std::chrono::milliseconds(100)); bool is_aggregated = - pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf, name); + pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf, &name); Ticks new_lifetime = entry->expire_ts; ASSERT_NE(entry, nullptr); @@ -433,23 +444,24 @@ TEST_F(PacketCacheTest, AggregateInPIT) { pkt_cache_lookup_t lookup_result; off_t entry_id; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } TEST_F(PacketCacheTest, RetransmissionInPIT) { // Prepare another msgbuf (using same connection ID) - Name new_name; - name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN); + hicn_name_t new_name; + int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name); + EXPECT_EQ(rc, 0); msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &new_name); // Check if entry properly created (use sleep to get an updated ts) - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); Ticks old_lifetime = entry->expire_ts; std::this_thread::sleep_for(std::chrono::milliseconds(100)); bool is_aggregated = - pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf, name); + pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf, &name); Ticks new_lifetime = entry->expire_ts; ASSERT_NE(entry, nullptr); @@ -461,17 +473,17 @@ TEST_F(PacketCacheTest, RetransmissionInPIT) { pkt_cache_lookup_t lookup_result; off_t entry_id; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } TEST_F(PacketCacheTest, LookupExpiredInterest) { // Prepare msgbuf with 0 as interest lifetime - msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, name, 0); + msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &name, 0); // Add to PIT - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); ASSERT_NE(entry, nullptr); // Wait to make the interest expire @@ -479,14 +491,14 @@ TEST_F(PacketCacheTest, LookupExpiredInterest) { pkt_cache_lookup_t lookup_result; off_t entry_id; - pkt_cache_lookup(pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, + pkt_cache_lookup(pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_EXPIRED); } TEST_F(PacketCacheTest, LookupExpiredData) { // Prepare msgbuf with 0 as data expiry time - msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, name, 0); + msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &name, 0); // Add to CS pkt_cache_entry_t *entry = @@ -498,25 +510,27 @@ TEST_F(PacketCacheTest, LookupExpiredData) { pkt_cache_lookup_t lookup_result; off_t entry_id; - pkt_cache_lookup(pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, + pkt_cache_lookup(pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_DATA_EXPIRED); } TEST_F(PacketCacheTest, GetStaleEntries) { // Add to CS a msgbuf with immediate expiration (i.e. stale) - msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, name, 0); + msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &name, 0); pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID); // Add to CS another msgbuf with immediate expiration (i.e. stale) - Name name_2; - name_CreateFromAddress(&name_2, AF_INET, IPV4_LOOPBACK, IPV4_LEN); + hicn_name_t name_2; + int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &name_2); + EXPECT_EQ(rc, 0); msgbuf_t *msgbuf_2 = msgbuf_create(msgbuf_pool, CONN_ID, &name_2, 0); pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf_2, MSGBUF_ID_2); // Add to CS a msgbuf with 5-seconds expiration (i.e. not stale) - Name name_3; - name_CreateFromAddress(&name_3, AF_INET6, IPV6_LOOPBACK, IPV6_LEN); + hicn_name_t name_3; + rc = hicn_name_create_from_ip_address(IPV6_LOOPBACK, 0, &name_3); + EXPECT_EQ(rc, 0); msgbuf_t *msgbuf_3 = msgbuf_create(msgbuf_pool, CONN_ID, &name_3, FIVE_SECONDS); pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf_3, MSGBUF_ID_3); @@ -526,17 +540,19 @@ TEST_F(PacketCacheTest, GetStaleEntries) { } TEST_F(PacketCacheTest, GetMultipleStaleEntries) { - ip_address_t addr; + hicn_ip_address_t addr; char name[30]; const int NUM_STALES = 10; + int rc; // Add to CS multiple msgbufs with immediate expiration (i.e. 0 seconds), // resulting in stale entries for (int i = 0; i < NUM_STALES; i++) { snprintf(name, 30, "b001::%d", i); inet_pton(AF_INET6, name, (struct in6_addr *)&addr); - Name name; - name_CreateFromAddress(&name, AF_INET6, addr, IPV6_LEN); + hicn_name_t name; + rc = hicn_name_create_from_ip_address(addr, 0, &name); + EXPECT_EQ(rc, 0); msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, i, &name, 0); pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, i); @@ -547,8 +563,9 @@ TEST_F(PacketCacheTest, GetMultipleStaleEntries) { for (int i = NUM_STALES; i < 15; i++) { snprintf(name, 30, "b001::%d", i); inet_pton(AF_INET6, name, (struct in6_addr *)&addr); - Name name; - name_CreateFromAddress(&name, AF_INET6, addr, IPV6_LEN); + hicn_name_t name; + rc = hicn_name_create_from_ip_address(addr, 0, &name); + EXPECT_EQ(rc, 0); msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, i, &name, FIVE_SECONDS); pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, i); @@ -559,23 +576,22 @@ TEST_F(PacketCacheTest, GetMultipleStaleEntries) { } TEST_F(PacketCacheTest, PerformanceDoubleLookup) { - Name tmp = get_name_from_prefix("b001::0"); + hicn_name_t tmp = get_name_from_prefix("b001::0"); auto elapsed_time_double = get_execution_time([&]() { kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix(); // Add to hash table for (int seq = 0; seq < N_OPS; seq++) { - name_SetSegment(&tmp, seq); - _add_suffix(prefix_to_suffixes, name_GetContentName(&tmp), - name_GetSegment(&tmp), name_GetSegment(&tmp)); + hicn_name_set_suffix(&tmp, seq); + _add_suffix(prefix_to_suffixes, hicn_name_get_prefix(&tmp), + hicn_name_get_suffix(&tmp), hicn_name_get_suffix(&tmp)); } // Read from hash table - int rc; for (int seq = 0; seq < N_OPS; seq++) { - name_SetSegment(&tmp, seq); - _get_suffix(prefix_to_suffixes, name_GetContentName(&tmp), seq, &rc); + hicn_name_set_suffix(&tmp, seq); + _get_suffix(prefix_to_suffixes, hicn_name_get_prefix(&tmp), seq); } _prefix_map_free(prefix_to_suffixes); @@ -584,24 +600,24 @@ TEST_F(PacketCacheTest, PerformanceDoubleLookup) { } TEST_F(PacketCacheTest, PerformanceCachedLookup) { - Name tmp = get_name_from_prefix("b001::0"); + hicn_name_t tmp = get_name_from_prefix("b001::0"); auto elapsed_time_single = get_execution_time([&]() { kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix(); kh_pkt_cache_suffix_t *suffixes = - _get_suffixes(prefix_to_suffixes, name_GetContentName(&tmp)); + _get_suffixes(prefix_to_suffixes, hicn_name_get_prefix(&tmp), true); // Add to hash table for (int seq = 0; seq < N_OPS; seq++) { - name_SetSegment(&tmp, seq); - __add_suffix(suffixes, name_GetSegment(&tmp), name_GetSegment(&tmp)); + hicn_name_set_suffix(&tmp, seq); + __add_suffix(suffixes, hicn_name_get_suffix(&tmp), + hicn_name_get_suffix(&tmp)); } // Read from hash table - int rc; for (int seq = 0; seq < N_OPS; seq++) { - name_SetSegment(&tmp, seq); - __get_suffix(suffixes, name_GetSegment(&tmp), &rc); + hicn_name_set_suffix(&tmp, seq); + __get_suffix(suffixes, hicn_name_get_suffix(&tmp)); } _prefix_map_free(prefix_to_suffixes); @@ -610,7 +626,7 @@ TEST_F(PacketCacheTest, PerformanceCachedLookup) { } TEST_F(PacketCacheTest, PerformanceCachedLookupRandom) { - Name tmp = get_name_from_prefix("b001::0"); + hicn_name_t tmp = get_name_from_prefix("b001::0"); // Prepare random sequence numbers std::random_device rd; @@ -622,19 +638,19 @@ TEST_F(PacketCacheTest, PerformanceCachedLookupRandom) { auto elapsed_time_single_rand = get_execution_time([&]() { kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix(); kh_pkt_cache_suffix_t *suffixes = - _get_suffixes(prefix_to_suffixes, name_GetContentName(&tmp)); + _get_suffixes(prefix_to_suffixes, hicn_name_get_prefix(&tmp), true); // Add to hash table for (int seq = 0; seq < N_OPS; seq++) { - name_SetSegment(&tmp, seqs[seq]); - __add_suffix(suffixes, name_GetSegment(&tmp), name_GetSegment(&tmp)); + hicn_name_set_suffix(&tmp, seqs[seq]); + __add_suffix(suffixes, hicn_name_get_suffix(&tmp), + hicn_name_get_suffix(&tmp)); } // Read from hash table - int rc; for (int seq = 0; seq < N_OPS; seq++) { - name_SetSegment(&tmp, seqs[seq]); - __get_suffix(suffixes, name_GetSegment(&tmp), &rc); + hicn_name_set_suffix(&tmp, seqs[seq]); + __get_suffix(suffixes, hicn_name_get_suffix(&tmp)); } _prefix_map_free(prefix_to_suffixes); @@ -643,17 +659,17 @@ TEST_F(PacketCacheTest, PerformanceCachedLookupRandom) { } TEST_F(PacketCacheTest, Clear) { - Name tmp_name1, tmp_name2; + hicn_name_t tmp_name1, tmp_name2; cs_t *cs = pkt_cache_get_cs(pkt_cache); // Create name and add to msgbuf pool - name_Copy(name, &tmp_name1); - name_SetSegment(&tmp_name1, 1); + hicn_name_copy(&tmp_name1, &name); + hicn_name_set_suffix(&tmp_name1, 1); msgbuf_t *tmp_msgbuf1 = msgbuf_create(msgbuf_pool, CONN_ID_2, &tmp_name1); // Create (another) name and add to msgbuf pool - name_Copy(name, &tmp_name2); - name_SetSegment(&tmp_name2, 2); + hicn_name_copy(&tmp_name2, &name); + hicn_name_set_suffix(&tmp_name2, 2); msgbuf_t *tmp_msgbuf2 = msgbuf_create(msgbuf_pool, CONN_ID_2, &tmp_name2); // Add to packet cache (2 entries in the CS, 1 in the PIT) @@ -665,7 +681,7 @@ TEST_F(PacketCacheTest, Clear) { ASSERT_EQ(pkt_cache_get_size(pkt_cache), 3u); ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u); ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 2u); - ASSERT_EQ(cs->num_entries, 2u); + ASSERT_EQ(cs->num_entries, 2); ASSERT_EQ(cs->stats.lru.countAdds, 2u); // Clear packet cache (i.e. remove content packets from packet cache): @@ -677,6 +693,6 @@ TEST_F(PacketCacheTest, Clear) { ASSERT_EQ(pkt_cache_get_size(pkt_cache), 1u); ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u); ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u); - ASSERT_EQ(cs->num_entries, 0u); + ASSERT_EQ(cs->num_entries, 0); ASSERT_EQ(cs->stats.lru.countAdds, 0u); -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/test/test-parser.cc b/hicn-light/src/hicn/test/test-parser.cc index 3a8d2cdb2..2e396b97d 100644 --- a/hicn-light/src/hicn/test/test-parser.cc +++ b/hicn-light/src/hicn/test/test-parser.cc @@ -17,7 +17,7 @@ extern "C" { #include <hicn/util/log.h> -#include <hicn/config/parse.h> +#include <hicn/ctrl/parse.h> } class ParserTest : public ::testing::Test { @@ -68,4 +68,4 @@ TEST_F(ParserTest, AddListenerInvalidPortString) { TEST_F(ParserTest, UnknownCommnad) { std::string cmd = "add face"; ASSERT_EQ(parse(cmd.c_str(), &command_), -1); -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/test/test-pool.cc b/hicn-light/src/hicn/test/test-pool.cc deleted file mode 100644 index 8cd891d6a..000000000 --- a/hicn-light/src/hicn/test/test-pool.cc +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> -#include <netinet/in.h> - -extern "C" { -#define WITH_TESTS -#include <hicn/util/pool.h> -} - -/* - * TODO - * - test max_size - */ - -#define DEFAULT_SIZE 10 - -class PoolTest : public ::testing::Test { - protected: - PoolTest() {} - virtual ~PoolTest() {} - - int *pool; -}; - -TEST_F(PoolTest, PoolAllocation) { - int rc; - - pool_init(pool, DEFAULT_SIZE, 0); - - size_t pool_size = next_pow2(DEFAULT_SIZE); - - EXPECT_EQ(pool_get_alloc_size(pool), pool_size); - - /* Check that free indices and bitmaps are correctly initialize */ - off_t *fi = pool_get_free_indices(pool); - EXPECT_EQ(vector_len(fi), pool_size); - EXPECT_EQ(fi[0], (long)(pool_size - 1)); - EXPECT_EQ(fi[pool_size - 1], 0); - - /* The allocated size of the underlying vector should be the next power of two - */ - EXPECT_EQ(vector_get_alloc_size(fi), pool_size); - - bitmap_t *fb = pool_get_free_bitmap(pool); - EXPECT_TRUE(bitmap_is_set(fb, 0)); - EXPECT_TRUE(bitmap_is_set(fb, pool_size - 2)); - EXPECT_TRUE(bitmap_is_set(fb, pool_size - 1)); - EXPECT_TRUE(bitmap_is_unset(fb, pool_size)); - - /* Getting elements from the pool should correctly update the free indices - * and bitmap */ - int *elt; - - rc = pool_get(pool, elt); - EXPECT_GE(rc, 0); - EXPECT_EQ(vector_len(fi), pool_size - 1); - EXPECT_TRUE(bitmap_is_unset(fb, 0)); - - rc = pool_get(pool, elt); - EXPECT_GE(rc, 0); - EXPECT_EQ(vector_len(fi), pool_size - 2); - EXPECT_TRUE(bitmap_is_unset(fb, 1)); - - for (unsigned i = 0; i < pool_size - 4; i++) { - rc = pool_get(pool, elt); - EXPECT_GE(rc, 0); - } - - rc = pool_get(pool, elt); - EXPECT_GE(rc, 0); - EXPECT_EQ(vector_len(fi), 1UL); - EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 2)); - - rc = pool_get(pool, elt); - EXPECT_GE(rc, 0); - EXPECT_EQ(vector_len(fi), 0UL); - EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 1)); - - /* - * Getting elements within the allocated range should not have triggered a - * resize - */ - EXPECT_EQ(pool_len(pool), pool_size); - - /* - * Getting elements once the allocated range has been exceeded should - * trigger a resize - */ - rc = pool_get(pool, elt); - EXPECT_GE(rc, 0); - - EXPECT_EQ(pool_get_alloc_size(pool), pool_size * 2); - - EXPECT_EQ(pool_len(pool), pool_size + 1); - - /* - * Doubling the size, we should have again pool_size elements free, minus 1 - */ - EXPECT_EQ(pool_get_free_indices_size(pool), pool_size - 1); - - /* - * NOTE: this is wrong as there has been a realloc and the old fi - * pointer is now invalid - */ - // EXPECT_EQ(vector_len(fi), pool_size - 1); - - /* And the bitmap should also be correctly modified */ - fb = pool_get_free_bitmap(pool); - EXPECT_TRUE(bitmap_is_unset(fb, pool_size)); - - /* Check that surrounding values are also correct */ - EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 1)); - EXPECT_TRUE(bitmap_is_set(fb, pool_size + 1)); - - /* Setting elements after should through */ - - /* Check that free indices and bitmaps are correctly updated */ - - pool_free(pool); -} - -TEST_F(PoolTest, PoolPut) { - pool_init(pool, DEFAULT_SIZE, 0); - - int *elt; - pool_get(pool, elt); - *elt = 10; - pool_put(pool, elt); - - pool_free(pool); -} - -TEST_F(PoolTest, PoolGetForceBitmapRealloc) { - const int N = 64; - int *elts[N]; - int *elt = NULL; - pool_init(pool, N, 0); - - for (int i = 0; i < N; i++) pool_get(pool, elts[i]); - pool_get(pool, elt); - - pool_free(pool); -} - -TEST_F(PoolTest, PoolGetAfterReleasing) { - int *elt1 = NULL, *elt2 = NULL, *tmp = NULL; - pool_init(pool, DEFAULT_SIZE, 0); - - // If two elements are requested... - off_t id1 = pool_get(pool, elt1); - pool_get(pool, tmp); - - // ...and the first one is released... - pool_put(pool, elt1); - - // ...requesting a new one should return - // the first one (that was freed) - off_t id2 = pool_get(pool, elt2); - EXPECT_EQ(id1, id2); - EXPECT_EQ(elt1, elt2); - - pool_free(pool); -} - -TEST_F(PoolTest, PoolGetMultipleElementsAfterReleasing) { - const int N = 2; - int *elts[N]; - pool_init(pool, N, 0); - - for (int i = 0; i < N; i++) pool_get(pool, elts[i]); - for (int i = 0; i < N; i++) pool_put(pool, elts[i]); - for (int i = 0; i < N; i++) pool_get(pool, elts[i]); - - pool_free(pool); -} diff --git a/hicn-light/src/hicn/test/test-ring.cc b/hicn-light/src/hicn/test/test-ring.cc deleted file mode 100644 index ab96d76c0..000000000 --- a/hicn-light/src/hicn/test/test-ring.cc +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> -#include <netinet/in.h> - -extern "C" { -#define WITH_TESTS -#include <hicn/util/ring.h> -} - -#define DEFAULT_SIZE 10UL - -class RingTest : public ::testing::Test { - protected: - RingTest() { ring_init(ring, DEFAULT_SIZE); } - virtual ~RingTest() { ring_free(ring); } - - int *ring = NULL; -}; - -/* TEST: Ring allocation and initialization */ -TEST_F(RingTest, RingAddOne) { - int val = -1; - /* Allocated size should be the next power of two */ - EXPECT_EQ(ring_get_size(ring), 0UL); - ring_add_value(ring, 1); - EXPECT_EQ(ring_get_size(ring), 1UL); - ring_get(ring, 0, &val); - EXPECT_EQ(val, 1); - EXPECT_EQ(ring_get_size(ring), 1UL); - ring_advance(ring, 1); - EXPECT_EQ(ring_get_size(ring), 0UL); -} - -TEST_F(RingTest, RingAddMany) { - size_t i = 0; - int val = -1; - size_t count = 0; - - /* Allocated size should be the next power of two */ - EXPECT_EQ(ring_get_size(ring), 0UL); - for (unsigned i = 0; i < DEFAULT_SIZE; i++) ring_add_value(ring, i); - EXPECT_EQ(ring_get_size(ring), DEFAULT_SIZE); - - count = 0; - ring_enumerate_n(ring, i, &val, 1, { - EXPECT_EQ(val, (int)(i)); - count++; - }); - EXPECT_EQ(count, 1UL); - - count = 0; - ring_enumerate_n(ring, i, &val, DEFAULT_SIZE, { - EXPECT_EQ(val, (int)(i)); - count++; - }); - EXPECT_EQ(count, DEFAULT_SIZE); - - count = 0; - ring_enumerate_n(ring, i, &val, DEFAULT_SIZE + 1, { - EXPECT_EQ(val, (int)(i)); - count++; - }); - EXPECT_EQ(count, DEFAULT_SIZE); - - // Drop one - ring_add_value(ring, DEFAULT_SIZE); - EXPECT_EQ(ring_get_size(ring), DEFAULT_SIZE); - - count = 0; - ring_enumerate_n(ring, i, &val, DEFAULT_SIZE, { - EXPECT_EQ(val, (int)(i + 1)); // all values shoud be shifted - count++; - }); - EXPECT_EQ(count, DEFAULT_SIZE); - - ring_advance(ring, DEFAULT_SIZE); - EXPECT_EQ(ring_get_size(ring), 0UL); -} diff --git a/hicn-light/src/hicn/test/test-strategy-replication.cc b/hicn-light/src/hicn/test/test-strategy-replication.cc index ab7dae1f7..2924173cb 100644 --- a/hicn-light/src/hicn/test/test-strategy-replication.cc +++ b/hicn-light/src/hicn/test/test-strategy-replication.cc @@ -152,7 +152,6 @@ TEST_F(StrategyReplicationTest, MultipleNexthops) { /* Retrieve candidate */ - unsigned nexthop; unsigned tests = 0; nexthops_foreach(nexthops, nexthop, { EXPECT_TRUE(nexthop == NEXTHOP_ID1 || nexthop == NEXTHOP_ID2); diff --git a/hicn-light/src/hicn/test/test-subscription.cc b/hicn-light/src/hicn/test/test-subscription.cc index f89254e67..5fd3ab57d 100644 --- a/hicn-light/src/hicn/test/test-subscription.cc +++ b/hicn-light/src/hicn/test/test-subscription.cc @@ -40,10 +40,10 @@ TEST_F(SubscriptionTest, SetTopic) { TEST_F(SubscriptionTest, GetObjectFromTopic) { hc_object_type_t object_type = object_from_topic(TOPIC_STRATEGY); - EXPECT_EQ(object_type, OBJECT_STRATEGY); + EXPECT_EQ(object_type, OBJECT_TYPE_STRATEGY); object_type = object_from_topic(TOPIC_FACE); - EXPECT_EQ(object_type, OBJECT_FACE); + EXPECT_EQ(object_type, OBJECT_TYPE_FACE); } TEST_F(SubscriptionTest, AddSubscription) { @@ -201,4 +201,4 @@ TEST_F(SubscriptionTest, GetConnectionsForSubscription) { subscription_table_get_connections_for_topic(subscriptions, TOPIC_FACE); EXPECT_EQ(vector_len(conn_ids), 1u); EXPECT_EQ(conn_ids[0], (unsigned)CONN_ID); -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/test/test-vector.cc b/hicn-light/src/hicn/test/test-vector.cc deleted file mode 100644 index dda71fd0c..000000000 --- a/hicn-light/src/hicn/test/test-vector.cc +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> - -extern "C" { -#include <hicn/util/vector.h> -} - -static constexpr size_t DEFAULT_SIZE = 10; -static constexpr size_t N_ELEMENTS = 5; - -class VectorTest : public ::testing::Test { - protected: - VectorTest() { vector_init(vector, DEFAULT_SIZE, 0); } - virtual ~VectorTest() { vector_free(vector); } - - int *vector = NULL; -}; - -TEST_F(VectorTest, VectorAllocateAndResize) { - // Allocated size should be the next power of two - EXPECT_EQ(vector_get_alloc_size(vector), 16UL); - - // Setting elements within the allocated size should not trigger a resize - vector_ensure_pos(vector, 15); - EXPECT_EQ(vector_get_alloc_size(vector), 16UL); - - // Setting elements after should through - vector_ensure_pos(vector, 16); - EXPECT_EQ(vector_get_alloc_size(vector), 32UL); -} - -TEST_F(VectorTest, VectorSize) { - EXPECT_EQ(vector_len(vector), 0); - - // Check size after pushing one element - vector_push(vector, 1); - EXPECT_EQ(vector_len(vector), 1); - - // Check size after pushing additional elements - vector_push(vector, 2); - vector_push(vector, 3); - EXPECT_EQ(vector_len(vector), 3); - - // Try adding multiple elements - const int n_elements_to_add = 5; - size_t expected_new_len = vector_len(vector) + n_elements_to_add; - for (int i = 0; i < n_elements_to_add; i++) vector_push(vector, i); - EXPECT_EQ(vector_len(vector), expected_new_len); -} - -TEST_F(VectorTest, VectorCheckValue) { - // Add elements - vector_push(vector, 109); - vector_push(vector, 200); - EXPECT_EQ(vector_at(vector, 0), 109); - EXPECT_EQ(vector_at(vector, 1), 200); - - // Update element - vector_set(vector, 1, 400); - EXPECT_EQ(vector_at(vector, 1), 400); - - // Add at last available position - size_t prev_size = vector_len(vector); - vector_set(vector, vector_len(vector) - 1, 123); - EXPECT_EQ(vector_at(vector, vector_len(vector) - 1), 123); - EXPECT_EQ(prev_size, vector_len(vector)) << "Size should not have changed"; -} - -TEST_F(VectorTest, RemoveElement) { - // Populate vector - for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(vector, i); - EXPECT_EQ(vector_len(vector), N_ELEMENTS); - for (size_t i = 0; i < vector_len(vector); i++) - EXPECT_EQ(vector_at(vector, i), (int)i); - - // Remove element - int value_to_remove = 3; - int num_removed = vector_remove_unordered(vector, value_to_remove); - - EXPECT_EQ(vector_len(vector), N_ELEMENTS - 1); - EXPECT_EQ(num_removed, 1); - for (size_t i = 0; i < vector_len(vector); i++) - EXPECT_NE(vector_at(vector, i), value_to_remove); -} - -TEST_F(VectorTest, RemoveNonExistingElement) { - // Push some initial values - vector_push(vector, 1); - vector_push(vector, 2); - vector_push(vector, 3); - EXPECT_EQ(vector_len(vector), 3); - - // Remove non-existing element - int num_removed = vector_remove_unordered(vector, 5); - EXPECT_EQ(num_removed, 0); - size_t prev_size = vector_len(vector); - EXPECT_EQ(prev_size, vector_len(vector)) << "Size should not have changed"; -} - -TEST_F(VectorTest, RemoveDuplicatedElement) { - // Populate vector - for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(vector, i); - EXPECT_EQ(vector_len(vector), N_ELEMENTS); - for (size_t i = 0; i < vector_len(vector); i++) - EXPECT_EQ(vector_at(vector, i), (int)i); - vector_set(vector, 0, 3); // Duplicate element - - // Remove (duplicated) elements - int value_to_remove = 3; - int num_removed = vector_remove_unordered(vector, value_to_remove); - - EXPECT_EQ(vector_len(vector), N_ELEMENTS - 2); - EXPECT_EQ(num_removed, 2); - for (size_t i = 0; i < vector_len(vector); i++) - EXPECT_NE(vector_at(vector, i), value_to_remove); -} - -TEST_F(VectorTest, Iterate) { - for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(vector, i); - - int count = 0; - int *elem; - vector_foreach(vector, elem, { EXPECT_EQ(*elem, count++); }); -} - -TEST_F(VectorTest, MultipleResize) { - // Use small vector (size=1) to force multiple realloc operations - int *small_vector; - vector_init(small_vector, 1, 0); - - for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(small_vector, i); - - for (size_t i = 0; i < N_ELEMENTS; i++) - EXPECT_EQ(vector_at(small_vector, i), (int)i); - - EXPECT_EQ(vector_len(small_vector), 5UL); - EXPECT_EQ(vector_get_alloc_size(small_vector), 8UL); - - vector_free(small_vector); -} - -TEST_F(VectorTest, MaxSize) { - const int max_size = 4; - - // Fill the vector until max size is reached - int *small_vector; - vector_init(small_vector, 2, max_size); - for (int i = 0; i < max_size; i++) vector_push(small_vector, i); - - // Try expanding or appending elements should fail - int rc = vector_ensure_pos(small_vector, max_size); - EXPECT_EQ(rc, -1); - rc = vector_push(small_vector, 123); - EXPECT_EQ(rc, -1); - - vector_free(small_vector); -} - -TEST_F(VectorTest, Contains) { - // No elements - EXPECT_EQ(vector_contains(vector, 1), false); - - // Push one element - vector_push(vector, 1); - EXPECT_EQ(vector_contains(vector, 1), true); - - // Update element - vector_set(vector, 0, 2); - EXPECT_EQ(vector_contains(vector, 1), false); - EXPECT_EQ(vector_contains(vector, 2), true); -} - -TEST_F(VectorTest, Remove) { - // Remove element at invalid position - int rc = vector_remove_at(vector, 2); - EXPECT_EQ(rc, -1); // Failure - - // Push two elements and remove the second one - vector_push(vector, 1); - vector_push(vector, 2); - rc = vector_remove_at(vector, 1); - EXPECT_EQ(rc, 0); // Success - EXPECT_EQ(vector_len(vector), 1); - - // Push another element: it should replace the previous one - vector_push(vector, 3); - EXPECT_EQ(vector_len(vector), 2); - EXPECT_EQ(vector_at(vector, 1), 3); -} - -TEST_F(VectorTest, RemoveInTheMiddle) { - for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(vector, i); - - // Remove element in central position - int rc = vector_remove_at(vector, 2); - EXPECT_EQ(rc, 0); // Success - EXPECT_EQ(vector_contains(vector, 2), false); - EXPECT_EQ(vector_len(vector), N_ELEMENTS - 1); - - // Check if elements have been shifted (preserving the order) - int expected[] = {0, 1, 3, 4}; - for (int i = 0; i < vector_len(vector); i++) - EXPECT_EQ(vector_at(vector, i), expected[i]); -} - -TEST_F(VectorTest, Reset) { - vector_push(vector, 1); - vector_push(vector, 2); - EXPECT_EQ(vector_len(vector), 2); - - vector_reset(vector); - EXPECT_EQ(vector_len(vector), 0); - - vector_push(vector, 5); - EXPECT_EQ(vector_len(vector), 1); - EXPECT_EQ(vector_contains(vector, 5), true); - EXPECT_EQ(vector_at(vector, 0), 5); -}
\ No newline at end of file diff --git a/hicn-light/src/hicn/test/test-hash.cc b/hicn-light/src/hicn/test/test_hash.cc index 3b03a08a6..c742aa248 100644 --- a/hicn-light/src/hicn/test/test-hash.cc +++ b/hicn-light/src/hicn/test/test_hash.cc @@ -187,8 +187,7 @@ TEST(HashTest, PerformanceComparisonBigStruct) { TEST(HashTest, CollisionsComparison) { small_struct_t small_struct = {0}; std::unordered_set<uint32_t> hashes; - int n_collisions_fnv = 0, n_collisions_jenkins = 0, n_collisions_murmur = 0, - n_collisions_xxhash = 0; + int n_collisions_fnv = 0, n_collisions_jenkins = 0; // FNV for (int i = 0; i < 10 * N_HASHES; i++) { |