diff options
Diffstat (limited to 'ctrl/facemgr/src/api.c')
-rw-r--r-- | ctrl/facemgr/src/api.c | 269 |
1 files changed, 214 insertions, 55 deletions
diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c index 23ca2f2ae..dfb23db3b 100644 --- a/ctrl/facemgr/src/api.c +++ b/ctrl/facemgr/src/api.c @@ -160,6 +160,8 @@ struct facemgr_s { interface_t * updown; #endif int timer_fd; /* Timer used for reattempts */ + + int cur_static_id; /* Used to distinguish static faces (pre-incremented) */ }; int @@ -198,6 +200,7 @@ facemgr_initialize(facemgr_t * facemgr) } facemgr->timer_fd = 0; + facemgr->cur_static_id = 0; return 0; @@ -417,11 +420,13 @@ facemgr_create_interface(facemgr_t * facemgr, const char * name, const char * ty *pinterface = interface; return 0; + + //interface_finalize(interface); +ERR_INIT: + interface_map_remove(facemgr->interface_map, interface->name, NULL); ERR_MAP_ADD: free(interface_map_data); ERR_MAP_DATA: - interface_finalize(interface); -ERR_INIT: interface_free(interface); ERR_CREATE: if (pinterface) @@ -489,6 +494,7 @@ int facemgr_query_bonjour(facemgr_t * facemgr, netdevice_t * netdevice) DEBUG("sending event to bonjour interface"); /* Send an event to the interface (GET ?) */ + // XXX error handling return interface_on_event(bj, NULL); } #endif /* __linux__ */ @@ -506,8 +512,10 @@ int facemgr_query_android_utility(facemgr_t * facemgr, netdevice_t netdevice) goto ERR_ND; rc = interface_on_event(facemgr->au, facelet); - if (rc < 0) + if (rc < 0) { + // XXX error handling goto ERR_EVENT; + } return 0; @@ -533,6 +541,9 @@ int facelet_cache_lookup(const facelet_set_t * facelet_cache, facelet_t * facelet, facelet_t ***cached_facelets) { + assert(facelet); + if (!facelet_has_family(facelet)) + return 0; #if 0 // key is no more sufficient now that we support multiple faces per interface /* * If the facelet is uniquely identified by its key, it is used to perform @@ -565,6 +576,11 @@ facelet_cache_lookup(const facelet_set_t * facelet_cache, facelet_t * facelet, int num_match = 0; for (unsigned i = 0; i < n; i++) { +#if 0 + char facelet_s[MAXSZ_FACELET]; + facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_array[i]); + printf("cache entry #%d/%di = %s\n", i+1, n, facelet_s); +#endif if (!facelet_match(facelet_array[i], facelet)) { continue; } @@ -679,6 +695,7 @@ facemgr_complement_facelet_au(facemgr_t * facemgr, facelet_t * facelet) return -2; netdevice_t netdevice = NETDEVICE_EMPTY; + int rc = facelet_get_netdevice(facelet, &netdevice); if (rc < 0) { ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice from facelet"); @@ -955,7 +972,7 @@ int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet) netdevice_t netdevice = NETDEVICE_EMPTY; int rc = facelet_get_netdevice(facelet, &netdevice); if (rc < 0) { - ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice from facelet"); + ERROR("[facemgr_assign_face_type] Error retrieving netdevice from facelet"); return -1; } @@ -967,7 +984,7 @@ int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet) */ rc = facelet_get_netdevice_type(facelet, &netdevice_type); if (rc < 0) { - ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from facelet"); + ERROR("[facemgr_assign_face_type] Error retrieving netdevice_type from facelet"); return -2; } #endif /* WITH_ANDROID_UTILITY */ @@ -989,6 +1006,7 @@ int facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet) { int rc; + facelet_error_reason_t reason = FACELET_ERROR_REASON_INTERNAL_ERROR; switch(facelet_get_status(facelet)) { case FACELET_STATUS_UNCERTAIN: @@ -1046,8 +1064,10 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet) case FACELET_STATUS_CREATE: facelet_set_event(facelet, FACELET_EVENT_CREATE); - if (interface_on_event(facemgr->hl, facelet) < 0) { + rc = interface_on_event(facemgr->hl, facelet); + if (rc < 0) { ERROR("[facemgr_process_facelet] Failed to create face"); + reason = -rc; goto ERR; } @@ -1058,8 +1078,10 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet) case FACELET_STATUS_UPDATE: facelet_set_event(facelet, FACELET_EVENT_UPDATE); - if (interface_on_event(facemgr->hl, facelet) < 0) { + rc = interface_on_event(facemgr->hl, facelet); + if (rc < 0) { ERROR("[facemgr_process_facelet] Failed to update face"); + reason = -rc; goto ERR; } @@ -1069,8 +1091,10 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet) case FACELET_STATUS_DELETE: facelet_set_event(facelet, FACELET_EVENT_DELETE); - if (interface_on_event(facemgr->hl, facelet) < 0) { + rc = interface_on_event(facemgr->hl, facelet); + if (rc < 0) { ERROR("[facemgr_process_facelet] Failed to delete face"); + reason = -rc; goto ERR; } @@ -1080,6 +1104,8 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet) facelet_unset_local_port(facelet); facelet_unset_remote_addr(facelet); facelet_unset_remote_port(facelet); + facelet_unset_admin_state(facelet); + facelet_unset_state(facelet); facelet_unset_bj_done(facelet); #ifdef WITH_ANDROID_UTILITY facelet_unset_au_done(facelet); @@ -1100,11 +1126,11 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet) goto ERR; } - facelet_set_status_error(facelet, false); + facelet_unset_error(facelet); return 0; ERR: - facelet_set_status_error(facelet, true); + facelet_set_error(facelet, reason); return -1; } @@ -1120,11 +1146,12 @@ facemgr_reattempt_timeout(facemgr_t * facemgr, int fd, void * data) int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array); if (n < 0) { ERROR("[facemgr_reattempt_timeout] Could not retrieve facelets in cache"); + has_error = true; } else { for (unsigned i = 0; i < n; i++) { facelet_t * facelet = facelet_array[i]; - if (!facelet_get_status_error(facelet)) + if (!facelet_get_error(facelet)) continue; char buf[MAXSZ_FACELET]; @@ -1135,7 +1162,7 @@ facemgr_reattempt_timeout(facemgr_t * facemgr, int fd, void * data) has_error = true; continue; } - facelet_set_status_error(facelet, false); + facelet_unset_error(facelet); } free(facelet_array); } @@ -1227,6 +1254,82 @@ facemgr_process_facelet_create(facemgr_t * facemgr, facelet_t * facelet) return 0; } +/* + * \return 0 in case of success and no static facelet was added, 1 if a static + * facelet was added, and -1 in case of error. + */ +int +facemgr_consider_static_facelet(facemgr_t * facemgr, facelet_t * facelet) +{ + /* + * We need to analyze the facelet and eventually: + * - add it in our static list + * - replicate it on multipath interfaces + */ + netdevice_type_t netdevice_type; + if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) + return -1; + + if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) || + (netdevice_type == NETDEVICE_TYPE_LOOPBACK)) + return 0; + + if ((facelet_get_route_array(facelet, NULL) == 0)) + return 0; + + /* + * How to differenciate facelet created by face manager from user + * created ones ? This cannot be a flag in the facelet as it needs + * to work across restarts of the face manager... + * Also we might have two default routes. + * + * TODO: + * - The static one should not be a duplicate of the one we would + * create by default.... + * - This should anyways be detected... + * + * One solution would be to install the default ones as static but + * this requires to implement a priority scheme between some of the + * static routes so that the override mechanism continues to work as + * usual. + * + * Current, we recognize the routes created by default by the face + * maanger thanks to the routing prefixes (a single default route). + */ + + facelet_t * static_facelet = facelet_dup(facelet); + facelet_unset_netdevice(static_facelet); + facelet_unset_netdevice_type(static_facelet); + facelet_unset_local_addr(static_facelet); + facelet_unset_local_port(static_facelet); + + facelet_t * facelet_found = NULL; + if (facelet_array_get(facemgr->static_facelets, static_facelet, &facelet_found) < 0) { + ERROR("[facemgr_consider_static_facelet] Error checking whether static facelet already exists or not"); + return -1; + } + + /* Skip addition if facelet exists */ + if (facelet_found) + return 0; + + if (facelet_array_add(facemgr->static_facelets, static_facelet) < 0) { + ERROR("[facemgr_consider_static_facelet] Could not add facelet to static array"); + facelet_free(static_facelet); + return -1; + } + + char facelet_s[MAXSZ_FACELET]; + int rc = facelet_snprintf(facelet_s, MAXSZ_FACELET, static_facelet); + if (rc >= MAXSZ_FACELET) + ERROR("[facemgr_consider_static_facelet] Unexpected truncation of facelet string"); + if (rc < 0) + ERROR("[facemgr_consider_static_facelet] Error during facelet string output"); + DEBUG("[facemgr_consider_static_facelet] Successfully added facelet to static array %s", facelet_s); + + return 1; +} + /** * \brief Process facelet GET event * \param [in] facemgr - Pointer to the face manager instance @@ -1237,16 +1340,34 @@ facemgr_process_facelet_create(facemgr_t * facemgr, facelet_t * facelet) int facemgr_process_facelet_get(facemgr_t * facemgr, facelet_t * facelet) { - if (facelet_has_netdevice(facelet)) { - netdevice_t netdevice; - if (facelet_get_netdevice(facelet, &netdevice) < 0) - return -1; - if (!IS_VALID_NETDEVICE(netdevice)) - return -2; - facelet_set_status(facelet, FACELET_STATUS_CLEAN); - return facelet_set_add(facemgr->facelet_cache, facelet); + assert(facelet); + + if (!facelet_has_netdevice(facelet)) + return -2; + + netdevice_t netdevice; + if (facelet_get_netdevice(facelet, &netdevice) < 0) + return -1; + if (!IS_VALID_NETDEVICE(netdevice)) + return -2; + facelet_set_status(facelet, FACELET_STATUS_CLEAN); + + int n = facemgr_consider_static_facelet(facemgr, facelet); + if (n < 0) { + ERROR("[facemgr_process_facelet_get] Could not add facelet to static array"); + return -1; + } + if (n == 1) { + /* + * As a static facelet, it receives a new id not to be confused in the + * cache with default facelets + */ + facelet_set_id(facelet, ++facemgr->cur_static_id); } - return -2; + + char facelet_s[MAXSZ_FACELET]; + facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet); + return facelet_set_add(facemgr->facelet_cache, facelet); } /** @@ -1341,6 +1462,9 @@ int facemgr_process_facelet_first_time(facemgr_t * facemgr, facelet_t * facelet) { facelet_set_status(facelet, FACELET_STATUS_UNCERTAIN); + assert(facelet); + char facelet_s[MAXSZ_FACELET]; + facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet); if (facelet_set_add(facemgr->facelet_cache, facelet) < 0) { ERROR("[facemgr_process_facelet_first_time] Error adding facelet to cache"); goto ERR_CACHE; @@ -1372,15 +1496,28 @@ int facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in) { bool remove_facelet = true; + bool dump = true; int ret = 0; int rc; assert(facelet_in); + /* Update Netdevice type */ + if (facelet_has_netdevice(facelet_in) && (!facelet_has_netdevice_type(facelet_in))) { + netdevice_t netdevice = NETDEVICE_EMPTY; + + rc = facelet_get_netdevice(facelet_in, &netdevice); + if (rc < 0) { + ERROR("[facemgr_on_event] Error retrieving netdevice from facelet"); + return -1; + } + facelet_set_netdevice_type(facelet_in, facemgr_get_netdevice_type(facemgr, netdevice.name)); + } + char facelet_s[MAXSZ_FACELET]; facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_in); - DEBUG("EVENT %s", facelet_s); facelet_t ** cached_facelets = NULL; + assert(facelet_in); int n = facelet_cache_lookup(facemgr->facelet_cache, facelet_in, &cached_facelets); if (n < 0) { ERROR("[facemgr_on_event] Error during cache lookup"); @@ -1399,18 +1536,9 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in) * Assumption: we should always see the link before the address * assignment */ + DEBUG("[facemgr_on_event] CREATE NEW %s", facelet_s); assert(!facelet_has_family(facelet_in)); - if (!facelet_has_netdevice_type(facelet_in)) { - netdevice_t netdevice = NETDEVICE_EMPTY; - rc = facelet_get_netdevice(facelet_in, &netdevice); - if (rc < 0) { - ERROR("[facemgr_complement_facelet] Error retrieving netdevice from facelet"); - return -1; - } - facelet_set_netdevice_type(facelet_in, facemgr_get_netdevice_type(facemgr, netdevice.name)); - } - /* Create default v4 and v6 facelets */ facelet_t * facelet_v4 = facelet_dup(facelet_in); if (!facelet_v4) { @@ -1472,7 +1600,7 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in) continue; } /* The id must be different than 0 */ - facelet_set_id(facelet_new, i+1); + facelet_set_id(facelet_new, ++facemgr->cur_static_id); facelet_set_status(facelet_new, FACELET_STATUS_CLEAN); char buf[MAXSZ_FACELET]; @@ -1493,9 +1621,11 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in) case FACELET_EVENT_GET: /* Insert new facelet in cached */ + DEBUG("[facemgr_on_event] GET NEW %s", facelet_s); rc = facemgr_process_facelet_get(facemgr, facelet_in); if (rc == 0) remove_facelet = false; + dump = false; if (rc == -1) { ERROR("[facemgr_on_event] Error processing GET event"); goto ERR; @@ -1506,20 +1636,21 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in) /* Might be because we previously ignored the facelet... */ //ERROR("[facemgr_on_event] Unexpected UPDATE... face does not exist"); //goto ERR; + DEBUG("[facemgr_on_event] UPDATE NEW %s", facelet_s); INFO("Ignored UPDATE for non-existing face"); break; case FACELET_EVENT_DELETE: + DEBUG("[facemgr_on_event] DELETE NEW %s", facelet_s); ERROR("[facemgr_on_event] Unexpected DELETE... face does not exist"); goto ERR; case FACELET_EVENT_UNDEFINED: + case FACELET_EVENT_N: ERROR("[facemgr_on_event] Unexpected UNDEFINED event."); + ret = -1; goto ERR; - default: /* XXX Some events should be deprecated */ - ERROR("[facemgr_on_event] Deprecated event"); - goto ERR; } goto DUMP_CACHE; } @@ -1534,8 +1665,14 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in) * reconciliation by sending appropriate updates to the forwarder */ facelet_t * facelet = cached_facelets[i]; + + char facelet_s[MAXSZ_FACELET]; + facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet); + //DEBUG("Facelet from cache #%d %s", i, facelet_s); + switch(facelet_get_event(facelet_in)) { case FACELET_EVENT_CREATE: + DEBUG("[facemgr_on_event] CREATE EXISTING %s", facelet_s); // This case will occur when we try to re-create existing faces, // eg. in the situation of a forwarder restarting. // likely this occurs when the interface receives a (potentially new) address @@ -1552,13 +1689,17 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in) continue; case FACELET_EVENT_GET: /* should be an INFORM message */ - // FIXME, this might occur if the forwarder restarts and we - // resync faces... - ERROR("[facemgr_on_event] GET event for a face that already exists..."); - ret = -1; + /* + * This happens due to polling of the forwarder (or when it + * restarts) + */ + DEBUG("[facemgr_on_event] GET EXISTING %s", facelet_s); + //ERROR("[facemgr_on_event] GET event for a face that already exists..."); + dump = false; continue; case FACELET_EVENT_UPDATE: + DEBUG("[facemgr_on_event] UPDATE EXISTING %s", facelet_s); if (facelet_merge(facelet, facelet_in) < 0) { ERROR("[facemgr_on_event] Error merging facelets"); continue; @@ -1570,6 +1711,7 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in) continue; case FACELET_EVENT_DELETE: + DEBUG("[facemgr_on_event] DELETE EXISTING %s", facelet_s); if (facelet_merge(facelet, facelet_in) < 0) { ERROR("[facemgr_on_event] Error merging facelets"); continue; @@ -1580,9 +1722,12 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in) } continue; - default: /* XXX Some events should be deprecated */ - ERROR("[facemgr_on_event] Deprecated event"); + case FACELET_EVENT_UNDEFINED: + case FACELET_EVENT_N: + ERROR("[facemgr_on_event] Unexpected UNDEFINED event."); ret = -1; + goto ERR; + } } @@ -1593,11 +1738,13 @@ ERR: DUMP_CACHE: #if 1 - DEBUG(" <CACHE>"); - facelet_set_dump(facemgr->facelet_cache); - DEBUG(" </CACHE>"); - DEBUG("</EVENT ret=%d>", ret); - DEBUG("----------------------------------"); + if (dump) { + DEBUG(" <CACHE>"); + facelet_set_dump(facemgr->facelet_cache); + DEBUG(" </CACHE>"); + DEBUG("</EVENT ret=%d>", ret); + DEBUG("----------------------------------"); + } #endif free(cached_facelets); @@ -1684,41 +1831,54 @@ facemgr_bootstrap(facemgr_t * facemgr) DEBUG("Registering interfaces..."); rc = interface_register(&hicn_light_ops); if (rc < 0) { - ERROR("Could not register interfaces"); + ERROR("[facemgr_bootstrap] Error registering hicn_light interface"); goto ERR_REGISTER; } #ifdef __APPLE__ rc = interface_register(&network_framework_ops); - if (rc < 0) + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering network_framework interface"); goto ERR_REGISTER; + } #endif /* __APPLE__ */ #ifdef __linux__ rc = interface_register(&netlink_ops); - if (rc < 0) + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering netlink interface"); goto ERR_REGISTER; + } + rc = interface_register(&bonjour_ops); - if (rc < 0) + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering bonjour interface"); goto ERR_REGISTER; + } #endif /* __linux__ */ #ifdef WITH_ANDROID_UTILITY rc = interface_register(&android_utility_ops); - if (rc < 0) + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering android_utility interface"); goto ERR_REGISTER; + } #endif /* WITH_ANDROID_UTILITY */ #ifdef WITH_EXAMPLE_DUMMY rc = interface_register(&dummy_ops); - if (rc < 0) + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering dummy interface"); goto ERR_REGISTER; + } #endif #ifdef WITH_EXAMPLE_UPDOWN rc = interface_register(&updown_ops); - if (rc < 0) + if (rc < 0) { + ERROR("[facemgr_bootstrap] Error registering updown interface"); goto ERR_REGISTER; + } #endif rc = facemgr_create_interface(facemgr, "hl", "hicn_light", NULL, &facemgr->hl); @@ -1776,7 +1936,6 @@ facemgr_bootstrap(facemgr_t * facemgr) return 0; - /* FIXME facemgr_delete_interface */ #ifdef WITH_EXAMPLE_UPDOWN facemgr_delete_interface(facemgr, facemgr->updown); ERR_UPDOWN_CREATE: |