diff options
Diffstat (limited to 'ctrl')
-rw-r--r-- | ctrl/facemgr/includes/hicn/facemgr/facelet.h | 46 | ||||
-rw-r--r-- | ctrl/facemgr/src/api.c | 269 | ||||
-rw-r--r-- | ctrl/facemgr/src/facelet.c | 121 | ||||
-rw-r--r-- | ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c | 268 | ||||
-rw-r--r-- | ctrl/libhicnctrl/examples/create_face.c | 3 | ||||
-rw-r--r-- | ctrl/libhicnctrl/includes/hicn/ctrl/api.h | 5 | ||||
-rw-r--r-- | ctrl/libhicnctrl/includes/hicn/ctrl/commands.h | 13 | ||||
-rw-r--r-- | ctrl/libhicnctrl/includes/hicn/ctrl/face.h | 1 | ||||
-rw-r--r-- | ctrl/libhicnctrl/includes/hicn/ctrl/route.h | 1 | ||||
-rw-r--r-- | ctrl/libhicnctrl/src/api.c | 85 | ||||
-rw-r--r-- | ctrl/libhicnctrl/src/cli.c | 2 | ||||
-rw-r--r-- | ctrl/libhicnctrl/src/face.c | 1 | ||||
-rw-r--r-- | ctrl/libhicnctrl/src/route.c | 10 | ||||
-rw-r--r-- | ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c | 16 |
14 files changed, 707 insertions, 134 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), ¶ms, 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); diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c index 4bf266ff5..bb8c5e828 100644 --- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c +++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c @@ -1053,16 +1053,16 @@ static int hicn_face_ip_add_cb(const char *xpath, const sr_val_t *input, struct sockaddr_in sa; inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr)); unsigned char * tmp = (unsigned char *) &sa.sin_addr.s_addr; - memcpy(&msg->payload.local_addr.un.ip4[0],tmp,B32); - msg->payload.local_addr.af = ADDRESS_IP4; + memcpy(&msg->payload.face.local_addr.un.ip4[0],tmp,B32); + msg->payload.face.local_addr.af = ADDRESS_IP4; }else if(strcmp(input[1].data.string_val,"-1")){ void *dst = malloc(sizeof(struct in6_addr)); inet_pton(AF_INET6, input[1].data.string_val, dst); unsigned char * tmp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr; - memcpy(&msg->payload.local_addr.un.ip6[0],tmp,B128); - msg->payload.local_addr.af = ADDRESS_IP6; + memcpy(&msg->payload.face.local_addr.un.ip6[0],tmp,B128); + msg->payload.face.local_addr.af = ADDRESS_IP6; }else{ SRP_LOG_DBG_MSG("Invalid local IP address"); @@ -1074,8 +1074,8 @@ static int hicn_face_ip_add_cb(const char *xpath, const sr_val_t *input, struct sockaddr_in sa; inet_pton(AF_INET, input[2].data.string_val, &(sa.sin_addr)); unsigned char * tmp = (unsigned char *)&sa.sin_addr.s_addr; - memcpy(&msg->payload.remote_addr.un.ip4[0],tmp,B32); - msg->payload.remote_addr.af = ADDRESS_IP4; + memcpy(&msg->payload.face.remote_addr.un.ip4[0],tmp,B32); + msg->payload.face.remote_addr.af = ADDRESS_IP4; }else if(strcmp(input[3].data.string_val,"-1")){ @@ -1083,8 +1083,8 @@ static int hicn_face_ip_add_cb(const char *xpath, const sr_val_t *input, void *dst = malloc(sizeof(struct in6_addr)); inet_pton(AF_INET6, input[3].data.string_val, dst); unsigned char * tmp =(unsigned char *) ((struct in6_addr *)dst)->s6_addr; - memcpy(&msg->payload.remote_addr.un.ip6[0],tmp,B128); - msg->payload.remote_addr.af = ADDRESS_IP6; + memcpy(&msg->payload.face.remote_addr.un.ip6[0],tmp,B128); + msg->payload.face.remote_addr.af = ADDRESS_IP6; }else{ SRP_LOG_DBG_MSG("Invalid local IP address"); |