aboutsummaryrefslogtreecommitdiffstats
path: root/ctrl
diff options
context:
space:
mode:
Diffstat (limited to 'ctrl')
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/facelet.h46
-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
-rw-r--r--ctrl/libhicnctrl/examples/create_face.c3
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h5
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/commands.h13
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/face.h1
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/route.h1
-rw-r--r--ctrl/libhicnctrl/src/api.c85
-rw-r--r--ctrl/libhicnctrl/src/cli.c2
-rw-r--r--ctrl/libhicnctrl/src/face.c1
-rw-r--r--ctrl/libhicnctrl/src/route.c10
13 files changed, 699 insertions, 126 deletions
diff --git a/ctrl/facemgr/includes/hicn/facemgr/facelet.h b/ctrl/facemgr/includes/hicn/facemgr/facelet.h
index 476858eff..a0318b206 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/facelet.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/facelet.h
@@ -33,6 +33,8 @@
#define MAXSZ_FACELET 1024
+#define FACELET_MAX_ERRORS 10
+
/* NOTE: Any test should be sufficient */
#define IS_VALID_NETDEVICE(netdevice) ((netdevice.index != 0) && (netdevice.name[0] != '\0'))
@@ -116,6 +118,23 @@ typedef enum {
extern const char * facelet_status_str[];
+/* Facelet error reason */
+#define foreach_facelet_error_reason \
+ _(UNDEFINED) \
+ _(UNSPECIFIED_ERROR) \
+ _(FORWARDER_OFFLINE) \
+ _(PERMISSION_DENIED) \
+ _(INTERNAL_ERROR) \
+ _(N)
+
+typedef enum {
+#define _(x) FACELET_ERROR_REASON_ ## x,
+ foreach_facelet_error_reason
+#undef _
+} facelet_error_reason_t;
+
+extern const char * facelet_error_reason_str[];
+
/* Facelet attribute status */
/*
@@ -142,6 +161,20 @@ extern const char * facelet_attr_status_str_short[];
/* Facelet attribute */
+#ifdef WITH_POLICY
+#define foreach_facelet_attr \
+ _(netdevice_type_t, netdevice_type) \
+ _(netdevice_t, netdevice) \
+ _(int, family) \
+ _(ip_address_t, local_addr) \
+ _(u16, local_port) \
+ _(ip_address_t, remote_addr) \
+ _(u16, remote_port) \
+ _(face_state_t, admin_state) \
+ _(face_state_t, state) \
+ _(u32, priority) \
+ _(facemgr_face_type_t, face_type)
+#else
#define foreach_facelet_attr \
_(netdevice_type_t, netdevice_type) \
_(netdevice_t, netdevice) \
@@ -153,6 +186,7 @@ extern const char * facelet_attr_status_str_short[];
_(face_state_t, admin_state) \
_(face_state_t, state) \
_(facemgr_face_type_t, face_type)
+#endif /* WITH_POLICY */
#define foreach_facelet_event \
_(UNDEFINED) \
@@ -160,13 +194,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
@@ -234,8 +261,9 @@ int facelet_merge(facelet_t * facelet, const facelet_t * facelet_to_merge);
facelet_status_t facelet_get_status(const facelet_t * facelet);
void facelet_set_status(facelet_t * facelet, facelet_status_t status);
-void facelet_set_status_error(facelet_t * facelet, bool value);
-bool facelet_get_status_error(const facelet_t * facelet);
+void facelet_set_error(facelet_t * facelet, facelet_error_reason_t reason);
+void facelet_unset_error(facelet_t * facelet);
+bool facelet_get_error(const facelet_t * facelet);
void facelet_set_bj_done(facelet_t * facelet);
void facelet_unset_bj_done(facelet_t * facelet);
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 = {
diff --git a/ctrl/libhicnctrl/examples/create_face.c b/ctrl/libhicnctrl/examples/create_face.c
index dcacaeff1..5f92f5906 100644
--- a/ctrl/libhicnctrl/examples/create_face.c
+++ b/ctrl/libhicnctrl/examples/create_face.c
@@ -107,7 +107,10 @@ int main() {
.remote_port = 6000,
.admin_state = FACE_STATE_UNDEFINED,
.state = FACE_STATE_UNDEFINED,
+#ifdef WITH_POLICY
+ .priority = 0,
.tags = POLICY_TAGS_EMPTY,
+#endif /* WITH_POLICY */
},
};
if (netdevice_set_name(&face.face.netdevice, if_name) < 0) {
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
index b3032d0f3..c9c2f0da8 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -498,6 +498,7 @@ typedef struct {
u16 remote_port; /* .rw */
hc_connection_state_t admin_state; /* .rw */
#ifdef WITH_POLICY
+ uint32_t priority; /* .rw */
policy_tags_t tags; /* .rw */
#endif /* WITH_POLICY */
hc_connection_state_t state; /* .r. */
@@ -523,8 +524,9 @@ int hc_connection_validate(const hc_connection_t * connection);
int hc_connection_cmp(const hc_connection_t * c1, const hc_connection_t * c2);
int hc_connection_parse(void * in, hc_connection_t * connection);
-#ifdef WITH_POLICY
int hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+#ifdef WITH_POLICY
+int hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
#endif /* WITH_POLICY */
#define foreach_connection(VAR, data) foreach_type(hc_connection_t, VAR, data)
@@ -599,6 +601,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/commands.h b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
index a5bc15e8a..520559ccf 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
@@ -75,6 +75,7 @@ typedef enum {
LIST_POLICIES,
REMOVE_POLICY,
UPDATE_CONNECTION,
+ CONNECTION_SET_PRIORITY,
#endif /* WITH_POLICY */
LAST_COMMAND_VALUE
} command_id;
@@ -138,6 +139,7 @@ typedef struct {
uint8_t connectionType;
uint8_t admin_state;
#ifdef WITH_POLICY
+ uint32_t priority;
policy_tags_t tags;
#endif /* WITH_POLICY */
} add_connection_command;
@@ -166,6 +168,9 @@ typedef struct {
uint32_t connid;
uint8_t state;
uint8_t admin_state;
+#ifdef WITH_POLICY
+ uint32_t priority;
+#endif /* WITH_POLICY */
char interfaceName[SYMBOLIC_NAME_LEN];
char connectionName[SYMBOLIC_NAME_LEN];
} list_connections_command;
@@ -335,9 +340,15 @@ typedef struct {
typedef struct {
char symbolicOrConnid[SYMBOLIC_NAME_LEN];
uint8_t admin_state;
+ uint32_t priority;
policy_tags_t tags;
} update_connection_command;
+typedef struct {
+ char symbolicOrConnid[SYMBOLIC_NAME_LEN];
+ uint32_t priority;
+} connection_set_priority_command;
+
#endif /* WITH_POLICY */
//===== size of commands ======
@@ -394,6 +405,8 @@ static inline int payloadLengthDaemon(command_id id) {
return sizeof(remove_policy_command);
case UPDATE_CONNECTION:
return sizeof(update_connection_command);
+ case CONNECTION_SET_PRIORITY:
+ return sizeof(connection_set_priority_command);
#endif /* WITH_POLICY */
case LAST_COMMAND_VALUE:
return 0;
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h
index 5c1fecd55..f0a8045de 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h
@@ -153,6 +153,7 @@ typedef struct {
face_state_t admin_state;
face_state_t state;
#ifdef WITH_POLICY
+ uint32_t priority;
policy_tags_t tags; /**< \see policy_tag_t */
#endif /* WITH_POLICY */
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..14ee69b53 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;
@@ -1272,6 +1269,7 @@ _hc_connection_create(hc_sock_t * s, hc_connection_t * connection, bool async)
.connectionType = (u8)map_to_connection_type[connection->type],
.admin_state = connection->admin_state,
#ifdef WITH_POLICY
+ .priority = connection->priority,
.tags = connection->tags,
#endif /* WITH_POLICY */
}
@@ -1549,6 +1547,7 @@ hc_connection_parse(void * in, hc_connection_t * connection)
.remote_port = ntohs(cmd->connectionData.remotePort),
.admin_state = cmd->connectionData.admin_state,
#ifdef WITH_POLICY
+ .priority = cmd->connectionData.priority,
.tags = cmd->connectionData.tags,
#endif /* WITH_POLICY */
.state = state,
@@ -1649,6 +1648,56 @@ hc_connection_set_admin_state_async(hc_sock_t * s, const char * conn_id_or_name,
return _hc_connection_set_admin_state(s, conn_id_or_name, state, true);
}
+int
+_hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name,
+ uint32_t priority, bool async)
+{
+ int rc;
+ DEBUG("[hc_connection_set_priority] connection_id/name=%s priority=%d async=%s",
+ conn_id_or_name, priority, BOOLSTR(async));
+ struct {
+ header_control_message hdr;
+ connection_set_priority_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = CONNECTION_SET_ADMIN_STATE,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .priority = priority,
+ },
+ };
+ rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_connection_set_priority] Unexpected truncation of symbolic name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = CONNECTION_SET_PRIORITY,
+ .size_in = sizeof(connection_set_priority_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+int
+hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name,
+ uint32_t priority)
+{
+ return _hc_connection_set_priority(s, conn_id_or_name, priority, false);
+}
+
+int
+hc_connection_set_priority_async(hc_sock_t * s, const char * conn_id_or_name,
+ uint32_t priority)
+{
+ return _hc_connection_set_priority(s, conn_id_or_name, priority, true);
+}
+
/*----------------------------------------------------------------------------*
* Routes
*----------------------------------------------------------------------------*/
@@ -1815,9 +1864,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 */
@@ -1927,6 +1976,7 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool
.admin_state = face_state_to_connection_state(f->admin_state),
.state = face_state_to_connection_state(f->state),
#ifdef WITH_POLICY
+ .priority = f->priority,
.tags = f->tags,
#endif /* WITH_POLICY */
};
@@ -1946,6 +1996,7 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool
.admin_state = face_state_to_connection_state(f->admin_state),
.state = face_state_to_connection_state(f->state),
#ifdef WITH_POLICY
+ .priority = f->priority,
.tags = f->tags,
#endif /* WITH_POLICY */
};
@@ -1968,6 +2019,7 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool
.admin_state = face_state_to_connection_state(f->admin_state),
.state = face_state_to_connection_state(f->state),
#ifdef WITH_POLICY
+ .priority = f->priority,
.tags = f->tags,
#endif /* WITH_POLICY */
};
@@ -1978,6 +2030,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;
@@ -2011,6 +2065,7 @@ hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face)
.admin_state = connection_state_to_face_state(connection->admin_state),
.state = connection_state_to_face_state(connection->state),
#ifdef WITH_POLICY
+ .priority = connection->priority,
.tags = connection->tags,
#endif /* WITH_POLICY */
},
@@ -2029,6 +2084,7 @@ hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face)
.admin_state = connection_state_to_face_state(connection->admin_state),
.state = connection_state_to_face_state(connection->state),
#ifdef WITH_POLICY
+ .priority = connection->priority,
.tags = connection->tags,
#endif /* WITH_POLICY */
},
@@ -2046,6 +2102,7 @@ hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face)
.admin_state = connection_state_to_face_state(connection->admin_state),
.state = connection_state_to_face_state(connection->state),
#ifdef WITH_POLICY
+ .priority = connection->priority,
.tags = connection->tags,
#endif /* WITH_POLICY */
},
@@ -2366,7 +2423,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,19 +2508,22 @@ 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 [%d] (%s)",
face->id,
face->name,
+ face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
face_type_str[face->face.type],
local,
remote,
face_state_str[face->face.state],
face_state_str[face->face.admin_state],
+ face->face.priority,
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,
@@ -2473,12 +2533,19 @@ hc_face_snprintf(char * s, size_t size, hc_face_t * face)
}
int
-hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, // XXX wrong identifier
+hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
face_state_t admin_state)
{
return hc_connection_set_admin_state(s, conn_id_or_name, admin_state);
}
+int
+hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name,
+ uint32_t priority)
+{
+ return hc_connection_set_priority(s, conn_id_or_name, priority);
+}
+
/*----------------------------------------------------------------------------*
* Punting
*----------------------------------------------------------------------------*/
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);