summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordan Augé <jordan.auge+fdio@cisco.com>2019-11-12 00:15:11 +0100
committerJordan Augé <jordan.auge+fdio@cisco.com>2019-11-17 00:56:51 +0100
commit45bc09ae553e7ac5bf6cd7ab2e77e7f6d0877596 (patch)
tree347cd702a5d3914e003401158b916c709caa302e
parent547acf3eed92d3564139cccf205c852178bcc310 (diff)
[HICN-395] Static face/route maintainance though face manager
Change-Id: I8f2287a262412bacc50f3c89756ec9fd6ce30d33 Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com>
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/facelet.h7
-rw-r--r--ctrl/facemgr/src/api.c204
-rw-r--r--ctrl/facemgr/src/facelet.c27
-rw-r--r--ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c218
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h1
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/route.h1
-rw-r--r--ctrl/libhicnctrl/src/api.c17
-rw-r--r--ctrl/libhicnctrl/src/cli.c2
-rw-r--r--ctrl/libhicnctrl/src/face.c1
-rw-r--r--ctrl/libhicnctrl/src/route.c10
-rw-r--r--lib/includes/hicn/util/array.h3
-rw-r--r--lib/includes/hicn/util/set.h6
12 files changed, 410 insertions, 87 deletions
diff --git a/ctrl/facemgr/includes/hicn/facemgr/facelet.h b/ctrl/facemgr/includes/hicn/facemgr/facelet.h
index 476858eff..8e71d60f0 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/facelet.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/facelet.h
@@ -160,13 +160,6 @@ extern const char * facelet_attr_status_str_short[];
_(CREATE) \
_(UPDATE) \
_(DELETE) \
- _(SET_PARAMS) \
- _(SET_UP) \
- _(SET_DOWN) \
- _(SET_TAGS) \
- _(CLEAR_TAGS) \
- _(ADD_TAG) \
- _(REMOVE_TAG) \
_(N)
#define MAXSZ_EVENT__ 10
diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c
index 23ca2f2ae..d27811476 100644
--- a/ctrl/facemgr/src/api.c
+++ b/ctrl/facemgr/src/api.c
@@ -160,6 +160,8 @@ struct facemgr_s {
interface_t * updown;
#endif
int timer_fd; /* Timer used for reattempts */
+
+ int cur_static_id; /* Used to distinguish static faces (pre-incremented) */
};
int
@@ -198,6 +200,7 @@ facemgr_initialize(facemgr_t * facemgr)
}
facemgr->timer_fd = 0;
+ facemgr->cur_static_id = 0;
return 0;
@@ -533,6 +536,9 @@ int
facelet_cache_lookup(const facelet_set_t * facelet_cache, facelet_t * facelet,
facelet_t ***cached_facelets)
{
+ assert(facelet);
+ if (!facelet_has_family(facelet))
+ return 0;
#if 0 // key is no more sufficient now that we support multiple faces per interface
/*
* If the facelet is uniquely identified by its key, it is used to perform
@@ -565,6 +571,11 @@ facelet_cache_lookup(const facelet_set_t * facelet_cache, facelet_t * facelet,
int num_match = 0;
for (unsigned i = 0; i < n; i++) {
+#if 0
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_array[i]);
+ printf("cache entry #%d/%di = %s\n", i+1, n, facelet_s);
+#endif
if (!facelet_match(facelet_array[i], facelet)) {
continue;
}
@@ -679,6 +690,7 @@ facemgr_complement_facelet_au(facemgr_t * facemgr, facelet_t * facelet)
return -2;
netdevice_t netdevice = NETDEVICE_EMPTY;
+
int rc = facelet_get_netdevice(facelet, &netdevice);
if (rc < 0) {
ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice from facelet");
@@ -1080,6 +1092,8 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet)
facelet_unset_local_port(facelet);
facelet_unset_remote_addr(facelet);
facelet_unset_remote_port(facelet);
+ facelet_unset_admin_state(facelet);
+ facelet_unset_state(facelet);
facelet_unset_bj_done(facelet);
#ifdef WITH_ANDROID_UTILITY
facelet_unset_au_done(facelet);
@@ -1227,6 +1241,82 @@ facemgr_process_facelet_create(facemgr_t * facemgr, facelet_t * facelet)
return 0;
}
+/*
+ * \return 0 in case of success and no static facelet was added, 1 if a static
+ * facelet was added, and -1 in case of error.
+ */
+int
+facemgr_consider_static_facelet(facemgr_t * facemgr, facelet_t * facelet)
+{
+ /*
+ * We need to analyze the facelet and eventually:
+ * - add it in our static list
+ * - replicate it on multipath interfaces
+ */
+ netdevice_type_t netdevice_type;
+ if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0)
+ return -1;
+
+ if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) ||
+ (netdevice_type == NETDEVICE_TYPE_LOOPBACK))
+ return 0;
+
+ if ((facelet_get_route_array(facelet, NULL) == 0))
+ return 0;
+
+ /*
+ * How to differenciate facelet created by face manager from user
+ * created ones ? This cannot be a flag in the facelet as it needs
+ * to work across restarts of the face manager...
+ * Also we might have two default routes.
+ *
+ * TODO:
+ * - The static one should not be a duplicate of the one we would
+ * create by default....
+ * - This should anyways be detected...
+ *
+ * One solution would be to install the default ones as static but
+ * this requires to implement a priority scheme between some of the
+ * static routes so that the override mechanism continues to work as
+ * usual.
+ *
+ * Current, we recognize the routes created by default by the face
+ * maanger thanks to the routing prefixes (a single default route).
+ */
+
+ facelet_t * static_facelet = facelet_dup(facelet);
+ facelet_unset_netdevice(static_facelet);
+ facelet_unset_netdevice_type(static_facelet);
+ facelet_unset_local_addr(static_facelet);
+ facelet_unset_local_port(static_facelet);
+
+ facelet_t * facelet_found = NULL;
+ if (facelet_array_get(facemgr->static_facelets, static_facelet, &facelet_found) < 0) {
+ ERROR("[facemgr_consider_static_facelet] Error checking whether static facelet already exists or not");
+ return -1;
+ }
+
+ /* Skip addition if facelet exists */
+ if (facelet_found)
+ return 0;
+
+ if (facelet_array_add(facemgr->static_facelets, static_facelet) < 0) {
+ ERROR("[facemgr_consider_static_facelet] Could not add facelet to static array");
+ facelet_free(static_facelet);
+ return -1;
+ }
+
+ char facelet_s[MAXSZ_FACELET];
+ int rc = facelet_snprintf(facelet_s, MAXSZ_FACELET, static_facelet);
+ if (rc >= MAXSZ_FACELET)
+ ERROR("[facemgr_consider_static_facelet] Unexpected truncation of facelet string");
+ if (rc < 0)
+ ERROR("[facemgr_consider_static_facelet] Error during facelet string output");
+ DEBUG("[facemgr_consider_static_facelet] Successfully added facelet to static array %s", facelet_s);
+
+ return 1;
+}
+
/**
* \brief Process facelet GET event
* \param [in] facemgr - Pointer to the face manager instance
@@ -1237,16 +1327,34 @@ facemgr_process_facelet_create(facemgr_t * facemgr, facelet_t * facelet)
int
facemgr_process_facelet_get(facemgr_t * facemgr, facelet_t * facelet)
{
- if (facelet_has_netdevice(facelet)) {
- netdevice_t netdevice;
- if (facelet_get_netdevice(facelet, &netdevice) < 0)
- return -1;
- if (!IS_VALID_NETDEVICE(netdevice))
- return -2;
- facelet_set_status(facelet, FACELET_STATUS_CLEAN);
- return facelet_set_add(facemgr->facelet_cache, facelet);
+ assert(facelet);
+
+ if (!facelet_has_netdevice(facelet))
+ return -2;
+
+ netdevice_t netdevice;
+ if (facelet_get_netdevice(facelet, &netdevice) < 0)
+ return -1;
+ if (!IS_VALID_NETDEVICE(netdevice))
+ return -2;
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+
+ int n = facemgr_consider_static_facelet(facemgr, facelet);
+ if (n < 0) {
+ ERROR("[facemgr_process_facelet_get] Could not add facelet to static array");
+ return -1;
}
- return -2;
+ if (n == 1) {
+ /*
+ * As a static facelet, it receives a new id not to be confused in the
+ * cache with default facelets
+ */
+ facelet_set_id(facelet, ++facemgr->cur_static_id);
+ }
+
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
+ return facelet_set_add(facemgr->facelet_cache, facelet);
}
/**
@@ -1341,6 +1449,9 @@ int facemgr_process_facelet_first_time(facemgr_t * facemgr, facelet_t * facelet)
{
facelet_set_status(facelet, FACELET_STATUS_UNCERTAIN);
+ assert(facelet);
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
if (facelet_set_add(facemgr->facelet_cache, facelet) < 0) {
ERROR("[facemgr_process_facelet_first_time] Error adding facelet to cache");
goto ERR_CACHE;
@@ -1372,15 +1483,28 @@ int
facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
{
bool remove_facelet = true;
+ bool dump = true;
int ret = 0;
int rc;
assert(facelet_in);
+ /* Update Netdevice type */
+ if (facelet_has_netdevice(facelet_in) && (!facelet_has_netdevice_type(facelet_in))) {
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+
+ rc = facelet_get_netdevice(facelet_in, &netdevice);
+ if (rc < 0) {
+ ERROR("[facemgr_on_event] Error retrieving netdevice from facelet");
+ return -1;
+ }
+ facelet_set_netdevice_type(facelet_in, facemgr_get_netdevice_type(facemgr, netdevice.name));
+ }
+
char facelet_s[MAXSZ_FACELET];
facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_in);
- DEBUG("EVENT %s", facelet_s);
facelet_t ** cached_facelets = NULL;
+ assert(facelet_in);
int n = facelet_cache_lookup(facemgr->facelet_cache, facelet_in, &cached_facelets);
if (n < 0) {
ERROR("[facemgr_on_event] Error during cache lookup");
@@ -1399,18 +1523,9 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
* Assumption: we should always see the link before the address
* assignment
*/
+ DEBUG("[facemgr_on_event] CREATE NEW %s", facelet_s);
assert(!facelet_has_family(facelet_in));
- if (!facelet_has_netdevice_type(facelet_in)) {
- netdevice_t netdevice = NETDEVICE_EMPTY;
- rc = facelet_get_netdevice(facelet_in, &netdevice);
- if (rc < 0) {
- ERROR("[facemgr_complement_facelet] Error retrieving netdevice from facelet");
- return -1;
- }
- facelet_set_netdevice_type(facelet_in, facemgr_get_netdevice_type(facemgr, netdevice.name));
- }
-
/* Create default v4 and v6 facelets */
facelet_t * facelet_v4 = facelet_dup(facelet_in);
if (!facelet_v4) {
@@ -1472,7 +1587,7 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
continue;
}
/* The id must be different than 0 */
- facelet_set_id(facelet_new, i+1);
+ facelet_set_id(facelet_new, ++facemgr->cur_static_id);
facelet_set_status(facelet_new, FACELET_STATUS_CLEAN);
char buf[MAXSZ_FACELET];
@@ -1493,9 +1608,11 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
case FACELET_EVENT_GET:
/* Insert new facelet in cached */
+ DEBUG("[facemgr_on_event] GET NEW %s", facelet_s);
rc = facemgr_process_facelet_get(facemgr, facelet_in);
if (rc == 0)
remove_facelet = false;
+ dump = false;
if (rc == -1) {
ERROR("[facemgr_on_event] Error processing GET event");
goto ERR;
@@ -1506,20 +1623,21 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
/* Might be because we previously ignored the facelet... */
//ERROR("[facemgr_on_event] Unexpected UPDATE... face does not exist");
//goto ERR;
+ DEBUG("[facemgr_on_event] UPDATE NEW %s", facelet_s);
INFO("Ignored UPDATE for non-existing face");
break;
case FACELET_EVENT_DELETE:
+ DEBUG("[facemgr_on_event] DELETE NEW %s", facelet_s);
ERROR("[facemgr_on_event] Unexpected DELETE... face does not exist");
goto ERR;
case FACELET_EVENT_UNDEFINED:
+ case FACELET_EVENT_N:
ERROR("[facemgr_on_event] Unexpected UNDEFINED event.");
+ ret = -1;
goto ERR;
- default: /* XXX Some events should be deprecated */
- ERROR("[facemgr_on_event] Deprecated event");
- goto ERR;
}
goto DUMP_CACHE;
}
@@ -1534,8 +1652,14 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
* reconciliation by sending appropriate updates to the forwarder
*/
facelet_t * facelet = cached_facelets[i];
+
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
+ //DEBUG("Facelet from cache #%d %s", i, facelet_s);
+
switch(facelet_get_event(facelet_in)) {
case FACELET_EVENT_CREATE:
+ DEBUG("[facemgr_on_event] CREATE EXISTING %s", facelet_s);
// This case will occur when we try to re-create existing faces,
// eg. in the situation of a forwarder restarting.
// likely this occurs when the interface receives a (potentially new) address
@@ -1552,13 +1676,17 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
continue;
case FACELET_EVENT_GET: /* should be an INFORM message */
- // FIXME, this might occur if the forwarder restarts and we
- // resync faces...
- ERROR("[facemgr_on_event] GET event for a face that already exists...");
- ret = -1;
+ /*
+ * This happens due to polling of the forwarder (or when it
+ * restarts)
+ */
+ DEBUG("[facemgr_on_event] GET EXISTING %s", facelet_s);
+ //ERROR("[facemgr_on_event] GET event for a face that already exists...");
+ dump = false;
continue;
case FACELET_EVENT_UPDATE:
+ DEBUG("[facemgr_on_event] UPDATE EXISTING %s", facelet_s);
if (facelet_merge(facelet, facelet_in) < 0) {
ERROR("[facemgr_on_event] Error merging facelets");
continue;
@@ -1570,6 +1698,7 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
continue;
case FACELET_EVENT_DELETE:
+ DEBUG("[facemgr_on_event] DELETE EXISTING %s", facelet_s);
if (facelet_merge(facelet, facelet_in) < 0) {
ERROR("[facemgr_on_event] Error merging facelets");
continue;
@@ -1580,9 +1709,12 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
}
continue;
- default: /* XXX Some events should be deprecated */
- ERROR("[facemgr_on_event] Deprecated event");
+ case FACELET_EVENT_UNDEFINED:
+ case FACELET_EVENT_N:
+ ERROR("[facemgr_on_event] Unexpected UNDEFINED event.");
ret = -1;
+ goto ERR;
+
}
}
@@ -1593,11 +1725,13 @@ ERR:
DUMP_CACHE:
#if 1
- DEBUG(" <CACHE>");
- facelet_set_dump(facemgr->facelet_cache);
- DEBUG(" </CACHE>");
- DEBUG("</EVENT ret=%d>", ret);
- DEBUG("----------------------------------");
+ if (dump) {
+ DEBUG(" <CACHE>");
+ facelet_set_dump(facemgr->facelet_cache);
+ DEBUG(" </CACHE>");
+ DEBUG("</EVENT ret=%d>", ret);
+ DEBUG("----------------------------------");
+ }
#endif
free(cached_facelets);
diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c
index 7a34b18c8..a7a1fd3ae 100644
--- a/ctrl/facemgr/src/facelet.c
+++ b/ctrl/facemgr/src/facelet.c
@@ -229,7 +229,8 @@ facelet_create_from_face(face_t * face)
/* Attribute : netdevice */
/* NOTE index is not set */
if (IS_VALID_NETDEVICE(face->netdevice)) {
- facelet->netdevice = face->netdevice;
+ /* /!\ A face has only the netdevice name */
+ netdevice_set_name(&facelet->netdevice, face->netdevice.name);
facelet->netdevice_status = FACELET_ATTR_STATUS_CLEAN;
} else {
facelet->netdevice_status = FACELET_ATTR_STATUS_UNSET;
@@ -240,7 +241,7 @@ facelet_create_from_face(face_t * face)
if (facelet->netdevice_type != NETDEVICE_TYPE_UNDEFINED) {
facelet->netdevice_type_status = FACELET_ATTR_STATUS_CLEAN;
} else {
- facelet->netdevice = NETDEVICE_EMPTY;
+ facelet->netdevice_type = NETDEVICE_TYPE_UNDEFINED;
facelet->netdevice_type_status = FACELET_ATTR_STATUS_UNSET;
}
@@ -407,13 +408,32 @@ facelet_dup(const facelet_t * current_facelet)
} else {
for (unsigned i = 0; i < n; i++) {
hicn_route_t * route = route_array[i];
- route_set_add(facelet->routes, route);
+ hicn_route_t * new_route = hicn_route_dup(route);
+ if (!new_route)
+ goto ERR_ROUTE;
+ route_set_add(facelet->routes, new_route);
}
}
free(route_array);
return facelet;
+ERR_ROUTE:
+ {
+ /* Free all routes */
+ hicn_route_t ** new_route_array;
+ int n = route_set_get_array(facelet->routes, &new_route_array);
+ if (n < 0) {
+ ERROR("[facelet_free] Error getting route set associated to facelet");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hicn_route_t * new_route = new_route_array[i];
+ hicn_route_free(new_route);
+ }
+ }
+ free(route_array);
+ facelet_free(facelet);
+ }
ERR_CREATE:
return NULL;
}
@@ -489,7 +509,6 @@ do {
} \
} while(0)
-/* facelet_match is the incoming one */
bool
facelet_equals(const facelet_t * facelet1, const facelet_t * facelet2)
{
diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
index 945b60af2..1b73c694f 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;
@@ -254,8 +320,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) {
@@ -393,38 +461,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 = {
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
index b3032d0f3..d6bb282cb 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -599,6 +599,7 @@ int hc_route_parse(void * in, hc_route_t * route);
int hc_route_create(hc_sock_t * s, hc_route_t * route);
int hc_route_delete(hc_sock_t * s, hc_route_t * route);
int hc_route_list(hc_sock_t * s, hc_data_t ** pdata);
+int hc_route_list_async(hc_sock_t * s);
#define foreach_route(VAR, data) foreach_type(hc_route_t, VAR, data)
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
index f67cccf93..2b96d22cc 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
@@ -31,6 +31,7 @@ typedef struct hicn_route_s hicn_route_t;
#define MAXSZ_ROUTE MAXSZ_ROUTE_ + NULLTERM
hicn_route_t * hicn_route_create(ip_prefix_t * prefix, face_id_t face_id, route_cost_t cost);
+hicn_route_t * hicn_route_dup(const hicn_route_t * route);
void hicn_route_free(hicn_route_t * route);
int hicn_route_cmp(const hicn_route_t * route1, const hicn_route_t * route2);
diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c
index 6c9b54a92..74a8821e2 100644
--- a/ctrl/libhicnctrl/src/api.c
+++ b/ctrl/libhicnctrl/src/api.c
@@ -715,7 +715,6 @@ hc_sock_process(hc_sock_t * s, hc_data_t ** data)
available -= num_chunks * s->cur_request->data->in_element_size;
s->roff += num_chunks * s->cur_request->data->in_element_size;
if (s->remaining == 0) {
- printf("done, sock map remove\n");
if (hc_sock_map_remove(s->map, s->cur_request->seq, NULL) < 0) {
ERROR("[hc_sock_process] Error removing request from map");
return -1;
@@ -856,7 +855,6 @@ hc_execute_command(hc_sock_t * s, hc_msg_t * msg, size_t msg_len,
ERROR("[hc_execute_command] Could not get next sequence number");
goto ERR_SEQ;
}
- printf("Sending message with seq %d\n", seq);
/* Create state used to process the request */
hc_sock_request_t * request = NULL;
@@ -867,7 +865,6 @@ hc_execute_command(hc_sock_t * s, hc_msg_t * msg, size_t msg_len,
}
/* Add state to map */
- printf("sock map add\n");
if (hc_sock_map_add(s->map, seq, request) < 0) {
ERROR("[hc_execute_command] Error adding request state to map");
goto ERR_MAP;
@@ -1815,9 +1812,9 @@ hc_route_list(hc_sock_t * s, hc_data_t ** pdata)
}
int
-hc_route_list_async(hc_sock_t * s, hc_data_t ** pdata)
+hc_route_list_async(hc_sock_t * s)
{
- return _hc_route_list(s, pdata, true);
+ return _hc_route_list(s, NULL, true);
}
/* ROUTE PARSE */
@@ -1978,6 +1975,8 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool
} else {
memset(connection->name, 0, SYMBOLIC_NAME_LEN);
}
+ snprintf(connection->interface_name, INTERFACE_LEN, "%s",
+ f->netdevice.name);
break;
default:
return -1;
@@ -2366,7 +2365,7 @@ hc_connection_parse_to_face(void * in, hc_face_t * face)
int
-hc_face_list_async(hc_sock_t * s) //, hc_data_t ** pdata)
+hc_face_list_async(hc_sock_t * s)
{
struct {
header_control_message hdr;
@@ -2451,9 +2450,10 @@ hc_face_snprintf(char * s, size_t size, hc_face_t * face)
if (rc < 0)
return rc;
- return snprintf(s, size, "[#%d %s] %s %s %s %s/%s (%s)",
+ return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s (%s)",
face->id,
face->name,
+ face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
face_type_str[face->face.type],
local,
remote,
@@ -2461,9 +2461,10 @@ hc_face_snprintf(char * s, size_t size, hc_face_t * face)
face_state_str[face->face.admin_state],
tags);
#else
- return snprintf(s, size, "[#%d %s] %s %s %s %s/%s",
+ return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s",
face->id,
face->name,
+ face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
face_type_str[face->face.type],
local,
remote,
diff --git a/ctrl/libhicnctrl/src/cli.c b/ctrl/libhicnctrl/src/cli.c
index a171f7045..879454c3a 100644
--- a/ctrl/libhicnctrl/src/cli.c
+++ b/ctrl/libhicnctrl/src/cli.c
@@ -379,7 +379,7 @@ parse_options(int argc, char *argv[], hc_command_t * command)
case OBJECT_FACE:
switch(command->action) {
case ACTION_CREATE:
- if ((argc - optind != 6) && (argc - optind != 7)) {
+ if ((argc - optind != 5) && (argc - optind != 6)) {
usage_face_create(argv[0], true, false);
goto ERR_PARAM;
}
diff --git a/ctrl/libhicnctrl/src/face.c b/ctrl/libhicnctrl/src/face.c
index 41ff58f81..0e25890da 100644
--- a/ctrl/libhicnctrl/src/face.c
+++ b/ctrl/libhicnctrl/src/face.c
@@ -129,6 +129,7 @@ netdevice_get_name(const netdevice_t * netdevice, const char ** name)
int
netdevice_set_name(netdevice_t * netdevice, const char * name)
{
+ memset(netdevice->name, 0, sizeof(netdevice->name));
int rc = snprintf(netdevice->name, IFNAMSIZ, "%s", name);
if (rc < 0)
return -1;
diff --git a/ctrl/libhicnctrl/src/route.c b/ctrl/libhicnctrl/src/route.c
index 61434871b..703b4763f 100644
--- a/ctrl/libhicnctrl/src/route.c
+++ b/ctrl/libhicnctrl/src/route.c
@@ -43,6 +43,16 @@ hicn_route_create(ip_prefix_t * prefix, face_id_t face_id, route_cost_t cost)
return route;
}
+hicn_route_t *
+hicn_route_dup(const hicn_route_t * route)
+{
+ hicn_route_t * new_route = malloc(sizeof(hicn_route_t));
+ if (!route)
+ return NULL;
+ memcpy(new_route, route, sizeof(hicn_route_t));
+ return new_route;
+}
+
void hicn_route_free(hicn_route_t * route)
{
free(route);
diff --git a/lib/includes/hicn/util/array.h b/lib/includes/hicn/util/array.h
index ab8852ed8..56cfcad8b 100644
--- a/lib/includes/hicn/util/array.h
+++ b/lib/includes/hicn/util/array.h
@@ -167,9 +167,10 @@ NAME ## _get(const NAME ## _t * array, const T search, T * element)
{ \
assert(element); \
for (unsigned i = 0; i < array->size; i++) \
- if (CMP(search, array->elements[i]) == 0) \
+ if (CMP(search, array->elements[i]) == 0) { \
*element = array->elements[i]; \
return 0; \
+ } \
/* Not found */ \
*element = NULL; \
return 0; \
diff --git a/lib/includes/hicn/util/set.h b/lib/includes/hicn/util/set.h
index c1f43918b..c7dd7bf09 100644
--- a/lib/includes/hicn/util/set.h
+++ b/lib/includes/hicn/util/set.h
@@ -138,10 +138,12 @@ NAME ## _free(NAME ## _t * set) \
int \
NAME ## _add(NAME ## _t * set, const T element) \
{ \
+ T * found = tfind(element, &set->root, (cmp_t)CMP); \
void * ptr = tsearch(element, &set->root, (cmp_t)CMP); \
if (!ptr) \
return -1; \
- set->size++; \
+ if (!found) \
+ set->size++; \
return 0; \
} \
\
@@ -214,7 +216,7 @@ int \
NAME ## _get_array(const NAME ## _t * set, T ** element) \
{ \
if (!element) \
- goto END; \
+ goto END; \
*element = malloc(set->size * sizeof(T)); \
if (!*element) \
return -1; \