Files
openairinterface5g/openair-cn/SGW-LITE/sgw_lite_context_manager.c
T

366 lines
16 KiB
C

/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2012 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#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");
hashtbl_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;
hashtbl_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 = hashtbl_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");
hashtbl_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_hashtbl_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.
*/
hashtbl_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 = hashtbl_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 = hashtbl_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);
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) {
hashtbl_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_hashtbl_destroy(contextP->sgw_eps_bearer_context_information.pdn_connections);
}*/
if (contextP->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers != NULL) {
hashtbl_destroy(contextP->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers);
}
if (contextP->pgw_eps_bearer_context_information.apns != NULL) {
obj_hashtbl_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_hashtbl_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_hashtbl_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.
*/
hashtbl_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 = hashtbl_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;
hashtbl_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 = hashtbl_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, hashtble_rc_code2string(hash_rc));
hash_rc = hashtbl_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_WARNING("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 = hashtbl_remove(eps_bearersP, eps_bearer_idP);
return temp;
}