This is done for better merging branch/LG_PRE_RELEASE_0.3 into trunk (same process is applied on this branch) git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7073 818b1a75-f10b-46b9-bf7c-635c3b92a50f
420 lines
15 KiB
C
420 lines
15 KiB
C
/*******************************************************************************
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
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.
|
|
|
|
*******************************************************************************/
|
|
|
|
|
|
#include <pthread.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <stdint.h>
|
|
#include <inttypes.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include "intertask_interface.h"
|
|
#include "mme_config.h"
|
|
|
|
#include "assertions.h"
|
|
#include "conversions.h"
|
|
#include "tree.h"
|
|
#include "enum_string.h"
|
|
#include "common_types.h"
|
|
|
|
#include "mme_app_extern.h"
|
|
#include "mme_app_ue_context.h"
|
|
#include "mme_app_defs.h"
|
|
|
|
static inline int ue_context_compare_identifiers(struct ue_context_s *p1,
|
|
struct ue_context_s *p2);
|
|
|
|
RB_PROTOTYPE(ue_context_map, ue_context_s, rb_entry,
|
|
ue_context_compare_identifiers);
|
|
|
|
RB_GENERATE(ue_context_map, ue_context_s, rb_entry,
|
|
ue_context_compare_identifiers);
|
|
|
|
static inline int ue_context_compare_identifiers(
|
|
struct ue_context_s *p1, struct ue_context_s *p2)
|
|
{
|
|
MME_APP_DEBUG(" ue_context_compare_identifiers IMSI %"SCNu64"\n", p1->imsi);
|
|
MME_APP_DEBUG(" ue_context_compare_identifiers mme_s11_teid %08x\n" , p1->mme_s11_teid);
|
|
MME_APP_DEBUG(" ue_context_compare_identifiers mme_ue_s1ap_id %08x\n" , p1->mme_ue_s1ap_id);
|
|
MME_APP_DEBUG(" ue_context_compare_identifiers ue_id %08x\n" , p1->ue_id);
|
|
|
|
if (p1->imsi > 0) {
|
|
/* if IMSI provided */
|
|
if (p1->imsi > p2->imsi) {
|
|
return 1;
|
|
}
|
|
|
|
if (p1->imsi < p2->imsi) {
|
|
return -1;
|
|
}
|
|
} else if (p1->mme_s11_teid > 0) {
|
|
/* if s11 teid provided */
|
|
if (p1->mme_s11_teid > p2->mme_s11_teid) {
|
|
return 1;
|
|
}
|
|
|
|
if (p1->mme_s11_teid < p2->mme_s11_teid) {
|
|
return -1;
|
|
}
|
|
} else if (p1->mme_ue_s1ap_id > 0) {
|
|
MME_APP_DEBUG(" with mme_ue_s1ap_id %d\n" , p2->mme_ue_s1ap_id);
|
|
|
|
/* if s1ap ue id provided */
|
|
if (p1->mme_ue_s1ap_id > p2->mme_ue_s1ap_id) {
|
|
return 1;
|
|
}
|
|
|
|
if (p1->mme_ue_s1ap_id < p2->mme_ue_s1ap_id) {
|
|
return -1;
|
|
}
|
|
} else if (p1->ue_id > 0) {
|
|
/* if nas ue_id provided */
|
|
if (p1->ue_id > p2->ue_id) {
|
|
return 1;
|
|
}
|
|
|
|
if (p1->ue_id < p2->ue_id) {
|
|
return -1;
|
|
}
|
|
} else {
|
|
uint16_t mcc1;
|
|
uint16_t mnc1;
|
|
uint16_t mnc1_len;
|
|
uint16_t mcc2;
|
|
uint16_t mnc2;
|
|
uint16_t mnc2_len;
|
|
|
|
PLMN_T_TO_MCC_MNC(p1->guti.gummei.plmn, mcc1, mnc1, mnc1_len);
|
|
PLMN_T_TO_MCC_MNC(p1->guti.gummei.plmn, mcc2, mnc2, mnc2_len);
|
|
|
|
/* else compare by GUTI */
|
|
if ((p1->guti.m_tmsi < p2->guti.m_tmsi) &&
|
|
(p1->guti.gummei.MMEcode < p2->guti.gummei.MMEcode) &&
|
|
(p1->guti.gummei.MMEgid < p2->guti.gummei.MMEgid) &&
|
|
(mcc1 < mcc2) &&
|
|
(mnc1 < mnc2) &&
|
|
(mnc1_len < mnc2_len))
|
|
return 1;
|
|
|
|
if ((p1->guti.m_tmsi > p2->guti.m_tmsi) &&
|
|
(p1->guti.gummei.MMEcode > p2->guti.gummei.MMEcode) &&
|
|
(p1->guti.gummei.MMEgid > p2->guti.gummei.MMEgid) &&
|
|
(mcc1 > mcc2) &&
|
|
(mnc1 > mnc2) &&
|
|
(mnc1_len > mnc2_len))
|
|
return -1;
|
|
}
|
|
|
|
/* Match -> return 0 */
|
|
return 0;
|
|
}
|
|
|
|
ue_context_t *mme_create_new_ue_context(void)
|
|
{
|
|
ue_context_t *new_p;
|
|
|
|
new_p = malloc(sizeof(ue_context_t));
|
|
|
|
if (new_p == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
memset(new_p, 0, sizeof(ue_context_t));
|
|
return new_p;
|
|
}
|
|
|
|
inline
|
|
struct ue_context_s *mme_ue_context_exists_imsi(mme_ue_context_t *mme_ue_context,
|
|
mme_app_imsi_t imsi)
|
|
{
|
|
struct ue_context_s reference;
|
|
|
|
DevAssert(mme_ue_context != NULL);
|
|
|
|
memset(&reference, 0, sizeof(struct ue_context_s));
|
|
reference.imsi = imsi;
|
|
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
|
|
&reference);
|
|
}
|
|
|
|
inline
|
|
struct ue_context_s *mme_ue_context_exists_s11_teid(mme_ue_context_t *mme_ue_context,
|
|
uint32_t teid)
|
|
{
|
|
struct ue_context_s reference;
|
|
|
|
DevAssert(mme_ue_context != NULL);
|
|
|
|
memset(&reference, 0, sizeof(struct ue_context_s));
|
|
reference.mme_s11_teid = teid;
|
|
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
|
|
&reference);
|
|
}
|
|
|
|
inline
|
|
ue_context_t *mme_ue_context_exists_mme_ue_s1ap_id(
|
|
mme_ue_context_t *mme_ue_context,
|
|
uint32_t mme_ue_s1ap_id)
|
|
{
|
|
struct ue_context_s reference;
|
|
|
|
DevAssert(mme_ue_context != NULL);
|
|
|
|
memset(&reference, 0, sizeof(struct ue_context_s));
|
|
reference.mme_ue_s1ap_id = mme_ue_s1ap_id;
|
|
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
|
|
&reference);
|
|
}
|
|
|
|
inline
|
|
ue_context_t *mme_ue_context_exists_nas_ue_id(
|
|
mme_ue_context_t *mme_ue_context,
|
|
uint32_t nas_ue_id)
|
|
{
|
|
struct ue_context_s reference;
|
|
|
|
DevAssert(mme_ue_context != NULL);
|
|
|
|
memset(&reference, 0, sizeof(struct ue_context_s));
|
|
reference.ue_id = nas_ue_id;
|
|
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
|
|
&reference);
|
|
}
|
|
|
|
|
|
inline
|
|
ue_context_t *mme_ue_context_exists_guti(mme_ue_context_t *mme_ue_context,
|
|
GUTI_t guti)
|
|
{
|
|
struct ue_context_s reference;
|
|
|
|
DevAssert(mme_ue_context != NULL);
|
|
|
|
memset(&reference, 0, sizeof(struct ue_context_s));
|
|
|
|
memcpy(&reference.guti, &guti, sizeof(GUTI_t));
|
|
|
|
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
|
|
&reference);
|
|
}
|
|
|
|
int mme_insert_ue_context(mme_ue_context_t *mme_ue_context, struct ue_context_s *ue_context_p)
|
|
{
|
|
struct ue_context_s *collision_p = NULL;
|
|
|
|
DevAssert(mme_ue_context != NULL);
|
|
DevAssert(ue_context_p != NULL);
|
|
|
|
/* Updating statistics */
|
|
mme_ue_context->nb_ue_managed++;
|
|
mme_ue_context->nb_ue_since_last_stat++;
|
|
|
|
collision_p = RB_INSERT(ue_context_map, &mme_ue_context->ue_context_tree,
|
|
ue_context_p);
|
|
|
|
if (collision_p != NULL) {
|
|
fprintf(stderr, "This ue context already exists...\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void mme_app_dump_ue_contexts(mme_ue_context_t *mme_ue_context)
|
|
{
|
|
struct ue_context_s *context_p;
|
|
|
|
MME_APP_DEBUG("-----------------------UE contexts-----------------------\n");
|
|
RB_FOREACH(context_p, ue_context_map, &mme_ue_context->ue_context_tree) {
|
|
uint8_t j;
|
|
|
|
MME_APP_DEBUG(" - IMSI ...........: %"SCNu64"\n", context_p->imsi);
|
|
MME_APP_DEBUG(" | m_tmsi | mmec | mmegid | mcc | mnc |\n");
|
|
MME_APP_DEBUG(" - GUTI............: | %08x | %02x | %04x | %03u | %03u |\n",
|
|
context_p->guti.m_tmsi, context_p->guti.gummei.MMEcode,
|
|
context_p->guti.gummei.MMEgid,
|
|
/* TODO check if two or three digits MNC... */
|
|
context_p->guti.gummei.plmn.MCCdigit3 * 100 +
|
|
context_p->guti.gummei.plmn.MCCdigit2 * 10 +
|
|
context_p->guti.gummei.plmn.MCCdigit1,
|
|
context_p->guti.gummei.plmn.MNCdigit3 * 100 +
|
|
context_p->guti.gummei.plmn.MNCdigit2 * 10 +
|
|
context_p->guti.gummei.plmn.MNCdigit1);
|
|
MME_APP_DEBUG(" - Authenticated ..: %s\n",
|
|
(context_p->imsi_auth == IMSI_UNAUTHENTICATED) ? "FALSE": "TRUE");
|
|
MME_APP_DEBUG(" - eNB UE s1ap ID .: %08x\n", context_p->eNB_ue_s1ap_id);
|
|
MME_APP_DEBUG(" - MME UE s1ap ID .: %08x\n", context_p->mme_ue_s1ap_id);
|
|
MME_APP_DEBUG(" - MME S11 TEID ...: %08x\n", context_p->mme_s11_teid);
|
|
MME_APP_DEBUG(" - SGW S11 TEID ...: %08x\n", context_p->sgw_s11_teid);
|
|
MME_APP_DEBUG(" | mcc | mnc | cell id |\n");
|
|
MME_APP_DEBUG(" - E-UTRAN CGI ....: | %03u | %03u | %08x |\n",
|
|
context_p->e_utran_cgi.plmn.MCCdigit3 * 100 +
|
|
context_p->e_utran_cgi.plmn.MCCdigit2 * 10 +
|
|
context_p->e_utran_cgi.plmn.MCCdigit1,
|
|
context_p->e_utran_cgi.plmn.MNCdigit3 * 100 +
|
|
context_p->e_utran_cgi.plmn.MNCdigit2 * 10 +
|
|
context_p->e_utran_cgi.plmn.MNCdigit1,
|
|
context_p->e_utran_cgi.cell_identity);
|
|
/* Ctime return a \n in the string */
|
|
MME_APP_DEBUG(" - Last acquired ..: %s", ctime(&context_p->cell_age));
|
|
|
|
/* Display UE info only if we know them */
|
|
if (context_p->subscription_known == SUBSCRIPTION_KNOWN) {
|
|
MME_APP_DEBUG(" - Status .........: %s\n",
|
|
(context_p->sub_status == SS_SERVICE_GRANTED) ? "Granted" : "Barred");
|
|
#define DISPLAY_BIT_MASK_PRESENT(mASK) \
|
|
((context_p->access_restriction_data & mASK) ? 'X' : 'O')
|
|
MME_APP_DEBUG(" (O = allowed, X = !O) |UTRAN|GERAN|GAN|HSDPA EVO|E_UTRAN|HO TO NO 3GPP|\n");
|
|
MME_APP_DEBUG(" - Access restriction | %c | %c | %c | %c | %c | %c |\n",
|
|
DISPLAY_BIT_MASK_PRESENT(ARD_UTRAN_NOT_ALLOWED),
|
|
DISPLAY_BIT_MASK_PRESENT(ARD_GERAN_NOT_ALLOWED),
|
|
DISPLAY_BIT_MASK_PRESENT(ARD_GAN_NOT_ALLOWED),
|
|
DISPLAY_BIT_MASK_PRESENT(ARD_I_HSDPA_EVO_NOT_ALLOWED),
|
|
DISPLAY_BIT_MASK_PRESENT(ARD_E_UTRAN_NOT_ALLOWED),
|
|
DISPLAY_BIT_MASK_PRESENT(ARD_HO_TO_NON_3GPP_NOT_ALLOWED));
|
|
MME_APP_DEBUG(" - Access Mode ....: %s\n",
|
|
ACCESS_MODE_TO_STRING(context_p->access_mode));
|
|
MME_APP_DEBUG(" - MSISDN .........: %-*s\n",
|
|
MSISDN_LENGTH, context_p->msisdn);
|
|
MME_APP_DEBUG(" - RAU/TAU timer ..: %u\n", context_p->rau_tau_timer);
|
|
MME_APP_DEBUG(" - IMEISV .........: %*s\n", 15,
|
|
context_p->me_identity.imeisv);
|
|
MME_APP_DEBUG(" - AMBR (bits/s) ( Downlink | Uplink )\n");
|
|
MME_APP_DEBUG(" Subscribed ...: (%010"PRIu64"|%010"PRIu64")\n",
|
|
context_p->subscribed_ambr.br_dl,
|
|
context_p->subscribed_ambr.br_ul);
|
|
MME_APP_DEBUG(" Allocated ....: (%010"PRIu64"|%010"PRIu64")\n",
|
|
context_p->used_ambr.br_dl, context_p->used_ambr.br_ul);
|
|
MME_APP_DEBUG(" - Known vectors ..: %u\n", context_p->nb_of_vectors);
|
|
|
|
for (j = 0; j < context_p->nb_of_vectors; j++) {
|
|
int k;
|
|
char xres_string[3 * XRES_LENGTH_MAX + 1];
|
|
eutran_vector_t *vector_p;
|
|
|
|
vector_p = &context_p->vector_list[j];
|
|
|
|
MME_APP_DEBUG(" - RAND ..: "RAND_FORMAT"\n",
|
|
RAND_DISPLAY(vector_p->rand));
|
|
MME_APP_DEBUG(" - AUTN ..: "AUTN_FORMAT"\n",
|
|
AUTN_DISPLAY(vector_p->autn));
|
|
MME_APP_DEBUG(" - KASME .: "KASME_FORMAT"\n",
|
|
KASME_DISPLAY_1(vector_p->kasme));
|
|
MME_APP_DEBUG(" "KASME_FORMAT"\n",
|
|
KASME_DISPLAY_2(vector_p->kasme));
|
|
|
|
for (k = 0; k < vector_p->xres.size; k++) {
|
|
sprintf(&xres_string[k * 3], "%02x,", vector_p->xres.data[k]);
|
|
}
|
|
|
|
xres_string[k * 3 - 1] = '\0';
|
|
MME_APP_DEBUG(" - XRES ..: %s\n", xres_string);
|
|
}
|
|
|
|
MME_APP_DEBUG(" - PDN List:\n");
|
|
|
|
for (j = 0; j < context_p->apn_profile.nb_apns; j++) {
|
|
struct apn_configuration_s *apn_config_p;
|
|
|
|
apn_config_p = &context_p->apn_profile.apn_configuration[j];
|
|
|
|
/* Default APN ? */
|
|
MME_APP_DEBUG(" - Default APN ...: %s\n",
|
|
(apn_config_p->context_identifier == context_p->apn_profile.context_identifier)
|
|
? "TRUE" : "FALSE");
|
|
MME_APP_DEBUG(" - APN ...........: %s\n", apn_config_p->service_selection);
|
|
MME_APP_DEBUG(" - AMBR (bits/s) ( Downlink | Uplink )\n");
|
|
MME_APP_DEBUG(" (%010"PRIu64"|%010"PRIu64")\n",
|
|
apn_config_p->ambr.br_dl, apn_config_p->ambr.br_ul);
|
|
MME_APP_DEBUG(" - PDN type ......: %s\n",
|
|
PDN_TYPE_TO_STRING(apn_config_p->pdn_type));
|
|
MME_APP_DEBUG(" - QOS\n");
|
|
MME_APP_DEBUG(" QCI .........: %u\n",
|
|
apn_config_p->subscribed_qos.qci);
|
|
MME_APP_DEBUG(" Prio level ..: %u\n",
|
|
apn_config_p->subscribed_qos.allocation_retention_priority.priority_level);
|
|
MME_APP_DEBUG(" Pre-emp vul .: %s\n",
|
|
(apn_config_p->subscribed_qos.allocation_retention_priority.pre_emp_vulnerability
|
|
== PRE_EMPTION_VULNERABILITY_ENABLED) ? "ENABLED" : "DISABLED");
|
|
MME_APP_DEBUG(" Pre-emp cap .: %s\n",
|
|
(apn_config_p->subscribed_qos.allocation_retention_priority.pre_emp_capability
|
|
== PRE_EMPTION_CAPABILITY_ENABLED) ? "ENABLED" : "DISABLED");
|
|
|
|
if (apn_config_p->nb_ip_address == 0) {
|
|
MME_APP_DEBUG(" IP addr .....: Dynamic allocation\n");
|
|
} else {
|
|
int i;
|
|
MME_APP_DEBUG(" IP addresses :\n");
|
|
|
|
for (i = 0; i < apn_config_p->nb_ip_address; i++) {
|
|
if (apn_config_p->ip_address[i].pdn_type == IPv4) {
|
|
MME_APP_DEBUG(" ["IPV4_ADDR"]\n",
|
|
IPV4_ADDR_DISPLAY_8(apn_config_p->ip_address[i].address.ipv4_address));
|
|
} else {
|
|
char ipv6[40];
|
|
inet_ntop(AF_INET6, apn_config_p->ip_address[i].address.ipv6_address,ipv6, 40);
|
|
MME_APP_DEBUG(" [%s]\n", ipv6);
|
|
}
|
|
}
|
|
}
|
|
|
|
MME_APP_DEBUG("\n");
|
|
}
|
|
|
|
MME_APP_DEBUG(" - Bearer List:\n");
|
|
|
|
for (j = 0; j < BEARERS_PER_UE; j++) {
|
|
bearer_context_t *bearer_context_p;
|
|
|
|
bearer_context_p = &context_p->eps_bearers[j];
|
|
|
|
if (bearer_context_p->s_gw_teid != 0) {
|
|
MME_APP_DEBUG(" Bearer id .......: %02u\n", j);
|
|
MME_APP_DEBUG(" S-GW TEID (UP)...: %08x\n", bearer_context_p->s_gw_teid);
|
|
MME_APP_DEBUG(" P-GW TEID (UP)...: %08x\n", bearer_context_p->p_gw_teid);
|
|
MME_APP_DEBUG(" QCI .............: %u\n",
|
|
bearer_context_p->qci);
|
|
MME_APP_DEBUG(" Priority level ..: %u\n",
|
|
bearer_context_p->prio_level);
|
|
MME_APP_DEBUG(" Pre-emp vul .....: %s\n",
|
|
(bearer_context_p->pre_emp_vulnerability
|
|
== PRE_EMPTION_VULNERABILITY_ENABLED) ? "ENABLED" : "DISABLED");
|
|
MME_APP_DEBUG(" Pre-emp cap .....: %s\n",
|
|
(bearer_context_p->pre_emp_capability
|
|
== PRE_EMPTION_CAPABILITY_ENABLED) ? "ENABLED" : "DISABLED");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
MME_APP_DEBUG("---------------------------------------------------------\n");
|
|
}
|