/******************************************************************************* OpenAirInterface Copyright(c) 1999 - 2014 Eurecom OpenAirInterface is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenAirInterface is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenAirInterface.The full GNU General Public License is included in this distribution in the file called "COPYING". If not, see . Contact Information OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. *******************************************************************************/ /*! \file sgw_lite_context_manager.c * \brief * \author Lionel Gauthier * \company Eurecom * \email: lionel.gauthier@eurecom.fr */ #define SGW_LITE #define SGW_LITE_CONTEXT_MANAGER_C #include #include #include #include #include "tree.h" #include "hashtable.h" #include "intertask_interface.h" #include "mme_config.h" #include "sgw_lite_defs.h" #include "sgw_lite_context_manager.h" #include "sgw_lite.h" extern sgw_app_t sgw_app; //----------------------------------------------------------------------------- static void sgw_lite_display_s11teid2mme_mapping(uint64_t keyP, void *dataP, void* unusedParameterP) //----------------------------------------------------------------------------- { mme_sgw_tunnel_t * mme_sgw_tunnel= NULL; if (dataP != NULL) { mme_sgw_tunnel = (mme_sgw_tunnel_t *)dataP; SPGW_APP_DEBUG("| %u\t<------------->\t%u\n", mme_sgw_tunnel->remote_teid, mme_sgw_tunnel->local_teid); } else { SPGW_APP_DEBUG("INVALID S11 TEID MAPPING FOUND\n"); } } //----------------------------------------------------------------------------- void sgw_lite_display_s11teid2mme_mappings(void) //----------------------------------------------------------------------------- { SPGW_APP_DEBUG("+--------------------------------------+\n"); SPGW_APP_DEBUG("| MME <--- S11 TE ID MAPPINGS ---> SGW |\n"); SPGW_APP_DEBUG("+--------------------------------------+\n"); hashtable_apply_funct_on_elements(sgw_app.s11teid2mme_hashtable, sgw_lite_display_s11teid2mme_mapping, NULL); SPGW_APP_DEBUG("+--------------------------------------+\n"); } //----------------------------------------------------------------------------- static void sgw_lite_display_pdn_connection_sgw_eps_bearers(uint64_t keyP, void *dataP, void* unusedParameterP) //----------------------------------------------------------------------------- { sgw_eps_bearer_entry_t *eps_bearer_entry = NULL; if (dataP != NULL) { eps_bearer_entry = (sgw_eps_bearer_entry_t *)dataP; SPGW_APP_DEBUG("|\t\t\t\t%"PRId64"\t<-> ebi: %u, enb_teid_for_S1u: %u, s_gw_teid_for_S1u_S12_S4_up: %u (tbc)\n", keyP, eps_bearer_entry->eps_bearer_id, eps_bearer_entry->enb_teid_for_S1u, eps_bearer_entry->s_gw_teid_for_S1u_S12_S4_up); } else { SPGW_APP_DEBUG("\t\t\t\tINVALID eps_bearer_entry FOUND\n"); } } //----------------------------------------------------------------------------- static void sgw_lite_display_s11_bearer_context_information(uint64_t keyP, void *dataP, void* unusedParameterP) //----------------------------------------------------------------------------- { s_plus_p_gw_eps_bearer_context_information_t * sp_context_information= NULL; hashtable_rc_t hash_rc; if (dataP != NULL) { sp_context_information = (s_plus_p_gw_eps_bearer_context_information_t *)dataP; SPGW_APP_DEBUG("| KEY %"PRId64": \n", keyP); SPGW_APP_DEBUG("|\tsgw_eps_bearer_context_information: |\n"); //Imsi_t imsi; ///< IMSI (International Mobile Subscriber Identity) is the subscriber permanent identity. SPGW_APP_DEBUG("|\t\timsi_unauthenticated_indicator:\t%u\n", sp_context_information->sgw_eps_bearer_context_information.imsi_unauthenticated_indicator); //char msisdn[MSISDN_LENGTH]; ///< The basic MSISDN of the UE. The presence is dictated by its storage in the HSS. SPGW_APP_DEBUG("|\t\tmme_teid_for_S11: \t%u\n", sp_context_information->sgw_eps_bearer_context_information.mme_teid_for_S11); //ip_address_t mme_ip_address_for_S11; ///< MME IP address the S11 interface. SPGW_APP_DEBUG("|\t\ts_gw_teid_for_S11_S4: \t%u\n", sp_context_information->sgw_eps_bearer_context_information.s_gw_teid_for_S11_S4); //ip_address_t s_gw_ip_address_for_S11_S4; ///< S-GW IP address for the S11 interface and the S4 Interface (control plane). //cgi_t last_known_cell_Id; ///< This is the last location of the UE known by the network SPGW_APP_DEBUG("|\t\tpdn_connection:\n"); SPGW_APP_DEBUG("|\t\t\tapn_in_use: %s\n", sp_context_information->sgw_eps_bearer_context_information.pdn_connection.apn_in_use); SPGW_APP_DEBUG("|\t\t\tdefault_bearer: %u\n", sp_context_information->sgw_eps_bearer_context_information.pdn_connection.default_bearer); SPGW_APP_DEBUG("|\t\t\teps_bearers:\n"); hash_rc = hashtable_apply_funct_on_elements(sp_context_information->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers, sgw_lite_display_pdn_connection_sgw_eps_bearers, NULL); if (hash_rc != HASH_TABLE_OK) { SPGW_APP_DEBUG("Invalid sgw_eps_bearers hashtable for display\n"); } //void *trxn; //uint32_t peer_ip; } else { SPGW_APP_DEBUG("INVALID s_plus_p_gw_eps_bearer_context_information FOUND\n"); } } //----------------------------------------------------------------------------- void sgw_lite_display_s11_bearer_context_information_mapping(void) //----------------------------------------------------------------------------- { SPGW_APP_DEBUG("+-----------------------------------------+\n"); SPGW_APP_DEBUG("| S11 BEARER CONTEXT INFORMATION MAPPINGS |\n"); SPGW_APP_DEBUG("+-----------------------------------------+\n"); hashtable_apply_funct_on_elements(sgw_app.s11_bearer_context_information_hashtable, sgw_lite_display_s11_bearer_context_information, NULL); SPGW_APP_DEBUG("+--------------------------------------+\n"); } //----------------------------------------------------------------------------- void pgw_lite_cm_free_apn(pgw_apn_t *apnP) //----------------------------------------------------------------------------- { if (apnP != NULL) { if (apnP->pdn_connections != NULL) { obj_hashtable_destroy(apnP->pdn_connections); } } } //----------------------------------------------------------------------------- Teid_t sgw_lite_get_new_S11_tunnel_id(void) //----------------------------------------------------------------------------- { // TO DO: RANDOM static Teid_t tunnel_id = 0; tunnel_id += 1; return tunnel_id; } //----------------------------------------------------------------------------- mme_sgw_tunnel_t *sgw_lite_cm_create_s11_tunnel(Teid_t remote_teid, Teid_t local_teid) //----------------------------------------------------------------------------- { mme_sgw_tunnel_t *new_tunnel; new_tunnel = malloc(sizeof(mme_sgw_tunnel_t)); if (new_tunnel == NULL) { /* Malloc failed, may be ENOMEM error */ SPGW_APP_ERROR("Failed to create tunnel for remote_teid %u\n", remote_teid); return NULL; } new_tunnel->remote_teid = remote_teid; new_tunnel->local_teid = local_teid; /* Trying to insert the new tunnel into the tree. * If collision_p is not NULL (0), it means tunnel is already present. */ hashtable_insert(sgw_app.s11teid2mme_hashtable, local_teid, new_tunnel); return new_tunnel; } //----------------------------------------------------------------------------- int sgw_lite_cm_remove_s11_tunnel(Teid_t local_teid) //----------------------------------------------------------------------------- { int temp; temp = hashtable_remove(sgw_app.s11teid2mme_hashtable, local_teid); return temp; } //----------------------------------------------------------------------------- sgw_eps_bearer_entry_t * sgw_lite_cm_create_eps_bearer_entry(void) //----------------------------------------------------------------------------- { sgw_eps_bearer_entry_t *eps_bearer_entry; eps_bearer_entry = malloc(sizeof(sgw_eps_bearer_entry_t)); if (eps_bearer_entry == NULL) { /* Malloc failed, may be ENOMEM error */ SPGW_APP_ERROR("Failed to create new EPS bearer object\n"); return NULL; } return eps_bearer_entry; } //----------------------------------------------------------------------------- sgw_pdn_connection_t * sgw_lite_cm_create_pdn_connection(void) //----------------------------------------------------------------------------- { sgw_pdn_connection_t *pdn_connection; pdn_connection = malloc(sizeof(sgw_pdn_connection_t)); if (pdn_connection == NULL) { /* Malloc failed, may be ENOMEM error */ SPGW_APP_ERROR("Failed to create new PDN connection object\n"); return NULL; } memset(pdn_connection, 0, sizeof(sgw_pdn_connection_t)); pdn_connection->sgw_eps_bearers = hashtable_create(12, NULL, NULL); if ( pdn_connection->sgw_eps_bearers == NULL) { SPGW_APP_ERROR("Failed to create eps bearers collection object\n"); free(pdn_connection); pdn_connection = NULL; return NULL; } return pdn_connection; } //----------------------------------------------------------------------------- void sgw_lite_cm_free_pdn_connection(sgw_pdn_connection_t *pdn_connectionP) //----------------------------------------------------------------------------- { if (pdn_connectionP != NULL) { if (pdn_connectionP->sgw_eps_bearers != NULL) { hashtable_destroy(pdn_connectionP->sgw_eps_bearers); } } } //----------------------------------------------------------------------------- void sgw_lite_cm_free_s_plus_p_gw_eps_bearer_context_information(s_plus_p_gw_eps_bearer_context_information_t *contextP) //----------------------------------------------------------------------------- { if (contextP == NULL) { return; } /*if (contextP->sgw_eps_bearer_context_information.pdn_connections != NULL) { obj_hashtable_destroy(contextP->sgw_eps_bearer_context_information.pdn_connections); }*/ if (contextP->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers != NULL) { hashtable_destroy(contextP->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers); } if (contextP->pgw_eps_bearer_context_information.apns != NULL) { obj_hashtable_destroy(contextP->pgw_eps_bearer_context_information.apns); } free(contextP); } //----------------------------------------------------------------------------- s_plus_p_gw_eps_bearer_context_information_t * sgw_lite_cm_create_bearer_context_information_in_collection(Teid_t teid) //----------------------------------------------------------------------------- { s_plus_p_gw_eps_bearer_context_information_t *new_bearer_context_information; new_bearer_context_information = malloc(sizeof(s_plus_p_gw_eps_bearer_context_information_t)); if (new_bearer_context_information == NULL) { /* Malloc failed, may be ENOMEM error */ SPGW_APP_ERROR("Failed to create new bearer context information object for S11 remote_teid %u\n", teid); return NULL; } memset(new_bearer_context_information, 0, sizeof(s_plus_p_gw_eps_bearer_context_information_t)); SPGW_APP_DEBUG("sgw_lite_cm_create_bearer_context_information_in_collection %d\n", teid); /*new_bearer_context_information->sgw_eps_bearer_context_information.pdn_connections = obj_hashtable_create(32, NULL, NULL, sgw_lite_cm_free_pdn_connection); if ( new_bearer_context_information->sgw_eps_bearer_context_information.pdn_connections == NULL) { SPGW_APP_ERROR("Failed to create PDN connections collection object entry for EPS bearer teid %u \n", teid); sgw_lite_cm_free_s_plus_p_gw_eps_bearer_context_information(new_bearer_context_information); return NULL; }*/ new_bearer_context_information->pgw_eps_bearer_context_information.apns = obj_hashtable_create(32, NULL, NULL, pgw_lite_cm_free_apn); if ( new_bearer_context_information->pgw_eps_bearer_context_information.apns == NULL) { SPGW_APP_ERROR("Failed to create APN collection object entry for EPS bearer S11 teid %u \n", teid); sgw_lite_cm_free_s_plus_p_gw_eps_bearer_context_information(new_bearer_context_information); return NULL; } /* Trying to insert the new tunnel into the tree. * If collision_p is not NULL (0), it means tunnel is already present. */ hashtable_insert(sgw_app.s11_bearer_context_information_hashtable, teid, new_bearer_context_information); SPGW_APP_DEBUG("Added new s_plus_p_gw_eps_bearer_context_information_t in s11_bearer_context_information_hashtable key teid %u\n", teid); return new_bearer_context_information; } int sgw_lite_cm_remove_bearer_context_information(Teid_t teid) { int temp; temp = hashtable_remove(sgw_app.s11_bearer_context_information_hashtable, teid); return temp; } //--- EPS Bearer Entry //----------------------------------------------------------------------------- sgw_eps_bearer_entry_t * sgw_lite_cm_create_eps_bearer_entry_in_collection(hash_table_t *eps_bearersP, ebi_t eps_bearer_idP) //----------------------------------------------------------------------------- { sgw_eps_bearer_entry_t *new_eps_bearer_entry; hashtable_rc_t hash_rc = HASH_TABLE_OK; if (eps_bearersP == NULL) { SPGW_APP_ERROR("Failed to create EPS bearer entry for EPS bearer id %u. reason eps bearer hashtable is NULL \n", eps_bearer_idP); return NULL; } new_eps_bearer_entry = malloc(sizeof(sgw_eps_bearer_entry_t)); if (new_eps_bearer_entry == NULL) { /* Malloc failed, may be ENOMEM error */ SPGW_APP_ERROR("Failed to create EPS bearer entry for EPS bearer id %u \n", eps_bearer_idP); return NULL; } memset(new_eps_bearer_entry, 0, sizeof(sgw_eps_bearer_entry_t)); new_eps_bearer_entry->eps_bearer_id = eps_bearer_idP; hash_rc = hashtable_insert(eps_bearersP, eps_bearer_idP, new_eps_bearer_entry); SPGW_APP_DEBUG("Inserted new EPS bearer entry for EPS bearer id %u status %s\n", eps_bearer_idP, hashtable_rc_code2string(hash_rc)); hash_rc = hashtable_apply_funct_on_elements(eps_bearersP, sgw_lite_display_pdn_connection_sgw_eps_bearers, NULL); if (hash_rc != HASH_TABLE_OK) { SPGW_APP_DEBUG("Invalid sgw_eps_bearers hashtable for display\n"); } /* CHECK DUPLICATES IN HASH TABLES ? if (temp == 1) { SPGW_APP_WARN("This EPS bearer entry already exists: %u\n", eps_bearer_idP); free(new_eps_bearer_entry); new_eps_bearer_entry = collision_p; }*/ return new_eps_bearer_entry; } //----------------------------------------------------------------------------- int sgw_lite_cm_remove_eps_bearer_entry(hash_table_t *eps_bearersP, ebi_t eps_bearer_idP) //----------------------------------------------------------------------------- { int temp; if (eps_bearersP == NULL) { return -1; } temp = hashtable_remove(eps_bearersP, eps_bearer_idP); return temp; }