diff options
Diffstat (limited to 'ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c')
-rw-r--r-- | ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c | 1144 |
1 files changed, 599 insertions, 545 deletions
diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c index b6e0e605a..b396782f5 100644 --- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c +++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * 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: @@ -19,8 +19,8 @@ */ #include <assert.h> #include <stdbool.h> -#include <stdio.h> // snprintf -#include <time.h> // time +#include <stdio.h> // snprintf +#include <time.h> // time #include <hicn/ctrl.h> #include <hicn/facemgr.h> @@ -38,578 +38,636 @@ #define WITH_POLL typedef enum { - HL_STATE_UNDEFINED, - HL_STATE_IDLE, - HL_STATE_ROUTES_SENT, - HL_STATE_ROUTES_RECEIVED, - HL_STATE_FACES_SENT, - HL_STATE_FACES_RECEIVED, - HL_STATE_N + HL_STATE_UNDEFINED, + HL_STATE_IDLE, + HL_STATE_ROUTES_SENT, + HL_STATE_ROUTES_RECEIVED, + HL_STATE_FACES_SENT, + HL_STATE_FACES_RECEIVED, + HL_STATE_N } hl_state_t; typedef struct { - hc_sock_t * s; /* NULL means no active socket */ - hl_state_t state; + hc_sock_t *s; /* NULL means no active socket */ - /* Timer used for forwarder reconnection */ - int reconnect_timer_fd; /* 0 means no active timer */ + /* Socket for polling, dependent on s */ + hc_sock_t *sp; /* NULL means no active socket */ - /* Timer used to periodically poll the forwarder face and routing tables */ - int poll_timer_fd; - hc_data_t * polled_routes; -} hl_data_t; + hl_state_t state; + + /* Timer used for forwarder reconnection */ + int reconnect_timer_fd; /* 0 means no active timer */ -/* Forward declarations */ -int hl_timeout(interface_t * interface, int fd, void * unused); + /* Timer used to periodically poll the forwarder face and routing tables */ + int poll_timer_fd; + hc_data_t *polled_routes; +} hl_data_t; #ifdef WITH_POLL -int hl_process_state(interface_t * interface, int fd, void * unused) +int hl_process_state(interface_t *interface, int fd, void *unused); #else -int hl_process_state(interface_t * interface) +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_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; +void start_poll_timer(interface_t *interface) { + hl_data_t *data = (hl_data_t *)interface->data; - 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; - - case HL_STATE_FACES_RECEIVED: - data->state = HL_STATE_IDLE; - break; - - case HL_STATE_ROUTES_SENT: - case HL_STATE_FACES_SENT: - INFO("[hl_process_state] Out of sync... resetting state"); - if (data->polled_routes) { - hc_data_free(data->polled_routes); - data->polled_routes = NULL; - } - data->state = HL_STATE_IDLE; - break; + data->poll_timer_fd = interface_register_timer(interface, INTERVAL_MS, + hl_process_state, interface); + if (data->poll_timer_fd < 0) { + ERROR("[start_poll_timer) Could not start polling timer"); + } +} - case HL_STATE_UNDEFINED: - case HL_STATE_N: - ERROR("[hl_process_state] Unexpected state"); - return -1; - } +void stop_poll_timer(interface_t *interface) { + hl_data_t *data = (hl_data_t *)interface->data; - return 0; + if (data->poll_timer_fd > 0) + if (interface_unregister_timer(interface, data->poll_timer_fd) < 0) { + ERROR("[stop_poll_timer] Could not stop polling timer"); + } } - -int -hl_after_connect(interface_t * interface) +#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 = interface->data; + 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_IDLE: + assert(!data->polled_routes); + stop_poll_timer(interface); + + // DEBUG("[hl_process_state] Querying route list"); + if (hc_route_list_async(data->sp) < 0) { + DEBUG("[hl_process_state] Error querying route list"); + return -1; + } + data->state = HL_STATE_ROUTES_SENT; + break; + + case HL_STATE_ROUTES_RECEIVED: + // DEBUG("[hl_process_state] Querying face list"); + if (hc_face_list_async(data->sp) < 0) { + DEBUG("[hl_process_state] Error querying face list"); + return -1; + } + data->state = HL_STATE_FACES_SENT; + break; + + case HL_STATE_FACES_RECEIVED: + data->state = HL_STATE_IDLE; + start_poll_timer(interface); + break; + + case HL_STATE_ROUTES_SENT: + case HL_STATE_FACES_SENT: + WARN("[hl_process_state] Out of sync... resetting state"); + if (data->polled_routes) { + hc_data_free(data->polled_routes); + data->polled_routes = NULL; + } + data->state = HL_STATE_IDLE; + start_poll_timer(interface); + break; + + case HL_STATE_UNDEFINED: + case HL_STATE_N: + ERROR("[hl_process_state] Unexpected state"); + return -1; + } + + return 0; +} - /* File descriptor for control socket operations */ - if (interface_register_fd(interface, hc_sock_get_fd(data->s), NULL) < 0) { - ERROR("[hc_connect] Error registering fd"); - goto ERR_FD; - } +/* + * Called whenever a connection to both sockets succeeds. + * Polling will be useful to detect when connection to the forwarder is lost, + * and will allow to try reconnect both sockets (the control socket being UDP / + * in blocking mode will not detect such loss of connection). Operations on the + * control socket that will fail will be reattempted by higher layers. + */ +int hl_after_connect(interface_t *interface) { + hl_data_t *data = interface->data; - /* We always restart from the idle phase */ - data->state = HL_STATE_IDLE; + /* File descriptor for polling socket operations */ + if (interface_register_fd(interface, hc_sock_get_fd(data->sp), NULL) < 0) { + ERROR("[hc_connect] Error registering fd"); + goto ERR_FD; + } + /* 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; - } + start_poll_timer(interface); #else - hl_process_state(interface); + hl_process_state(interface); #endif - return 0; + return 0; - //interface_unregister_fd(interface, hc_sock_get_fd(data->s)); + // interface_unregister_fd(interface, hc_sock_get_fd(data->sp)); ERR_FD: - return -1; + return -1; } -int _hl_connect(interface_t * interface); +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 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); - return -1; - } + int rc = _hl_connect(interface); + if (rc < 0) { + DEBUG( + "[hl_initialize] Error during connection reattempt; next attempt in " + "%ds", + INTERVAL_MS / 1000); + return -1; + } - if (interface_unregister_timer(interface, fd) < 0) { - ERROR("[hl_connect_timeout] Could not cancel timer after successful connect"); - } + if (interface_unregister_timer(interface, fd) < 0) { + ERROR( + "[hl_connect_timeout] Could not cancel timer after successful connect"); + } - /* Connect success */ - return hl_after_connect(interface); + /* Connect success */ + return hl_after_connect(interface); } - -int -_hl_connect(interface_t * interface) -{ - hl_data_t * data = interface->data; - assert(!data->s); - - data->s = hc_sock_create(); - if (data->s <= 0) { - ERROR("[hc_connect] Could not create control socket"); - goto ERR_SOCK; - } - - if (hc_sock_connect(data->s) < 0) { - DEBUG("[hc_connect] Could not connect control socket"); - goto ERR_CONNECT; - } - - return 0; - +/* + * Connection without reattempt. Both control and polling sockets should be + * connected to succeed. + */ +int _hl_connect(interface_t *interface) { + hl_data_t *data = interface->data; + assert(!data->s); + assert(!data->sp); + + data->s = hc_sock_create(); + if (data->s <= 0) { + ERROR("[hc_connect] Could not create control socket"); + goto ERR_SOCK; + } + + if (hc_sock_connect(data->s) < 0) { + DEBUG("[hc_connect] Could not connect control socket"); + goto ERR_CONNECT; + } + + data->sp = hc_sock_create(); + if (data->sp <= 0) { + ERROR("[hc_connect] Could not create polling socket"); + goto ERR_SOCK_POLL; + } + + if (hc_sock_connect(data->sp) < 0) { + DEBUG("[hc_connect] Could not connect polling socket"); + goto ERR_CONNECT_POLL; + } + + return 0; + +ERR_CONNECT_POLL: + hc_sock_free(data->sp); + data->sp = NULL; +ERR_SOCK_POLL: ERR_CONNECT: - hc_sock_free(data->s); - data->s = NULL; + hc_sock_free(data->s); + data->s = NULL; ERR_SOCK: - return -1; - + return -1; } -int hl_disconnect(interface_t * interface) -{ - hl_data_t * data = (hl_data_t *) interface->data; - if (data->reconnect_timer_fd > 0) - interface_unregister_timer(interface, data->reconnect_timer_fd); +int hl_disconnect(interface_t *interface) { + hl_data_t *data = (hl_data_t *)interface->data; + 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); + stop_poll_timer(interface); - if (data->polled_routes) - hc_data_free(data->polled_routes); + 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); - } + if (data->s) { + hc_sock_free(data->s); + data->s = NULL; + } - return 0; + if (data->sp) { + interface_unregister_fd(interface, hc_sock_get_fd(data->sp)); + hc_sock_free(data->sp); + data->sp = NULL; + } + + return 0; } -int -hl_connect(interface_t * interface) -{ - hl_data_t * data = interface->data; +/* Connection with reattempts */ +int hl_connect(interface_t *interface) { + hl_data_t *data = interface->data; - if (_hl_connect(interface) >= 0) - return hl_after_connect(interface); + if (_hl_connect(interface) >= 0) return hl_after_connect(interface); - /* Timer for managing the connection to the forwarder */ - DEBUG("Connection to forwarder failed... next retry in %ds", INTERVAL_MS / 1000); - data->reconnect_timer_fd = interface_register_timer(interface, INTERVAL_MS, hl_connect_timeout, NULL); - if (data->reconnect_timer_fd < 0) { - ERROR("[hc_connect] Could not initialize reattempt timer"); - return -1; - } + /* Timer for managing the connection to the forwarder */ + DEBUG("Connection to forwarder failed... next retry in %ds", + INTERVAL_MS / 1000); + data->reconnect_timer_fd = interface_register_timer(interface, INTERVAL_MS, + hl_connect_timeout, NULL); + if (data->reconnect_timer_fd < 0) { + ERROR("[hc_connect] Could not initialize reattempt timer"); + return -1; + } - return 0; + return 0; } -int -hl_initialize(interface_t * interface, void * cfg) -{ - hl_data_t * data = malloc(sizeof(hl_data_t)); - if (!data) { - ERROR("[hicn_light] Out of memory!"); - goto ERR_MALLOC; - } - - data->s = NULL; - data->reconnect_timer_fd = 0; - data->poll_timer_fd = 0; +int hl_initialize(interface_t *interface, void *cfg) { + hl_data_t *data = malloc(sizeof(hl_data_t)); + if (!data) { + ERROR("[hicn_light] Out of memory!"); + goto ERR_MALLOC; + } - interface->data = data; + data->s = NULL; + data->sp = NULL; + data->reconnect_timer_fd = 0; + data->poll_timer_fd = 0; + data->polled_routes = NULL; + data->state = HL_STATE_UNDEFINED; - if (hl_connect(interface) < 0) { - ERROR("[hl_initialize] Error during connection to forwarder"); - goto ERR_CONNECT; - } + interface->data = data; - data->polled_routes = NULL; + /* Connect both control and polling sockets */ + if (hl_connect(interface) < 0) { + ERROR("[hl_initialize] Error during connection to forwarder"); + goto ERR_CONNECT; + } - return 0; + return 0; ERR_CONNECT: - free(data); + free(data); ERR_MALLOC: - return -1; + return -1; } -int hl_finalize(interface_t * interface) -{ - hl_data_t * data = (hl_data_t *) interface->data; +int hl_finalize(interface_t *interface) { + hl_data_t *data = (hl_data_t *)interface->data; - hl_disconnect(interface); + hl_disconnect(interface); - if (data->polled_routes) - hc_data_free(data->polled_routes); + if (data->polled_routes) hc_data_free(data->polled_routes); - free(data); + free(data); - return 0; + return 0; } -int hl_on_event(interface_t * interface, facelet_t * facelet) -{ - hc_face_t hc_face; - hc_route_t route; - int rc; - int ret = 0; - hl_data_t * data = (hl_data_t *)interface->data; - face_t * face = NULL; - - hc_face.id = 0; - memset(hc_face.name, 0, sizeof(hc_face.name)); - - - /* NOTE - * - One example where this fails (and it is normal) is when we delete a - * face that was not completely created, because for instance bonjour did - * not give any data - */ - if (facelet_get_face(facelet, &face) < 0) { - ERROR("Could not retrieve face from facelet"); - ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; - goto ERR_FACE; +int hl_on_event(interface_t *interface, facelet_t *facelet) { + hc_face_t hc_face; + hc_route_t route; + int rc; + int ret = 0; + hl_data_t *data = (hl_data_t *)interface->data; + face_t *face = NULL; + + hc_face.id = 0; + memset(hc_face.name, 0, sizeof(hc_face.name)); + + /* NOTE + * - One example where this fails (and it is normal) is when we delete a + * face that was not completely created, because for instance bonjour did + * not give any data + */ + if (facelet_get_face(facelet, &face) < 0) { + ERROR("Could not retrieve face from facelet"); + ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + goto ERR_FACE; + } + + if (!data->s) { + /* We are not connected to the forwarder */ + ret = -FACELET_ERROR_REASON_FORWARDER_OFFLINE; + goto ERR; + } + + switch (facelet_get_event(facelet)) { + case FACELET_EVENT_CREATE: { + /* Create face */ + char buf[MAXSZ_FACELET]; + facelet_snprintf(buf, MAXSZ_FACELET, facelet); + DEBUG("Create facelet %s", buf); + + hc_face.face = *face; + rc = hc_face_create(data->s, &hc_face); + if (rc < 0) { + ERROR("Failed to create face\n"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } + INFO("Created face id=%d - %s", hc_face.id, buf); } - if (!data->s) { - /* We are not connected to the forwarder */ - ret = -FACELET_ERROR_REASON_FORWARDER_OFFLINE; + hicn_route_t **route_array; + int n = facelet_get_route_array(facelet, &route_array); + if (n < 0) { + ERROR("Failed to create default hICN/IPv4 route"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; goto ERR; - } + } + if (n == 0) { + /* Adding default routes */ + route = (hc_route_t){ + .face_id = hc_face.id, + .family = AF_INET, + .remote_addr = IPV4_ANY, + .len = 0, + .cost = DEFAULT_ROUTE_COST, + + }; + if (hc_route_create(data->s, &route) < 0) { + ERROR("Failed to create default hICN/IPv4 route"); + ret = -1; + } - switch(facelet_get_event(facelet)) { - - case FACELET_EVENT_CREATE: - { - /* Create face */ - char buf[MAXSZ_FACELET]; - facelet_snprintf(buf, MAXSZ_FACELET, facelet); - DEBUG("Create facelet %s", buf); - - hc_face.face = *face; - rc = hc_face_create(data->s, &hc_face); - if (rc < 0) { - ERROR("Failed to create face\n"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } - INFO("Created face id=%d - %s", hc_face.id, buf); - } + route = (hc_route_t){ + .face_id = hc_face.id, + .family = AF_INET6, + .remote_addr = IPV6_ANY, + .len = 0, + .cost = DEFAULT_ROUTE_COST, + }; + if (hc_route_create(data->s, &route) < 0) { + ERROR("Failed to create default hICN/IPv6 route"); + ret = -1; + } - hicn_route_t ** route_array; - int n = facelet_get_route_array(facelet, &route_array); - if (n < 0) { - ERROR("Failed to create default hICN/IPv4 route"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } - if (n == 0) { - /* Adding default routes */ - route = (hc_route_t) { - .face_id = hc_face.id, - .family = AF_INET, - .remote_addr = IPV4_ANY, - .len = 0, - .cost = DEFAULT_ROUTE_COST, - - }; - if (hc_route_create(data->s, &route) < 0) { - ERROR("Failed to create default hICN/IPv4 route"); - ret = -1; - } - - route = (hc_route_t) { - .face_id = hc_face.id, - .family = AF_INET6, - .remote_addr = IPV6_ANY, - .len = 0, - .cost = DEFAULT_ROUTE_COST, - }; - if (hc_route_create(data->s, &route) < 0) { - ERROR("Failed to create default hICN/IPv6 route"); - ret = -1; - } - - INFO("Successfully created default route(s)."); - } else { - for (unsigned i = 0; i < n; i++) { - hicn_route_t * hicn_route = route_array[i]; - ip_prefix_t prefix; - int cost; - if (hicn_route_get_prefix(hicn_route, &prefix) < 0) { - ERROR("Failed to get route prefix"); - ret = -1; - continue; - } - if (hicn_route_get_cost(hicn_route, &cost) < 0) { - ERROR("Failed to get route cost"); - ret = -1; - continue; - } - route = (hc_route_t) { - .face_id = hc_face.id, - .family = prefix.family, - .remote_addr = prefix.address, - .len = prefix.len, - .cost = cost, - }; - if (hc_route_create(data->s, &route) < 0) { - ERROR("Failed to create static route route"); - ret = -1; - continue; - } - } - } - free(route_array); - - break; - - case FACELET_EVENT_DELETE: - /* Removing a face should also remove associated routes */ - hc_face.face = *face; - rc = hc_face_delete(data->s, &hc_face); - if (rc < 0) { - ERROR("Failed to delete face\n"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } + INFO("Successfully created default route(s)."); + } else { + for (unsigned i = 0; i < n; i++) { + hicn_route_t *hicn_route = route_array[i]; + ip_prefix_t prefix; + int cost; + if (hicn_route_get_prefix(hicn_route, &prefix) < 0) { + ERROR("Failed to get route prefix"); + ret = -1; + continue; + } + if (hicn_route_get_cost(hicn_route, &cost) < 0) { + ERROR("Failed to get route cost"); + ret = -1; + continue; + } + route = (hc_route_t){ + .face_id = hc_face.id, + .name = "", /* take face_id into account */ + .family = prefix.family, + .remote_addr = prefix.address, + .len = prefix.len, + .cost = cost, + }; + if (hc_route_create(data->s, &route) < 0) { + ERROR("Failed to create static route route"); + ret = -1; + continue; + } + } + } + free(route_array); + + break; + + case FACELET_EVENT_DELETE: + /* Removing a face should also remove associated routes */ + hc_face.face = *face; + rc = hc_face_delete(data->s, &hc_face, 1); + if (rc < 0) { + ERROR("Failed to delete face\n"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } + + char buf[MAXSZ_FACELET]; + facelet_snprintf(buf, MAXSZ_FACELET, facelet); + INFO("Deleted face id=%d", hc_face.id); + + break; + + case FACELET_EVENT_UPDATE: + /* Currently, only admin_state & priority are supported */ + if (facelet_get_admin_state_status(facelet) == + FACELET_ATTR_STATUS_DIRTY) { + hc_face.face = *face; + hc_face_t *face_found; + + rc = hc_face_get(data->s, &hc_face, &face_found); + if (rc < 0) { + ERROR("Failed to find face\n"); + ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + goto ERR; + } + if (!face_found) { + ERROR("Face to update has not been found"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } + char conn_id_or_name[SYMBOLIC_NAME_LEN]; + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); + free(face_found); + + face_state_t admin_state; + if (facelet_get_admin_state(facelet, &admin_state) < 0) { + ERROR("Failed to retrieve facelet admin state"); + ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + goto ERR; + } - char buf[MAXSZ_FACELET]; - facelet_snprintf(buf, MAXSZ_FACELET, facelet); - INFO("Deleted face id=%d", hc_face.id); - - break; - - case FACELET_EVENT_UPDATE: - /* Currently, only admin_state & priority are supported */ - if (facelet_get_admin_state_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { - hc_face.face = *face; - hc_face_t * face_found; - - rc = hc_face_get(data->s, &hc_face, &face_found); - if (rc < 0) { - ERROR("Failed to find face\n"); - ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; - goto ERR; - } - if (!face_found) { - ERROR("Face to update has not been found"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } - char conn_id_or_name[SYMBOLIC_NAME_LEN]; - snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); - free(face_found); - - face_state_t admin_state; - if (facelet_get_admin_state(facelet, &admin_state) < 0) { - ERROR("Failed to retrieve facelet admin state"); - ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; - goto ERR; - } - - if (hc_connection_set_admin_state(data->s, conn_id_or_name, admin_state) < 0) { - ERROR("Failed to update admin state"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } - facelet_set_admin_state_status(facelet, FACELET_ATTR_STATUS_CLEAN); - INFO("Updated face id=%d - admin_state=%s", hc_face.id, - face_state_str[admin_state]); - } + if (hc_connection_set_admin_state(data->s, conn_id_or_name, + admin_state) < 0) { + ERROR("Failed to update admin state"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } + facelet_set_admin_state_status(facelet, FACELET_ATTR_STATUS_CLEAN); + INFO("Updated face id=%d - admin_state=%s", hc_face.id, + face_state_str(admin_state)); + } #ifdef WITH_POLICY - if (facelet_get_netdevice_type_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { - hc_face.face = *face; - hc_face_t * face_found; - - rc = hc_face_get(data->s, &hc_face, &face_found); - if (rc < 0) { - ERROR("Failed to find face\n"); - goto ERR; - } - if (!face_found) { - ERROR("Face to update has not been found"); - goto ERR; - } - char conn_id_or_name[SYMBOLIC_NAME_LEN]; - snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); - free(face_found); - - netdevice_type_t netdevice_type; - if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { - ERROR("Failed to retrieve facelet netdevice_type"); - goto ERR; - } - - /* Encode netdevice type into tags */ - policy_tags_t tags = POLICY_TAGS_EMPTY; - if (facelet_has_netdevice_type(facelet)) { - netdevice_type_t netdevice_type; - if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { - ERROR("error getting netdevice_type"); - goto ERR; - } - - - switch(netdevice_type) { - case NETDEVICE_TYPE_UNDEFINED: - case NETDEVICE_TYPE_LOOPBACK: - break; - case NETDEVICE_TYPE_WIRED: - policy_tags_add(&tags, POLICY_TAG_WIRED); - break; - case NETDEVICE_TYPE_WIFI: - policy_tags_add(&tags, POLICY_TAG_WIFI); - break; - case NETDEVICE_TYPE_CELLULAR: - policy_tags_add(&tags, POLICY_TAG_CELLULAR); - break; - default: - goto ERR; - } - } - //face->tags = tags; - - if (hc_connection_set_tags(data->s, conn_id_or_name, tags) < 0) { - ERROR("Failed to update tags"); - goto ERR; - } - facelet_set_netdevice_type_status(facelet, FACELET_ATTR_STATUS_CLEAN); - INFO("Updated face id=%d - netdevice_type=%s", hc_face.id, - netdevice_type_str[netdevice_type]); - } - if (facelet_get_priority_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { - INFO("Updating priority..."); - hc_face.face = *face; - hc_face_t * face_found; - - rc = hc_face_get(data->s, &hc_face, &face_found); - if (rc < 0) { - ERROR("Failed to find face\n"); - goto ERR; - } - if (!face_found) { - ERROR("Face to update has not been found"); - goto ERR; - } - char conn_id_or_name[SYMBOLIC_NAME_LEN]; - snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); - free(face_found); - - uint32_t priority; - if (facelet_get_priority(facelet, &priority) < 0) { - ERROR("Failed to retrieve facelet priority"); - goto ERR; - } - - INFO("Changing connection %s priority to %d", conn_id_or_name, priority); - if (hc_connection_set_priority(data->s, conn_id_or_name, priority) < 0) { - ERROR("Failed to update priority"); - goto ERR; - } - facelet_set_priority_status(facelet, FACELET_ATTR_STATUS_CLEAN); - - INFO("Updated face id=%d - priority=%d", hc_face.id, priority); - } -#endif /* WITH_POLICY */ - break; + if (facelet_get_netdevice_type_status(facelet) == + FACELET_ATTR_STATUS_DIRTY) { + hc_face.face = *face; + hc_face_t *face_found; + + rc = hc_face_get(data->s, &hc_face, &face_found); + if (rc < 0) { + ERROR("Failed to find face\n"); + goto ERR; + } + if (!face_found) { + ERROR("Face to update has not been found"); + goto ERR; + } + char conn_id_or_name[SYMBOLIC_NAME_LEN]; + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); + free(face_found); + + netdevice_type_t netdevice_type; + if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { + ERROR("Failed to retrieve facelet netdevice_type"); + goto ERR; + } - default: - ERROR("Unknown event %s\n", facelet_event_str[facelet_get_event(facelet)]); - /* Unsupported events */ - ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + /* Encode netdevice type into tags */ + policy_tags_t tags = POLICY_TAGS_EMPTY; + if (facelet_has_netdevice_type(facelet)) { + netdevice_type_t netdevice_type; + if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { + ERROR("error getting netdevice_type"); goto ERR; - } + } + + switch (netdevice_type) { + case NETDEVICE_TYPE_UNDEFINED: + case NETDEVICE_TYPE_LOOPBACK: + break; + case NETDEVICE_TYPE_WIRED: + policy_tags_add(&tags, POLICY_TAG_WIRED); + break; + case NETDEVICE_TYPE_WIFI: + policy_tags_add(&tags, POLICY_TAG_WIFI); + break; + case NETDEVICE_TYPE_CELLULAR: + policy_tags_add(&tags, POLICY_TAG_CELLULAR); + break; + default: + goto ERR; + } + } + // face->tags = tags; + + if (hc_connection_set_tags(data->s, conn_id_or_name, tags) < 0) { + ERROR("Failed to update tags"); + goto ERR; + } + facelet_set_netdevice_type_status(facelet, FACELET_ATTR_STATUS_CLEAN); + INFO("Updated face id=%d - netdevice_type=%s", hc_face.id, + netdevice_type_str(netdevice_type)); + } + if (facelet_get_priority_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { + INFO("Updating priority..."); + hc_face.face = *face; + hc_face_t *face_found; + + rc = hc_face_get(data->s, &hc_face, &face_found); + if (rc < 0) { + ERROR("Failed to find face\n"); + goto ERR; + } + if (!face_found) { + ERROR("Face to update has not been found"); + goto ERR; + } + char conn_id_or_name[SYMBOLIC_NAME_LEN]; + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); + free(face_found); + + uint32_t priority; + if (facelet_get_priority(facelet, &priority) < 0) { + ERROR("Failed to retrieve facelet priority"); + goto ERR; + } + + INFO("Changing connection %s priority to %d", conn_id_or_name, + priority); + if (hc_connection_set_priority(data->s, conn_id_or_name, priority) < + 0) { + ERROR("Failed to update priority"); + goto ERR; + } + facelet_set_priority_status(facelet, FACELET_ATTR_STATUS_CLEAN); + + INFO("Updated face id=%d - priority=%d", hc_face.id, priority); + } +#endif /* WITH_POLICY */ + break; + + default: + ERROR("Unknown event %s\n", + facelet_event_str[facelet_get_event(facelet)]); + /* Unsupported events */ + ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + goto ERR; + } ERR: - face_free(face); + face_free(face); ERR_FACE: - return ret; + return ret; } -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; - - /* 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_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); +/* + * This should only receive data from the polling socket which is asynchronous, + * while all face creation, etc. operations are done synchronously in this + * version. + */ +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; + + /* Workaround: sometimes this is called with data = NULL */ + if (!data) { + INFO("[hl_callback] no data"); + return 0; + } - hc_sock_free(data->s); - data->s = NULL; - hl_connect(interface); - return ret; + /* In case of error, reconnect to forwarder */ + if (hc_sock_callback(data->sp, &results) < 0) { + INFO("Closing socket... reconnecting..."); + if (interface_unregister_fd(interface, hc_sock_get_fd(data->sp)) < 0) { + ERROR("[hl_callback] Error unregistering fd"); } - /* Shall we wait for more data ? */ - if (!results->complete) - return ret; + /* Stopping poll timer */ + stop_poll_timer(interface); + if (data->polled_routes) hc_data_free(data->polled_routes); - /* Process returned data */ - switch(data->state) { + hc_sock_free(data->s); + data->s = NULL; + hc_sock_free(data->sp); + data->sp = NULL; - case HL_STATE_ROUTES_SENT: - //DEBUG("[hl_callback] Processing routes"); - data->polled_routes = results; + hl_connect(interface); + return ret; + } + + /* Shall we wait for more data ? */ + if (!results->complete) { + INFO("[hl_callback] results incomplete"); + return ret; + } + + /* Process returned data */ + // DEBUG("Processing data"); + switch (data->state) { + case HL_STATE_ROUTES_SENT: + // DEBUG("[hl_callback] Processing routes"); + data->polled_routes = results; #if 0 foreach_route(r, results) { @@ -622,19 +680,17 @@ int hl_callback(interface_t * interface, int fd, void * unused) DEBUG("Route: %s", buf); } #endif - 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; - - - case HL_STATE_FACES_SENT: - //DEBUG("[hl_callback] Processing faces"); - assert(data->polled_routes); - foreach_face(f, results) { - + 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; + + case HL_STATE_FACES_SENT: + // DEBUG("[hl_callback] Processing faces"); + assert(data->polled_routes); + foreach_face(f, results) { #if 0 char buf[MAXSZ_FACE]; int rc = hc_face_snprintf(buf, MAXSZ_FACE, f); @@ -646,17 +702,16 @@ int hl_callback(interface_t * interface, int fd, void * unused) DEBUG("Face: %s", buf); #endif - /* We can ignore faces on localhost */ + /* We can ignore faces on localhost */ - facelet_t * facelet = facelet_create_from_face(&f->face); - if (!facelet) { - ERROR("[hl_callback] Could not create facelet... skipping"); - continue; - } + facelet_t *facelet = facelet_create_from_face(&f->face); + if (!facelet) { + ERROR("[hl_callback] Could not create facelet... skipping"); + continue; + } - foreach_route(r, data->polled_routes) { - if (r->face_id != f->id) - continue; + foreach_route(r, data->polled_routes) { + if (r->face_id != f->id) continue; #if 0 char route_s[MAXSZ_HC_ROUTE]; @@ -668,41 +723,40 @@ int hl_callback(interface_t * interface, int fd, void * unused) 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); - } + if (r->len == 0) continue; - facelet_set_event(facelet, FACELET_EVENT_GET); - interface_raise_event(interface, facelet); - } - hc_data_free(results); - 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; - } + 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); + } - return ret; + facelet_set_event(facelet, FACELET_EVENT_GET); + interface_raise_event(interface, facelet); + } + hc_data_free(results); + 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 = { |