aboutsummaryrefslogtreecommitdiffstats
path: root/ctrl/facemgr/src
diff options
context:
space:
mode:
Diffstat (limited to 'ctrl/facemgr/src')
-rw-r--r--ctrl/facemgr/src/api.c269
-rw-r--r--ctrl/facemgr/src/facelet.c121
-rw-r--r--ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c268
3 files changed, 552 insertions, 106 deletions
diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c
index 23ca2f2ae..dfb23db3b 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;
@@ -417,11 +420,13 @@ facemgr_create_interface(facemgr_t * facemgr, const char * name, const char * ty
*pinterface = interface;
return 0;
+
+ //interface_finalize(interface);
+ERR_INIT:
+ interface_map_remove(facemgr->interface_map, interface->name, NULL);
ERR_MAP_ADD:
free(interface_map_data);
ERR_MAP_DATA:
- interface_finalize(interface);
-ERR_INIT:
interface_free(interface);
ERR_CREATE:
if (pinterface)
@@ -489,6 +494,7 @@ int facemgr_query_bonjour(facemgr_t * facemgr, netdevice_t * netdevice)
DEBUG("sending event to bonjour interface");
/* Send an event to the interface (GET ?) */
+ // XXX error handling
return interface_on_event(bj, NULL);
}
#endif /* __linux__ */
@@ -506,8 +512,10 @@ int facemgr_query_android_utility(facemgr_t * facemgr, netdevice_t netdevice)
goto ERR_ND;
rc = interface_on_event(facemgr->au, facelet);
- if (rc < 0)
+ if (rc < 0) {
+ // XXX error handling
goto ERR_EVENT;
+ }
return 0;
@@ -533,6 +541,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 +576,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 +695,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");
@@ -955,7 +972,7 @@ int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet)
netdevice_t netdevice = NETDEVICE_EMPTY;
int rc = facelet_get_netdevice(facelet, &netdevice);
if (rc < 0) {
- ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice from facelet");
+ ERROR("[facemgr_assign_face_type] Error retrieving netdevice from facelet");
return -1;
}
@@ -967,7 +984,7 @@ int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet)
*/
rc = facelet_get_netdevice_type(facelet, &netdevice_type);
if (rc < 0) {
- ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from facelet");
+ ERROR("[facemgr_assign_face_type] Error retrieving netdevice_type from facelet");
return -2;
}
#endif /* WITH_ANDROID_UTILITY */
@@ -989,6 +1006,7 @@ int
facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet)
{
int rc;
+ facelet_error_reason_t reason = FACELET_ERROR_REASON_INTERNAL_ERROR;
switch(facelet_get_status(facelet)) {
case FACELET_STATUS_UNCERTAIN:
@@ -1046,8 +1064,10 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet)
case FACELET_STATUS_CREATE:
facelet_set_event(facelet, FACELET_EVENT_CREATE);
- if (interface_on_event(facemgr->hl, facelet) < 0) {
+ rc = interface_on_event(facemgr->hl, facelet);
+ if (rc < 0) {
ERROR("[facemgr_process_facelet] Failed to create face");
+ reason = -rc;
goto ERR;
}
@@ -1058,8 +1078,10 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet)
case FACELET_STATUS_UPDATE:
facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- if (interface_on_event(facemgr->hl, facelet) < 0) {
+ rc = interface_on_event(facemgr->hl, facelet);
+ if (rc < 0) {
ERROR("[facemgr_process_facelet] Failed to update face");
+ reason = -rc;
goto ERR;
}
@@ -1069,8 +1091,10 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet)
case FACELET_STATUS_DELETE:
facelet_set_event(facelet, FACELET_EVENT_DELETE);
- if (interface_on_event(facemgr->hl, facelet) < 0) {
+ rc = interface_on_event(facemgr->hl, facelet);
+ if (rc < 0) {
ERROR("[facemgr_process_facelet] Failed to delete face");
+ reason = -rc;
goto ERR;
}
@@ -1080,6 +1104,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);
@@ -1100,11 +1126,11 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet)
goto ERR;
}
- facelet_set_status_error(facelet, false);
+ facelet_unset_error(facelet);
return 0;
ERR:
- facelet_set_status_error(facelet, true);
+ facelet_set_error(facelet, reason);
return -1;
}
@@ -1120,11 +1146,12 @@ facemgr_reattempt_timeout(facemgr_t * facemgr, int fd, void * data)
int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
if (n < 0) {
ERROR("[facemgr_reattempt_timeout] Could not retrieve facelets in cache");
+ has_error = true;
} else {
for (unsigned i = 0; i < n; i++) {
facelet_t * facelet = facelet_array[i];
- if (!facelet_get_status_error(facelet))
+ if (!facelet_get_error(facelet))
continue;
char buf[MAXSZ_FACELET];
@@ -1135,7 +1162,7 @@ facemgr_reattempt_timeout(facemgr_t * facemgr, int fd, void * data)
has_error = true;
continue;
}
- facelet_set_status_error(facelet, false);
+ facelet_unset_error(facelet);
}
free(facelet_array);
}
@@ -1227,6 +1254,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 +1340,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;
+ }
+ 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);
}
- return -2;
+
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
+ return facelet_set_add(facemgr->facelet_cache, facelet);
}
/**
@@ -1341,6 +1462,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 +1496,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 +1536,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 +1600,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 +1621,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 +1636,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 +1665,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 +1689,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 +1711,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 +1722,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 +1738,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);
@@ -1684,41 +1831,54 @@ facemgr_bootstrap(facemgr_t * facemgr)
DEBUG("Registering interfaces...");
rc = interface_register(&hicn_light_ops);
if (rc < 0) {
- ERROR("Could not register interfaces");
+ ERROR("[facemgr_bootstrap] Error registering hicn_light interface");
goto ERR_REGISTER;
}
#ifdef __APPLE__
rc = interface_register(&network_framework_ops);
- if (rc < 0)
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering network_framework interface");
goto ERR_REGISTER;
+ }
#endif /* __APPLE__ */
#ifdef __linux__
rc = interface_register(&netlink_ops);
- if (rc < 0)
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering netlink interface");
goto ERR_REGISTER;
+ }
+
rc = interface_register(&bonjour_ops);
- if (rc < 0)
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering bonjour interface");
goto ERR_REGISTER;
+ }
#endif /* __linux__ */
#ifdef WITH_ANDROID_UTILITY
rc = interface_register(&android_utility_ops);
- if (rc < 0)
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering android_utility interface");
goto ERR_REGISTER;
+ }
#endif /* WITH_ANDROID_UTILITY */
#ifdef WITH_EXAMPLE_DUMMY
rc = interface_register(&dummy_ops);
- if (rc < 0)
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering dummy interface");
goto ERR_REGISTER;
+ }
#endif
#ifdef WITH_EXAMPLE_UPDOWN
rc = interface_register(&updown_ops);
- if (rc < 0)
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering updown interface");
goto ERR_REGISTER;
+ }
#endif
rc = facemgr_create_interface(facemgr, "hl", "hicn_light", NULL, &facemgr->hl);
@@ -1776,7 +1936,6 @@ facemgr_bootstrap(facemgr_t * facemgr)
return 0;
- /* FIXME facemgr_delete_interface */
#ifdef WITH_EXAMPLE_UPDOWN
facemgr_delete_interface(facemgr, facemgr->updown);
ERR_UPDOWN_CREATE:
diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c
index 7a34b18c8..929005f57 100644
--- a/ctrl/facemgr/src/facelet.c
+++ b/ctrl/facemgr/src/facelet.c
@@ -47,15 +47,19 @@ const char * face_type_encap_str[] = {
#define FACEMGR_FACE_TYPE_STR(x) \
face_type_layer_str[x.layer], face_type_encap_str[x.encap]
-
const char * facelet_status_str[] = {
#define _(x) [FACELET_STATUS_ ## x] = STRINGIZE(x),
foreach_facelet_status
#undef _
};
-/* Facelet attribute status */
+const char * facelet_error_reason_str[] = {
+#define _(x) [FACELET_ERROR_REASON_ ## x] = STRINGIZE(x),
+ foreach_facelet_error_reason
+#undef _
+};
+/* Facelet attribute status */
const char * facelet_attr_status_str[] = {
#define _(x, str) [FACELET_ATTR_STATUS_ ## x] = STRINGIZE(x),
@@ -85,7 +89,7 @@ struct facelet_s {
facelet_status_t status;
- bool status_error;
+ int error;
facelet_event_t event;
@@ -120,10 +124,13 @@ facelet_create()
facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET;
facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET;
facelet->state_status = FACELET_ATTR_STATUS_UNSET;
+#ifdef WITH_POLICY
+ facelet->priority_status = FACELET_ATTR_STATUS_UNSET;
+#endif /* WITH_POLICY */
facelet->face_type_status = FACELET_ATTR_STATUS_UNSET;
facelet->status = FACELET_STATUS_UNDEFINED;
- facelet->status_error = false;
+ facelet->error = 0;
facelet->bj_done = false;
facelet->au_done = false;
@@ -229,7 +236,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 +248,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;
}
@@ -307,6 +315,16 @@ facelet_create_from_face(face_t * face)
facelet->state_status = FACELET_ATTR_STATUS_UNSET;
}
+#ifdef WITH_POLICY
+ /* Attribute : priority */
+ if (face->priority > 0) {
+ facelet->priority = face->priority;
+ facelet->priority_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->priority_status = FACELET_ATTR_STATUS_UNSET;
+ }
+#endif /* WITH_POLICY */
+
/* Attribute : face_type */
if ((face->type != FACE_TYPE_UNDEFINED) && (face->type != FACE_TYPE_N)) {
switch(face->type) {
@@ -330,7 +348,7 @@ facelet_create_from_face(face_t * face)
/* Status */
facelet->status = FACELET_STATUS_CLEAN;
- facelet->status_error = false;
+ facelet->error = 0;
/* TODO Consistency check between face type and found attributes */
if (facelet_validate_face(facelet) < 0)
@@ -407,13 +425,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 +526,6 @@ do {
} \
} while(0)
-/* facelet_match is the incoming one */
bool
facelet_equals(const facelet_t * facelet1, const facelet_t * facelet2)
{
@@ -786,6 +822,15 @@ facelet_get_face(const facelet_t * facelet, face_t ** pface)
face->state = FACE_STATE_UP;
}
+#ifdef WITH_POLICY
+ /* Priority */
+ if (facelet_has_priority(facelet)) {
+ if (facelet_get_priority(facelet, &face->priority) < 0)
+ goto ERR;
+ } else {
+ face->priority = 0;
+ }
+
/* Tags */
/* - based on netdevice type */
@@ -816,6 +861,7 @@ facelet_get_face(const facelet_t * facelet, face_t ** pface)
}
}
face->tags = tags;
+#endif /* WITH_POLICY */
*pface = face;
@@ -852,15 +898,35 @@ facelet_set_status(facelet_t * facelet, facelet_status_t status)
}
void
-facelet_set_status_error(facelet_t * facelet, bool value)
+facelet_set_error(facelet_t * facelet, facelet_error_reason_t reason)
{
- facelet->status_error = value;
+ facelet->error++;
+ switch(reason) {
+ case FACELET_ERROR_REASON_UNSPECIFIED_ERROR:
+ case FACELET_ERROR_REASON_INTERNAL_ERROR:
+ case FACELET_ERROR_REASON_PERMISSION_DENIED:
+ if (facelet->error >= FACELET_MAX_ERRORS)
+ facelet_set_status(facelet, FACELET_STATUS_IGNORED);
+ break;
+ case FACELET_ERROR_REASON_FORWARDER_OFFLINE:
+ break;
+ case FACELET_ERROR_REASON_UNDEFINED:
+ case FACELET_ERROR_REASON_N:
+ ERROR("facelet_set_error] Unexpected error reason");
+ break;
+ }
+}
+
+void
+facelet_unset_error(facelet_t * facelet)
+{
+ facelet->error = 0;
}
bool
-facelet_get_status_error(const facelet_t * facelet)
+facelet_get_error(const facelet_t * facelet)
{
- return facelet->status_error;
+ return facelet->error;
}
void
@@ -934,7 +1000,7 @@ facelet_snprintf(char * s, size_t size, const facelet_t * facelet)
/* Header + key attributes (netdevice + family) */
rc = snprintf(cur, s + size - cur, "<Facelet %s %s (%s)",
facelet_status_str[facelet->status],
- facelet_get_status_error(facelet) ? "/!\\" : "",
+ facelet_get_error(facelet) ? "/!\\" : "",
(facelet->family == AF_INET) ? "AF_INET" :
(facelet->family == AF_INET6) ? "AF_INET6" :
(facelet->family == AF_UNSPEC) ? "AF_UNSPEC" :
@@ -1062,6 +1128,18 @@ facelet_snprintf(char * s, size_t size, const facelet_t * facelet)
return cur - s;
}
+#ifdef WITH_POLICY
+ /* Priority */
+ if (facelet_has_priority(facelet)) {
+ rc = snprintf(cur, s + size - cur, " priority=%d", facelet->priority);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+ }
+#endif /* WITH_POLICY */
+
/* Face type */
if (facelet_has_face_type(facelet)) {
rc = snprintf(cur, s + size - cur, " face_type=LAYER%s/%s",
@@ -1284,6 +1362,19 @@ int facelet_snprintf_json(char * s, size_t size, const facelet_t * facelet, int
return cur - s;
}
+#ifdef WITH_POLICY
+ /* Priority */
+ if (facelet_has_priority(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent+1), "",
+ "\"priority\"", facelet->priority);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+ }
+#endif /* WITH_POLICY */
+
if (facelet_has_face_type(facelet)) {
rc = snprintf(cur, s + size - cur, "%*s%s: \"LAYER%s/%s\",\n", 4 * (indent+1), "",
"\"face_type\"",
@@ -1298,7 +1389,7 @@ int facelet_snprintf_json(char * s, size_t size, const facelet_t * facelet, int
/* Status error */
rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\"\n", 4 * (indent+1), "",
"\"error\"",
- facelet_get_status_error(facelet) ? "true" : "false");
+ facelet_get_error(facelet) ? "true" : "false");
if (rc < 0)
return rc;
cur += rc;
diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
index 945b60af2..a6cd44fe0 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;
@@ -228,9 +294,12 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
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
@@ -238,11 +307,13 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
*/
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;
}
@@ -254,12 +325,13 @@ 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.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", hc_face.id);
@@ -268,6 +340,7 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
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) {
@@ -326,7 +399,6 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
continue;
}
}
-
}
break;
@@ -338,12 +410,13 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
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;
}
break;
case FACELET_EVENT_UPDATE:
- /* Currently, only admin_state is supported */
+ /* 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;
@@ -351,10 +424,12 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
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];
@@ -364,67 +439,188 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
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;
}
INFO("Admin state updated");
}
+ 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");
+ 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;
+ }
+
+ if (hc_connection_set_priority(data->s, conn_id_or_name, priority) < 0) {
+ ERROR("Failed to update priority");
+ goto ERR;
+ }
+ INFO("Priority updated");
+ }
break;
default:
ERROR("Unknown event %s\n", facelet_event_str[facelet_get_event(facelet)]);
/* Unsupported events */
+ ret = -FACELET_ERROR_REASON_INTERNAL_ERROR;
goto ERR;
}
- face_free(face);
- return ret;
-
ERR:
face_free(face);
ERR_FACE:
- return -1;
+ 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;
- 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 */
+ 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);
+ 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 have a queue of pending data elements per active query */
+ /* We can ignore faces on localhost */
- return 0;
+ 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 = {