git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4242 818b1a75-f10b-46b9-bf7c-635c3b92a50f
366 lines
16 KiB
C
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;
|
|
}
|
|
|