diff options
Diffstat (limited to 'ctrl/facemgr/src/interfaces/hicn_light')
-rw-r--r-- | ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c | 218 |
1 files changed, 189 insertions, 29 deletions
diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c index 76edfec10..53aa95a75 100644 --- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c +++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c @@ -28,17 +28,23 @@ #include <hicn/util/log.h> #include <hicn/util/map.h> +#include "../../common.h" #include "../../interface.h" #define DEFAULT_ROUTE_COST 0 #define INTERVAL_MS 1000 +#define WITH_POLL + typedef enum { HL_STATE_UNDEFINED, - HL_STATE_CONNECTING, + HL_STATE_IDLE, + HL_STATE_ROUTES_SENT, + HL_STATE_ROUTES_RECEIVED, HL_STATE_FACES_SENT, - HL_STATE_DONE, + HL_STATE_FACES_RECEIVED, + HL_STATE_N } hl_state_t; typedef struct { @@ -50,31 +56,63 @@ typedef struct { /* Timer used to periodically poll the forwarder face and routing tables */ int poll_timer_fd; + hc_data_t * polled_routes; } hl_data_t; /* Forward declarations */ int hl_timeout(interface_t * interface, int fd, void * unused); +#ifdef WITH_POLL +int hl_process_state(interface_t * interface, int fd, void * unused) +#else int hl_process_state(interface_t * interface) +#endif { hl_data_t * data = (hl_data_t *)interface->data; + /* + * Every tick we need to probe the forwarder for the list of faces and + * associated routes. + * + * This is used to guess manually added faces and routes + * + * TODO ensure we are idle at tick time + */ + switch(data->state) { - case HL_STATE_UNDEFINED: // FIXME - case HL_STATE_CONNECTING: // FIXME - if (hc_face_list_async(data->s) < 0) { - /* Blocking call */ - printf("Could not retrieve face list\n"); + case HL_STATE_IDLE: + assert(!data->polled_routes); + + //DEBUG("[hl_process_state] Querying route list"); + if (hc_route_list_async(data->s) < 0) { + DEBUG("[hl_process_state] Error querying route list"); return -1; } + data->state = HL_STATE_ROUTES_SENT; break; - case HL_STATE_FACES_SENT: + + case HL_STATE_ROUTES_RECEIVED: + //DEBUG("[hl_process_state] Querying face list"); + if (hc_face_list_async(data->s) < 0) { + DEBUG("[hl_process_state] Error querying face list"); + return -1; + } + data->state = HL_STATE_FACES_SENT; + break; break; - default: /* HL_STATE_DONE never called */ + case HL_STATE_FACES_RECEIVED: + data->state = HL_STATE_IDLE; break; + + case HL_STATE_ROUTES_SENT: + case HL_STATE_FACES_SENT: + case HL_STATE_UNDEFINED: + case HL_STATE_N: + ERROR("[hl_process_state] Unexpected state"); + return -1; } return 0; @@ -92,9 +130,21 @@ hl_after_connect(interface_t * interface) goto ERR_FD; } - data->state = HL_STATE_UNDEFINED; + /* We always restart from the idle phase */ + data->state = HL_STATE_IDLE; + +/* poll will replace the original get, ideally we would get notifications */ +#ifdef WITH_POLL + data->poll_timer_fd = interface_register_timer(interface, INTERVAL_MS, + hl_process_state, interface); + if (data->poll_timer_fd < 0) { + ERROR("[hc_connect] Could not initialize polling timer"); + return -1; + } +#else hl_process_state(interface); +#endif return 0; @@ -108,6 +158,10 @@ int _hl_connect(interface_t * interface); int hl_connect_timeout(interface_t * interface, int fd, void * unused) { + hl_data_t * data = interface->data; + assert(fd == data->reconnect_timer_fd); + _unused(data); + int rc = _hl_connect(interface); if (rc < 0) { DEBUG("[hl_initialize] Error during connection reattempt; next attempt in %ds", INTERVAL_MS / 1000); @@ -156,6 +210,12 @@ int hl_disconnect(interface_t * interface) if (data->reconnect_timer_fd > 0) interface_unregister_timer(interface, data->reconnect_timer_fd); + if (data->poll_timer_fd > 0) + interface_unregister_timer(interface, data->poll_timer_fd); + + if (data->polled_routes) + hc_data_free(data->polled_routes); + if (data->s) { interface_unregister_fd(interface, hc_sock_get_fd(data->s)); hc_sock_free(data->s); @@ -194,6 +254,7 @@ hl_initialize(interface_t * interface, void * cfg) data->s = NULL; data->reconnect_timer_fd = 0; + data->poll_timer_fd = 0; interface->data = data; @@ -202,6 +263,8 @@ hl_initialize(interface_t * interface, void * cfg) goto ERR_CONNECT; } + data->polled_routes = NULL; + return 0; ERR_CONNECT: @@ -216,6 +279,9 @@ int hl_finalize(interface_t * interface) hl_disconnect(interface); + if (data->polled_routes) + hc_data_free(data->polled_routes); + free(data); return 0; @@ -256,8 +322,10 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet) { char buf[MAXSZ_FACELET]; facelet_snprintf(buf, MAXSZ_FACELET, facelet); - printf("Create face %s\n", buf); + DEBUG("Create facelet %s", buf); } + hc_face.id = 0; + memset(hc_face.name, 0, sizeof(hc_face.name)); hc_face.face = *face; rc = hc_face_create(data->s, &hc_face); if (rc < 0) { @@ -399,38 +467,130 @@ ERR_FACE: int hl_callback(interface_t * interface, int fd, void * unused) { hl_data_t * data = (hl_data_t*)interface->data; + hc_data_t * results; + int ret = 0; - hc_data_t * faces; - if (hc_sock_callback(data->s, &faces) < 0){ + /* In case of error, reconnect to forwarder */ + if (hc_sock_callback(data->s, &results) < 0) { DEBUG("Closing socket... reconnecting..."); if (interface_unregister_fd(interface, hc_sock_get_fd(data->s)) < 0) { - ERROR("[hl_initialize] Error registering fd"); + ERROR("[hl_callback] Error unregistering fd"); + } + + /* Stopping poll timer */ + if (interface_unregister_timer(interface, data->poll_timer_fd) < 0) { + ERROR("[hl_callback] Could not cancel polling timer after forwarder disconnect"); } + if (data->polled_routes) + hc_data_free(data->polled_routes); + hc_sock_free(data->s); data->s = NULL; hl_connect(interface); - return 0; + return ret; } - if (faces->complete) { - foreach_face(f, faces) { + /* Shall we wait for more data ? */ + if (!results->complete) + return ret; + + /* Process returned data */ + switch(data->state) { + + case HL_STATE_ROUTES_SENT: + //DEBUG("[hl_callback] Processing routes"); + data->polled_routes = results; + #if 0 - char buf[MAXSZ_FACE]; - hc_face_snprintf(buf, MAXSZ_FACE, f); - printf("Face: %s\n", buf); + foreach_route(r, results) { + char buf[MAXSZ_FACE]; + int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, r); + if (rc >= MAXSZ_HC_ROUTE) + ERROR("[hl_callback] Unexpected truncation of route string"); + if (rc < 0) + ERROR("[hl_callback] Error during route string formatting"); + DEBUG("Route: %s", buf); + } #endif - facelet_t * facelet = facelet_create_from_face(&f->face); - facelet_set_event(facelet, FACELET_EVENT_GET); - interface_raise_event(interface, facelet); - } - } - hc_data_free(faces); + data->state = HL_STATE_ROUTES_RECEIVED; + if (hl_process_state(interface, fd, unused) < 0) { + ERROR("[hl_callback] Error processing state after routes received"); + ret = -1; + } + break; - /* XXX how do we know what object we get back */ - /* We have a queue of pending data elements per active query */ + case HL_STATE_FACES_SENT: + //DEBUG("[hl_callback] Processing faces"); + assert(data->polled_routes); + foreach_face(f, results) { - return 0; +#if 0 + char buf[MAXSZ_FACE]; + int rc = hc_face_snprintf(buf, MAXSZ_FACE, f); + if (rc >= MAXSZ_HC_FACE) + ERROR("[hl_callback] Unexpected truncation of face string"); + if (rc < 0) + ERROR("[hl_callback] Error during face string formatting"); + + DEBUG("Face: %s", buf); +#endif + + /* We can ignore faces on localhost */ + + facelet_t * facelet = facelet_create_from_face(&f->face); + char facelet_s[MAXSZ_FACELET]; + facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet); + foreach_route(r, data->polled_routes) { + if (r->face_id != f->id) + continue; + +#if 0 + char route_s[MAXSZ_HC_ROUTE]; + int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, r); + if (rc >= MAXSZ_HC_ROUTE) + ERROR("[hl_callback] Unexpected truncation of route string"); + if (rc < 0) + ERROR("[hl_callback] Error during route string formatting"); + DEBUG("Associated route: %s", route_s); +#endif + + if (r->len == 0) + continue; + + ip_prefix_t prefix = { + .family = r->family, + .address = r->remote_addr, + .len = r->len, + }; + hicn_route_t * route = hicn_route_create(&prefix, r->face_id, r->cost); + facelet_add_route(facelet, route); + } + + facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet); + facelet_set_event(facelet, FACELET_EVENT_GET); + interface_raise_event(interface, facelet); + } + + hc_data_free(data->polled_routes); + data->polled_routes = NULL; + data->state = HL_STATE_FACES_RECEIVED; + if (hl_process_state(interface, fd, unused) < 0) { + ERROR("[hl_callback] Error processing state after faces received"); + ret = -1; + } + break; + + case HL_STATE_IDLE: + case HL_STATE_FACES_RECEIVED: + case HL_STATE_ROUTES_RECEIVED: + case HL_STATE_UNDEFINED: + case HL_STATE_N: + ERROR("[hl_callback] Unexpected state"); + ret = -1; + } + + return ret; } const interface_ops_t hicn_light_ops = { |