Split ue_context into two context(enb_ue_t, mme_ue_t)

This commit is contained in:
James Park 2017-04-28 13:43:42 +09:00
parent b95e40a851
commit 65b5378c91
14 changed files with 501 additions and 61 deletions

View File

@ -66,6 +66,13 @@ typedef struct _e_cgi_t {
c_uint32_t cell_id; /* 28 bit */
} __attribute__ ((packed)) e_cgi_t;
typedef struct _guti_t {
plmn_id_t plmn_id;
c_uint16_t mme_gid;
c_uint8_t mme_code;
c_uint32_t m_tmsi;
} __attribute__ ((packed)) guti_t;
/**************************************************
* 8.14 PDN Address Allocation (PAA) */
#define PAA_IPV4_LEN 5

View File

@ -25,6 +25,7 @@ status_t emm_build_attach_accept(
&attach_accept->eps_network_feature_support;
d_assert(ue, return CORE_ERROR, "Null param");
d_assert(ue->enb_ue, return CORE_ERROR, "Null param");
memset(&message, 0, sizeof(message));
message.h.security_header_type =
@ -41,7 +42,7 @@ status_t emm_build_attach_accept(
tai_list->length = 6;
tai_list->type = 2;
tai_list->num = 0; /* +1 = 1 elements */
memcpy(&tai_list->type2.tai[0], &ue->tai, sizeof(tai_t));
memcpy(&tai_list->type2.tai[0], &ue->enb_ue->tai, sizeof(tai_t));
attach_accept->esm_message_container.data = esmbuf->payload;
attach_accept->esm_message_container.len = esmbuf->len;

View File

@ -141,16 +141,19 @@ void emm_handle_attach_request(
}
}
void emm_handle_identity_request(mme_ue_t *ue)
void emm_handle_identity_request(mme_ue_t *mme_ue)
{
status_t rv;
mme_enb_t *enb = NULL;
enb_ue_t *ue = NULL;
pkbuf_t *emmbuf = NULL, *s1apbuf = NULL;
nas_message_t message;
nas_identity_request_t *identity_request =
&message.emm.identity_request;
d_assert(mme_ue, return, "Null param");
ue = mme_ue->enb_ue;
d_assert(ue, return, "Null param");
enb = ue->enb;
d_assert(ue->enb, return, "Null param");
@ -202,16 +205,19 @@ void emm_handle_identity_response(
}
void emm_handle_authentication_request(mme_ue_t *ue)
void emm_handle_authentication_request(mme_ue_t *mme_ue)
{
status_t rv;
mme_enb_t *enb = NULL;
enb_ue_t *ue = NULL;
pkbuf_t *emmbuf = NULL, *s1apbuf = NULL;
nas_message_t message;
nas_authentication_request_t *authentication_request =
&message.emm.authentication_request;
d_assert(mme_ue, return, "Null param");
ue = mme_ue->enb_ue;
d_assert(ue, return, "Null param");
enb = ue->enb;
d_assert(ue->enb, return, "Null param");
@ -221,9 +227,9 @@ void emm_handle_authentication_request(mme_ue_t *ue)
message.emm.h.message_type = NAS_AUTHENTICATION_REQUEST;
memcpy(authentication_request->authentication_parameter_rand.rand,
ue->rand, RAND_LEN);
mme_ue->rand, RAND_LEN);
memcpy(authentication_request->authentication_parameter_autn.autn,
ue->autn, AUTN_LEN);
mme_ue->autn, AUTN_LEN);
authentication_request->authentication_parameter_autn.length =
AUTN_LEN;
@ -241,6 +247,7 @@ void emm_handle_authentication_response(
{
status_t rv;
mme_enb_t *enb = NULL;
enb_ue_t *enb_ue = NULL;
pkbuf_t *emmbuf = NULL, *s1apbuf = NULL;
nas_authentication_response_parameter_t *authentication_response_parameter =
@ -257,8 +264,10 @@ void emm_handle_authentication_response(
&security_mode_command->replayed_ue_security_capabilities;
d_assert(ue, return, "Null param");
enb = ue->enb;
d_assert(ue->enb, return, "Null param");
enb_ue = ue->enb_ue;
d_assert(enb_ue, return, "Null param");
enb = enb_ue->enb;
d_assert(enb, return, "Null param");
if (authentication_response_parameter->length != ue->xres_len ||
memcmp(authentication_response_parameter->res,
@ -313,7 +322,7 @@ void emm_handle_authentication_response(
rv = nas_security_encode(&emmbuf, ue, &message);
d_assert(rv == CORE_OK && emmbuf, return, "emm build error");
rv = s1ap_build_downlink_nas_transport(&s1apbuf, ue, emmbuf);
rv = s1ap_build_downlink_nas_transport(&s1apbuf, enb_ue, emmbuf);
d_assert(rv == CORE_OK && s1apbuf,
pkbuf_free(emmbuf); return, "s1ap build error");
@ -324,14 +333,17 @@ void emm_handle_create_session_response(mme_bearer_t *bearer)
{
status_t rv;
mme_ue_t *ue = NULL;
enb_ue_t *enb_ue = NULL;
mme_enb_t *enb = NULL;
pkbuf_t *esmbuf = NULL, *emmbuf = NULL, *s1apbuf = NULL;
d_assert(bearer, return, "Null param");
ue = bearer->ue;
d_assert(ue, return, "Null param");
enb = ue->enb;
d_assert(ue->enb, return, "Null param");
enb_ue = ue->enb_ue;
d_assert(enb_ue, return, "Null param");
enb = enb_ue->enb;
d_assert(enb, return, "Null param");
rv = esm_build_activate_default_bearer_context(&esmbuf, bearer);
d_assert(rv == CORE_OK && esmbuf,
@ -358,6 +370,7 @@ void emm_handle_attach_complete(
{
status_t rv;
mme_enb_t *enb = NULL;
enb_ue_t *enb_ue = NULL;
pkbuf_t *emmbuf = NULL, *s1apbuf = NULL;
nas_message_t message;
@ -371,7 +384,9 @@ void emm_handle_attach_complete(
time_exp_lt(&time_exp, time_now());
d_assert(ue, return, "Null param");
enb = ue->enb;
enb_ue = ue->enb_ue;
d_assert(enb_ue, return, "Null param");
enb = enb_ue->enb;
d_assert(enb, return, "Null param");
emm_handle_esm_message_container(
@ -414,7 +429,7 @@ void emm_handle_attach_complete(
rv = nas_security_encode(&emmbuf, ue, &message);
d_assert(rv == CORE_OK && emmbuf, return, "emm build error");
rv = s1ap_build_downlink_nas_transport(&s1apbuf, ue, emmbuf);
rv = s1ap_build_downlink_nas_transport(&s1apbuf, enb_ue, emmbuf);
d_assert(rv == CORE_OK && s1apbuf,
pkbuf_free(emmbuf); return, "s1ap build error");
@ -434,6 +449,7 @@ void emm_handle_detach_request(
{
status_t rv;
mme_enb_t *enb = NULL;
enb_ue_t *enb_ue = NULL;
pkbuf_t *emmbuf = NULL, *s1apbuf = NULL;
nas_message_t message;
@ -445,7 +461,9 @@ void emm_handle_detach_request(
*/
d_assert(ue, return, "Null param");
enb = ue->enb;
enb_ue = ue->enb_ue;
d_assert(enb_ue, return, "Null param");
enb = enb_ue->enb;
d_assert(enb, return, "Null param");
switch (detach_type->detach_type)
@ -484,7 +502,7 @@ void emm_handle_detach_request(
rv = nas_security_encode(&emmbuf, ue, &message);
d_assert(rv == CORE_OK && emmbuf, return, "emm build error");
rv = s1ap_build_downlink_nas_transport(&s1apbuf, ue, emmbuf);
rv = s1ap_build_downlink_nas_transport(&s1apbuf, enb_ue, emmbuf);
d_assert(rv == CORE_OK && s1apbuf,
pkbuf_free(emmbuf); return, "s1ap build error");
@ -493,3 +511,98 @@ void emm_handle_detach_request(
/* initiate s1 ue context release */
}
mme_ue_t *emm_find_ue_by_message(enb_ue_t *enb_ue, nas_message_t *message)
{
mme_ue_t *mme_ue = NULL;
switch(message->emm.h.message_type)
{
case NAS_ATTACH_REQUEST:
{
nas_attach_request_t *attach_request =
&message->emm.attach_request;
nas_eps_mobile_identity_t *eps_mobile_identity =
&attach_request->eps_mobile_identity;
switch(eps_mobile_identity->imsi.type)
{
case NAS_EPS_MOBILE_IDENTITY_IMSI:
{
c_uint8_t imsi[MAX_IMSI_LEN];
int imsi_len = 0;
c_int8_t imsi_bcd[MAX_IMSI_BCD_LEN+1];
nas_imsi_to_bcd(
&eps_mobile_identity->imsi, eps_mobile_identity->length,
imsi_bcd);
core_bcd_to_buffer(imsi_bcd, imsi, &imsi_len);
d_trace(3,"Search mme_ue by UE_IMSI[%s]\n", imsi_bcd);
/* Find mme_ue_context by IMSI */
mme_ue = mme_ue_find_by_imsi(imsi, imsi_len);
/* If not found , create one */
if (!mme_ue)
{
mme_ue = mme_ue_add(enb_ue);
}
break;
}
case NAS_EPS_MOBILE_IDENTITY_GUTI:
{
nas_eps_mobile_identity_guti_t *nas_guti = NULL;
nas_guti = &eps_mobile_identity->guti;
guti_t guti;
guti.plmn_id = nas_guti->plmn_id;
guti.mme_gid = nas_guti->mme_gid;
guti.mme_code = nas_guti->mme_code;
guti.m_tmsi = nas_guti->m_tmsi;
d_trace(3,"Search mme_ue by GUTI[G:%d,C:%d,M_TMSI:0x%x]\n",
guti.mme_gid,
guti.mme_code,
guti.m_tmsi);
printf("Search mme_ue by GUTI[G:%d,C:%d,M_TMSI:0x%x]\n",
guti.mme_gid,
guti.mme_code,
guti.m_tmsi);
mme_ue = mme_ue_find_by_guti(&guti);
if (!mme_ue)
{
mme_ue = mme_ue_add(enb_ue);
}
break;
}
default:
{
printf("Uknown message imsi type =%d\n",
eps_mobile_identity->imsi.type);
break;
}
}
break;
}
case NAS_DETACH_REQUEST:
{
/* TODO */
break;
}
case NAS_TRACKING_AREA_UPDATE_REQUEST:
{
/* TODO */
break;
}
default:
{
break;
}
}
return mme_ue;
}

View File

@ -22,6 +22,7 @@ CORE_DECLARE(void) emm_handle_identity_response(
mme_ue_t *ue, nas_identity_response_t *identity_response);
CORE_DECLARE(void) emm_handle_detach_request(
mme_ue_t *ue, nas_detach_request_from_ue_t *detach_request);
CORE_DECLARE(mme_ue_t*) emm_find_ue_by_message(enb_ue_t *enb_ue, nas_message_t *message);
#ifdef __cplusplus
}

View File

@ -32,19 +32,22 @@ void esm_handle_s6a_update_location(mme_bearer_t *bearer)
{
status_t rv;
mme_ue_t *ue = NULL;
enb_ue_t *enb_ue = NULL;
mme_enb_t *enb = NULL;
pkbuf_t *esmbuf = NULL, *s1apbuf = NULL;
d_assert(bearer, return, "Null param");
ue = bearer->ue;
d_assert(ue, return, "Null param");
enb = ue->enb;
d_assert(ue->enb, return, "Null param");
enb_ue = ue->enb_ue;
d_assert(enb_ue, return, "Null param");
enb = enb_ue->enb;
d_assert(enb, return, "Null param");
rv = esm_build_information_request(&esmbuf, bearer);
d_assert(rv == CORE_OK && esmbuf, return, "esm_build failed");
rv = s1ap_build_downlink_nas_transport(&s1apbuf, ue, esmbuf);
rv = s1ap_build_downlink_nas_transport(&s1apbuf, enb_ue, esmbuf);
d_assert(rv == CORE_OK && s1apbuf,
pkbuf_free(esmbuf); return, "s1ap build error");

View File

@ -23,6 +23,7 @@ pool_declare(mme_sgw_pool, mme_sgw_t, MAX_NUM_OF_SGW);
index_declare(mme_enb_pool, mme_enb_t, MAX_NUM_OF_ENB);
index_declare(mme_ue_pool, mme_ue_t, MAX_NUM_OF_UE);
index_declare(enb_ue_pool, enb_ue_t, MAX_NUM_OF_UE);
index_declare(mme_bearer_pool, mme_bearer_t, MAX_NUM_OF_UE_BEARER);
pool_declare(mme_pdn_pool, pdn_t, MAX_NUM_OF_UE_PDN);
@ -53,12 +54,15 @@ status_t mme_context_init()
list_init(&self.enb_list);
index_init(&mme_ue_pool, MAX_NUM_OF_UE);
index_init(&enb_ue_pool, MAX_NUM_OF_UE);
index_init(&mme_bearer_pool, MAX_NUM_OF_UE_BEARER);
pool_init(&mme_pdn_pool, MAX_NUM_OF_UE_PDN);
self.mme_addr = inet_addr(g_mme_ip_addr);
self.mme_ue_s1ap_id_hash = hash_make();
self.imsi_hash = hash_make();
self.guti_hash = hash_make();
self.s1ap_addr = self.mme_addr;
self.s1ap_port = S1AP_SCTP_PORT;
@ -107,9 +111,16 @@ status_t mme_context_final()
d_assert(self.mme_ue_s1ap_id_hash, , "Null param");
hash_destroy(self.mme_ue_s1ap_id_hash);
d_assert(self.imsi_hash, , "Null param");
hash_destroy(self.imsi_hash);
d_assert(self.guti_hash, , "Null param");
hash_destroy(self.guti_hash);
pool_final(&mme_pdn_pool);
index_final(&mme_bearer_pool);
index_final(&mme_ue_pool);
index_final(&enb_ue_pool);
index_final(&mme_enb_pool);
pool_final(&mme_sgw_pool);
@ -224,7 +235,7 @@ status_t mme_enb_remove(mme_enb_t *enb)
fsm_final(&enb->sm, 0);
fsm_clear(&enb->sm);
mme_ue_remove_in_enb(enb);
enb_ue_remove_in_enb(enb);
net_unregister_sock(enb->s1ap_sock);
net_close(enb->s1ap_sock);
@ -300,19 +311,21 @@ mme_enb_t* mme_enb_next(mme_enb_t *enb)
return list_next(enb);
}
mme_ue_t* mme_ue_add(mme_enb_t *enb)
/** enb_ue_context handling function */
enb_ue_t* enb_ue_add(mme_enb_t *enb)
{
mme_ue_t *ue = NULL;
enb_ue_t *ue = NULL;
d_assert(self.mme_ue_s1ap_id_hash, return NULL, "Null param");
d_assert(enb, return NULL, "Null param");
index_alloc(&mme_ue_pool, &ue);
index_alloc(&enb_ue_pool, &ue);
d_assert(ue, return NULL, "Null param");
ue->mme_ue_s1ap_id = NEXT_ID(self.mme_ue_s1ap_id, 1, 0xffffffff);
hash_set(self.mme_ue_s1ap_id_hash, &ue->mme_ue_s1ap_id,
sizeof(ue->mme_ue_s1ap_id), ue);
#if 0
ue->mme_s11_teid = ue->index;
ue->mme_s11_addr = mme_self()->s11_addr;
@ -320,10 +333,135 @@ mme_ue_t* mme_ue_add(mme_enb_t *enb)
list_init(&ue->pdn_list);
list_init(&ue->bearer_list);
#endif
list_append(&enb->ue_list, ue);
ue->enb = enb;
#if 0
fsm_create(&ue->sm, enbue_state_initial, enbue_state_final);
fsm_init(&ue->sm, 0);
#endif
return ue;
}
unsigned int enb_ue_count()
{
d_assert(self.mme_ue_s1ap_id_hash, return 0, "Null param");
return hash_count(self.mme_ue_s1ap_id_hash);
}
status_t enb_ue_remove(enb_ue_t *ue)
{
d_assert(self.mme_ue_s1ap_id_hash, return CORE_ERROR, "Null param");
d_assert(ue, return CORE_ERROR, "Null param");
d_assert(ue->enb, return CORE_ERROR, "Null param");
#if 0
fsm_final(&ue->sm, 0);
fsm_clear(&ue->sm);
mme_bearer_remove_all(ue);
mme_pdn_remove_all(ue);
#endif
list_remove(&ue->enb->ue_list, ue);
hash_set(self.mme_ue_s1ap_id_hash, &ue->mme_ue_s1ap_id,
sizeof(ue->mme_ue_s1ap_id), NULL);
index_free(&enb_ue_pool, ue);
return CORE_OK;
}
status_t enb_ue_remove_in_enb(mme_enb_t *enb)
{
enb_ue_t *ue = NULL, *next_ue = NULL;
ue = enb_ue_first_in_enb(enb);
while (ue)
{
next_ue = enb_ue_next_in_enb(ue);
enb_ue_remove(ue);
ue = next_ue;
}
return CORE_OK;
}
enb_ue_t* enb_ue_find(index_t index)
{
d_assert(index, return NULL, "Invalid Index");
return index_find(&enb_ue_pool, index);
}
enb_ue_t* enb_ue_find_by_enb_ue_s1ap_id(
mme_enb_t *enb, c_uint32_t enb_ue_s1ap_id)
{
enb_ue_t *ue = NULL;
ue = enb_ue_first_in_enb(enb);
while (ue)
{
if (enb_ue_s1ap_id == ue->enb_ue_s1ap_id)
break;
ue = enb_ue_next_in_enb(ue);
}
return ue;
}
enb_ue_t* enb_ue_find_by_mme_ue_s1ap_id(c_uint32_t mme_ue_s1ap_id)
{
d_assert(self.mme_ue_s1ap_id_hash, return NULL, "Null param");
return hash_get(self.mme_ue_s1ap_id_hash,
&mme_ue_s1ap_id, sizeof(mme_ue_s1ap_id));
}
enb_ue_t* enb_ue_first_in_enb(mme_enb_t *enb)
{
return list_first(&enb->ue_list);
}
enb_ue_t* enb_ue_next_in_enb(enb_ue_t *ue)
{
return list_next(ue);
}
mme_ue_t* mme_ue_add(enb_ue_t *enb_ue)
{
mme_ue_t *ue = NULL;
#if 0
d_assert(self.mme_ue_s1ap_id_hash, return NULL, "Null param");
#endif
d_assert(enb_ue, return NULL, "Null param");
index_alloc(&mme_ue_pool, &ue);
d_assert(ue, return NULL, "Null param");
#if 0
ue->mme_ue_s1ap_id = NEXT_ID(self.mme_ue_s1ap_id, 1, 0xffffffff);
hash_set(self.mme_ue_s1ap_id_hash, &ue->mme_ue_s1ap_id,
sizeof(ue->mme_ue_s1ap_id), ue);
#endif
ue->mme_s11_teid = ue->index;
ue->mme_s11_addr = mme_self()->s11_addr;
ue->ebi = MIN_EPS_BEARER_ID - 1; /* Setup EBI Generator */
list_init(&ue->pdn_list);
list_init(&ue->bearer_list);
//list_append(&enb->ue_list, ue);
ue->enb_ue = enb_ue;
enb_ue->mme_ue = ue;
fsm_create(&ue->sm, emm_state_initial, emm_state_final);
fsm_init(&ue->sm, 0);
@ -332,9 +470,9 @@ mme_ue_t* mme_ue_add(mme_enb_t *enb)
status_t mme_ue_remove(mme_ue_t *ue)
{
d_assert(self.mme_ue_s1ap_id_hash, return CORE_ERROR, "Null param");
//d_assert(self.mme_ue_s1ap_id_hash, return CORE_ERROR, "Null param");
d_assert(ue, return CORE_ERROR, "Null param");
d_assert(ue->enb, return CORE_ERROR, "Null param");
//d_assert(ue->enb, return CORE_ERROR, "Null param");
fsm_final(&ue->sm, 0);
fsm_clear(&ue->sm);
@ -342,9 +480,11 @@ status_t mme_ue_remove(mme_ue_t *ue)
mme_bearer_remove_all(ue);
mme_pdn_remove_all(ue);
#if 0
list_remove(&ue->enb->ue_list, ue);
hash_set(self.mme_ue_s1ap_id_hash, &ue->mme_ue_s1ap_id,
sizeof(ue->mme_ue_s1ap_id), NULL);
#endif
index_free(&mme_ue_pool, ue);
@ -371,18 +511,54 @@ mme_ue_t* mme_ue_find(index_t index)
return index_find(&mme_ue_pool, index);
}
#if 0
mme_ue_t* mme_ue_find_by_mme_ue_s1ap_id(c_uint32_t mme_ue_s1ap_id)
{
d_assert(self.mme_ue_s1ap_id_hash, return NULL, "Null param");
return hash_get(self.mme_ue_s1ap_id_hash,
&mme_ue_s1ap_id, sizeof(mme_ue_s1ap_id));
}
#endif
mme_ue_t* mme_ue_find_by_teid(c_uint32_t teid)
{
return mme_ue_find(teid);
}
mme_ue_t* mme_ue_find_by_imsi(c_uint8_t *imsi, int imsi_len)
{
mme_ue_t *iter = NULL;
#if 0
d_assert(imsi && imsi_len, return NULL, "Invalid Param");
for (iter = list_first(&self.mme_ue_list); iter; iter = list_next(iter))
{
if (!memcmp(iter->imsi,imsi, imsi_len))
break;
}
#endif
return iter;
}
mme_ue_t* mme_ue_find_by_guti(guti_t *guti)
{
mme_ue_t *iter = NULL;
#if 0
d_assert(imsi && imsi_len, return NULL, "Invalid Param");
for (iter = list_first(&self.mme_ue_list); iter; iter = list_next(iter))
{
if (!memcmp(iter->imsi,imsi, imsi_len))
break;
}
#endif
return iter;
}
hash_index_t *mme_ue_first()
{
d_assert(self.mme_ue_s1ap_id_hash, return NULL, "Null param");
@ -400,6 +576,7 @@ mme_ue_t *mme_ue_this(hash_index_t *hi)
return hash_this_val(hi);
}
#if 0
unsigned int mme_ue_count()
{
d_assert(self.mme_ue_s1ap_id_hash, return 0, "Null param");
@ -449,6 +626,7 @@ mme_ue_t* mme_ue_next_in_enb(mme_ue_t *ue)
{
return list_next(ue);
}
#endif
mme_bearer_t* mme_bearer_add(mme_ue_t *ue, c_uint8_t pti)
{

View File

@ -75,6 +75,8 @@ typedef struct _mme_context_t {
list_t enb_list;
hash_t *mme_ue_s1ap_id_hash; /* hash table for MME-UE-S1AP-ID */
hash_t *imsi_hash; /* hash table (IMSI : MME_UE) */
hash_t *guti_hash; /* hash table (GUTI : MME_UE) */
} mme_context_t;
typedef struct _mme_sgw_t {
@ -94,7 +96,10 @@ typedef struct _mme_enb_t {
} mme_enb_t;
typedef struct _mme_ue_t {
typedef struct _enb_ue_t enb_ue_t;
typedef struct _mme_ue_t mme_ue_t;
struct _enb_ue_t {
lnode_t node; /**< A node of list_t */
index_t index; /**< An index of this node */
fsm_t sm;
@ -104,13 +109,44 @@ typedef struct _mme_ue_t {
/* UE identity */
c_uint32_t enb_ue_s1ap_id; /** eNB-UE-S1AP-ID received from eNB */
c_uint32_t mme_ue_s1ap_id; /** MME-UE-S1AP-ID received from MME */
c_uint8_t imsi[MAX_IMSI_LEN];
int imsi_len;
c_int8_t imsi_bcd[MAX_IMSI_BCD_LEN+1];
/* UE Info */
tai_t tai;
e_cgi_t e_cgi;
/* S_TMSI */
//s_tmsi_t s_smti;
/* mme_ue_context */
mme_ue_t *mme_ue;
/* Connected enodeB */
mme_enb_t *enb;
};
struct _mme_ue_t {
lnode_t node; /**< A node of list_t */
index_t index; /**< An index of this node */
fsm_t sm;
/* State Machine */
/* UE identity */
#if 0
c_uint32_t enb_ue_s1ap_id; /** eNB-UE-S1AP-ID received from eNB */
c_uint32_t mme_ue_s1ap_id; /** MME-UE-S1AP-ID received from MME */
#endif
c_uint8_t imsi[MAX_IMSI_LEN];
int imsi_len;
c_int8_t imsi_bcd[MAX_IMSI_BCD_LEN+1];
guti_t guti;
/* UE Info */
#if 0
tai_t tai;
e_cgi_t e_cgi;
#endif
plmn_id_t visited_plmn_id;
/* Security Context */
@ -153,8 +189,9 @@ typedef struct _mme_ue_t {
c_uint8_t ebi; /* EPS Bearer ID generator */
list_t bearer_list;
mme_enb_t *enb;
} mme_ue_t;
/* enb ue context */
enb_ue_t *enb_ue;
};
typedef struct _mme_bearer_t {
lnode_t node; /**< A node of list_t */
@ -201,7 +238,7 @@ CORE_DECLARE(mme_enb_t*) mme_enb_find_by_enb_id(c_uint32_t enb_id);
CORE_DECLARE(mme_enb_t*) mme_enb_first(void);
CORE_DECLARE(mme_enb_t*) mme_enb_next(mme_enb_t *enb);
CORE_DECLARE(mme_ue_t*) mme_ue_add(mme_enb_t *enb);
CORE_DECLARE(mme_ue_t*) mme_ue_add(enb_ue_t *enb_ue);
CORE_DECLARE(status_t) mme_ue_remove(mme_ue_t *ue);
CORE_DECLARE(status_t) mme_ue_remove_all();
CORE_DECLARE(mme_ue_t*) mme_ue_find(index_t index);
@ -217,6 +254,8 @@ CORE_DECLARE(mme_ue_t*) mme_ue_find_by_enb_ue_s1ap_id(
mme_enb_t *enb, c_uint32_t enb_ue_s1ap_id);
CORE_DECLARE(mme_ue_t*) mme_ue_first_in_enb(mme_enb_t *enb);
CORE_DECLARE(mme_ue_t*) mme_ue_next_in_enb(mme_ue_t *ue);
CORE_DECLARE(mme_ue_t*) mme_ue_find_by_imsi(c_uint8_t *imsi, int imsi_len);
CORE_DECLARE(mme_ue_t*) mme_ue_find_by_guti(guti_t *guti);
CORE_DECLARE(mme_bearer_t*) mme_bearer_add(mme_ue_t *ue, c_uint8_t pti);
CORE_DECLARE(status_t) mme_bearer_remove(mme_bearer_t *bearer);
@ -234,6 +273,17 @@ CORE_DECLARE(pdn_t*) mme_pdn_find_by_apn(mme_ue_t *ue, c_int8_t *apn);
CORE_DECLARE(pdn_t*) mme_pdn_first(mme_ue_t *ue);
CORE_DECLARE(pdn_t*) mme_pdn_next(pdn_t *pdn);
CORE_DECLARE(enb_ue_t*) enb_ue_add(mme_enb_t *enb);
CORE_DECLARE(unsigned int) enb_ue_count();
CORE_DECLARE(status_t) enb_ue_remove(enb_ue_t *ue);
CORE_DECLARE(status_t) enb_ue_remove_in_enb(mme_enb_t *enb);
CORE_DECLARE(enb_ue_t*) enb_ue_find(index_t index);
CORE_DECLARE(enb_ue_t*) enb_ue_find_by_enb_ue_s1ap_id(mme_enb_t *enb,
c_uint32_t enb_ue_s1ap_id);
CORE_DECLARE(enb_ue_t*) enb_ue_find_by_mme_ue_s1ap_id(c_uint32_t mme_ue_s1ap_id);
CORE_DECLARE(enb_ue_t*) enb_ue_first_in_enb(mme_enb_t *enb);
CORE_DECLARE(enb_ue_t*) enb_ue_next_in_enb(enb_ue_t *ue);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -32,6 +32,7 @@ status_t mme_s11_build_create_session_request(pkbuf_t **pkbuf, mme_bearer_t *bea
d_assert(sgw, return CORE_ERROR, "Null param");
ue = bearer->ue;
d_assert(ue, return CORE_ERROR, "Null param");
d_assert(ue->enb_ue, return CORE_ERROR, "Null param");
memset(&gtp_message, 0, sizeof(gtp_message_t));
@ -48,10 +49,10 @@ status_t mme_s11_build_create_session_request(pkbuf_t **pkbuf, mme_bearer_t *bea
memset(&uli, 0, sizeof(gtp_uli_t));
uli.flags.e_cgi = 1;
uli.flags.tai = 1;
memcpy(&uli.tai.plmn_id, &ue->tai.plmn_id, sizeof(uli.tai.plmn_id));
uli.tai.tac = ue->tai.tac;
memcpy(&uli.e_cgi.plmn_id, &ue->e_cgi.plmn_id, sizeof(uli.tai.plmn_id));
uli.e_cgi.cell_id = ue->e_cgi.cell_id;
memcpy(&uli.tai.plmn_id, &ue->enb_ue->tai.plmn_id, sizeof(uli.tai.plmn_id));
uli.tai.tac = ue->enb_ue->tai.tac;
memcpy(&uli.e_cgi.plmn_id, &ue->enb_ue->e_cgi.plmn_id, sizeof(uli.tai.plmn_id));
uli.e_cgi.cell_id = ue->enb_ue->e_cgi.cell_id;
req->user_location_information.presence = 1;
gtp_build_uli(&req->user_location_information, &uli,
uli_buf, GTP_MAX_ULI_LEN);

View File

@ -10,6 +10,7 @@
#include "nas_security.h"
#include "mme_s11_path.h"
#include "mme_s11_handler.h"
#include "emm_handler.h"
void mme_state_initial(fsm_t *s, event_t *e)
{
@ -145,6 +146,42 @@ void mme_state_operational(fsm_t *s, event_t *e)
break;
}
case MME_EVT_EMM_UE_MSG:
{
nas_message_t message;
index_t index = event_get_param1(e);
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param2(e);
//int mac_failed = event_get_param3(e);
enb_ue_t *ue = NULL;
mme_ue_t *mme_ue = NULL;
ue = enb_ue_find(index);
d_assert(ue, break, "No ENB UE context");
d_assert(pkbuf, break, "Null param");
d_assert(nas_emm_decode(&message, pkbuf) == CORE_OK,
pkbuf_free(pkbuf); break, "Can't decode NAS_EMM");
mme_ue = ue->mme_ue;
if (mme_ue == NULL)
{
/* Find MME UE by NAS message or create if needed */
mme_ue = emm_find_ue_by_message(ue, &message);
}
d_assert(mme_ue, pkbuf_free(pkbuf);break, "No MME UE context");
d_assert(FSM_STATE(&mme_ue->sm), pkbuf_free(pkbuf);break,
"No EMM State Machine");
/* Set event */
event_set_param1(e, (c_uintptr_t)mme_ue->index);/* mme_ue index */
event_set_param3(e, (c_uintptr_t)&message);
fsm_dispatch(&mme_ue->sm, (fsm_event_t*)e);
pkbuf_free(pkbuf);
break;
}
case MME_EVT_EMM_UE_FROM_S6A:
case MME_EVT_EMM_UE_FROM_S11:
case MME_EVT_EMM_BEARER_FROM_S11:

View File

@ -110,7 +110,7 @@ status_t nas_security_encode(
return CORE_OK;
}
status_t nas_security_decode(mme_ue_t *ue, pkbuf_t *pkbuf)
status_t nas_security_decode(mme_ue_t *ue, pkbuf_t *pkbuf, int *mac_failed)
{
c_int32_t hsize = 0;
@ -123,6 +123,7 @@ status_t nas_security_decode(mme_ue_t *ue, pkbuf_t *pkbuf)
d_assert(ue, return CORE_ERROR, "Null param");
d_assert(pkbuf, return CORE_ERROR, "Null param");
d_assert(pkbuf->payload, return CORE_ERROR, "Null param");
d_assert(mac_failed, return CORE_ERROR, "Null param");
h = pkbuf->payload;
switch(h->security_header_type)
@ -203,10 +204,15 @@ status_t nas_security_decode(mme_ue_t *ue, pkbuf_t *pkbuf)
memcpy(&mac32, mac, NAS_SECURITY_MAC_SIZE);
if (h->message_authentication_code != mac32)
{
#if 0
d_error("NAS MAC verification failed");
d_assert(pkbuf_header(pkbuf, hsize-1) == CORE_OK,
return CORE_ERROR, "pkbuf_header error");
return CORE_ERROR;
#else
d_warn("NAS MAC verification failed");
*mac_failed = 1;
#endif
}
}

View File

@ -22,7 +22,7 @@ extern "C" {
CORE_DECLARE(status_t) nas_security_encode(
pkbuf_t **pkbuf, mme_ue_t *ue, nas_message_t *message);
CORE_DECLARE(status_t) nas_security_decode(
mme_ue_t *ue, pkbuf_t *pkbuf);
mme_ue_t *ue, pkbuf_t *pkbuf, int *mac_failed);
CORE_DECLARE(void) nas_mac_calculate(c_uint8_t algorithm_identity,
c_uint8_t *knas_int, c_uint32_t count, c_uint8_t bearer,

View File

@ -107,7 +107,7 @@ status_t s1ap_build_setup_failure(pkbuf_t **pkbuf, S1ap_Cause_t cause)
}
status_t s1ap_build_downlink_nas_transport(
pkbuf_t **s1apbuf, mme_ue_t *ue, pkbuf_t *emmbuf)
pkbuf_t **s1apbuf, enb_ue_t *ue, pkbuf_t *emmbuf)
{
char buf[INET_ADDRSTRLEN];
@ -159,12 +159,15 @@ status_t s1ap_build_initial_context_setup_request(
S1ap_E_RABToBeSetupItemCtxtSUReq_t *e_rab = NULL;
struct S1ap_GBR_QosInformation *gbrQosInformation = NULL; /* OPTIONAL */
S1ap_NAS_PDU_t *nasPdu = NULL;
mme_ue_t *ue = NULL;
mme_ue_t *mme_ue = NULL;
enb_ue_t *ue = NULL;
pdn_t *pdn = NULL;
d_assert(emmbuf, return CORE_ERROR, "Null param");
d_assert(bearer, return CORE_ERROR, "Null param");
ue = bearer->ue;
mme_ue = bearer->ue;
d_assert(mme_ue, return CORE_ERROR, "Null param");
ue = mme_ue->enb_ue;
d_assert(ue, return CORE_ERROR, "Null param");
pdn = bearer->pdn;
d_assert(pdn, return CORE_ERROR, "Null param");
@ -176,10 +179,10 @@ status_t s1ap_build_initial_context_setup_request(
asn_uint642INTEGER(
&ies->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL,
ue->max_bandwidth_ul);
mme_ue->max_bandwidth_ul);
asn_uint642INTEGER(
&ies->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL,
ue->max_bandwidth_dl);
mme_ue->max_bandwidth_dl);
e_rab = (S1ap_E_RABToBeSetupItemCtxtSUReq_t *)
core_calloc(1, sizeof(S1ap_E_RABToBeSetupItemCtxtSUReq_t));
@ -224,7 +227,7 @@ status_t s1ap_build_initial_context_setup_request(
sizeof(c_uint8_t));
ies->ueSecurityCapabilities.encryptionAlgorithms.bits_unused = 0;
ies->ueSecurityCapabilities.encryptionAlgorithms.buf[0] =
ue->ue_network_capability.eea;
mme_ue->ue_network_capability.eea;
ies->ueSecurityCapabilities.integrityProtectionAlgorithms.size = 2;
ies->ueSecurityCapabilities.integrityProtectionAlgorithms.buf =
@ -232,13 +235,13 @@ status_t s1ap_build_initial_context_setup_request(
integrityProtectionAlgorithms.size, sizeof(c_uint8_t));
ies->ueSecurityCapabilities.integrityProtectionAlgorithms.bits_unused = 0;
ies->ueSecurityCapabilities.integrityProtectionAlgorithms.buf[0] =
(ue->ue_network_capability.eia << 1);
(mme_ue->ue_network_capability.eia << 1);
ies->securityKey.size = SHA256_DIGEST_SIZE;
ies->securityKey.buf =
core_calloc(ies->securityKey.size, sizeof(c_uint8_t));
ies->securityKey.bits_unused = 0;
memcpy(ies->securityKey.buf, ue->kenb, ies->securityKey.size);
memcpy(ies->securityKey.buf, mme_ue->kenb, ies->securityKey.size);
message.procedureCode = S1ap_ProcedureCode_id_InitialContextSetup;
message.direction = S1AP_PDU_PR_initiatingMessage;

View File

@ -12,7 +12,7 @@ CORE_DECLARE(status_t) s1ap_build_setup_rsp(pkbuf_t **pkbuf);
CORE_DECLARE(status_t) s1ap_build_setup_failure(
pkbuf_t **pkbuf, S1ap_Cause_t cause);
CORE_DECLARE(status_t) s1ap_build_downlink_nas_transport(
pkbuf_t **s1apbuf, mme_ue_t *ue, pkbuf_t *emmbuf);
pkbuf_t **s1apbuf, enb_ue_t *ue, pkbuf_t *emmbuf);
CORE_DECLARE(status_t) s1ap_build_initial_context_setup_request(
pkbuf_t **s1apbuf, mme_bearer_t *bearer, pkbuf_t *emmbuf);

View File

@ -12,11 +12,12 @@
#include "s1ap_handler.h"
static void event_s1ap_to_nas(mme_ue_t *ue, S1ap_NAS_PDU_t *nasPdu)
static void event_s1ap_to_nas(enb_ue_t *ue, S1ap_NAS_PDU_t *nasPdu)
{
nas_esm_header_t *h = NULL;
pkbuf_t *nasbuf = NULL;
event_t e;
int mac_failed = 0;
d_assert(ue, return, "Null param");
d_assert(nasPdu, return, "Null param");
@ -27,8 +28,34 @@ static void event_s1ap_to_nas(mme_ue_t *ue, S1ap_NAS_PDU_t *nasPdu)
d_assert(nasbuf, return, "Null param");
memcpy(nasbuf->payload, nasPdu->buf, nasPdu->size);
d_assert(nas_security_decode(ue, nasbuf) == CORE_OK,
pkbuf_free(nasbuf); return, "Can't decode NAS_PDU");
if (ue->mme_ue)
{
d_assert(nas_security_decode(ue->mme_ue, nasbuf,
&mac_failed) == CORE_OK,
pkbuf_free(nasbuf);return,
"nas_security_decode failed");
}
else
{
/* FIXME */
c_uint32_t hsize = sizeof(nas_security_header_t);
nas_security_header_t *sh = NULL;
sh = nasbuf->payload;
switch(sh->security_header_type)
{
case NAS_SECURITY_HEADER_PLAIN_NAS_MESSAGE:
case NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE:
{
break;
}
default:
mac_failed = 1;
d_warn("Security Protected (securiry header type:0x%x)",
sh->security_header_type);
pkbuf_header(nasbuf, -hsize);
}
}
h = nasbuf->payload;
d_assert(h, pkbuf_free(nasbuf); return, "Null param");
@ -37,22 +64,34 @@ static void event_s1ap_to_nas(mme_ue_t *ue, S1ap_NAS_PDU_t *nasPdu)
event_set(&e, MME_EVT_EMM_UE_MSG);
event_set_param1(&e, (c_uintptr_t)ue->index);
event_set_param2(&e, (c_uintptr_t)nasbuf);
event_set_param3(&e, (c_uintptr_t)mac_failed);
mme_event_send(&e);
}
else if (h->protocol_discriminator == NAS_PROTOCOL_DISCRIMINATOR_ESM)
{
mme_bearer_t *bearer = mme_bearer_find_by_pti(ue,
mme_bearer_t *bearer = NULL;
mme_ue_t *mme_ue = ue->mme_ue;
if (!mme_ue)
{
d_error("No mme_ue exists");
pkbuf_free(nasbuf);
return;
}
bearer = mme_bearer_find_by_pti(mme_ue,
h->procedure_transaction_identity);
if (bearer)
{
event_set(&e, MME_EVT_ESM_BEARER_MSG);
event_set_param1(&e, (c_uintptr_t)bearer->index);
event_set_param2(&e, (c_uintptr_t)nasbuf);
event_set_param3(&e, (c_uintptr_t)mac_failed);
mme_event_send(&e);
}
else
d_error("Can't find ESM context(UE:%s, PTI:%d)",
ue->imsi_bcd, h->procedure_transaction_identity);
mme_ue->imsi_bcd, h->procedure_transaction_identity);
}
else
d_assert(0, pkbuf_free(nasbuf); return, "Unknown protocol:%d",
@ -111,7 +150,7 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, s1ap_message_t *message)
{
char buf[INET_ADDRSTRLEN];
mme_ue_t *ue = NULL;
enb_ue_t *ue = NULL;
S1ap_InitialUEMessage_IEs_t *ies = NULL;
S1ap_TAI_t *tai = NULL;
S1ap_PLMNidentity_t *pLMNidentity = NULL;
@ -138,10 +177,10 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, s1ap_message_t *message)
cell_ID = &eutran_cgi->cell_ID;
d_assert(cell_ID, return,);
ue = mme_ue_find_by_enb_ue_s1ap_id(enb, ies->eNB_UE_S1AP_ID);
ue = enb_ue_find_by_enb_ue_s1ap_id(enb, ies->eNB_UE_S1AP_ID);
if (!ue)
{
ue = mme_ue_add(enb);
ue = enb_ue_add(enb);
d_assert(ue, return, "Null param");
ue->enb_ue_s1ap_id = ies->eNB_UE_S1AP_ID;
@ -160,7 +199,7 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, s1ap_message_t *message)
memcpy(&ue->e_cgi.cell_id, cell_ID->buf, sizeof(ue->e_cgi.cell_id));
ue->e_cgi.cell_id = (ntohl(ue->e_cgi.cell_id) >> 4);
d_assert(enb->s1ap_sock, mme_ue_remove(ue); return,);
d_assert(enb->s1ap_sock, enb_ue_remove(ue); return,);
d_info("[S1AP] InitialUEMessage : UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]",
ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
@ -174,13 +213,13 @@ void s1ap_handle_uplink_nas_transport(
{
char buf[INET_ADDRSTRLEN];
mme_ue_t *ue = NULL;
enb_ue_t *ue = NULL;
S1ap_UplinkNASTransport_IEs_t *ies = NULL;
ies = &message->s1ap_UplinkNASTransport_IEs;
d_assert(ies, return, "Null param");
ue = mme_ue_find_by_enb_ue_s1ap_id(enb, ies->eNB_UE_S1AP_ID);
ue = enb_ue_find_by_enb_ue_s1ap_id(enb, ies->eNB_UE_S1AP_ID);
d_assert(ue, return, "Null param");
d_info("[S1AP] uplinkNASTransport : UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]",
@ -196,13 +235,13 @@ void s1ap_handle_ue_capability_info_indication(
{
char buf[INET_ADDRSTRLEN];
mme_ue_t *ue = NULL;
enb_ue_t *ue = NULL;
S1ap_UECapabilityInfoIndicationIEs_t *ies = NULL;
ies = &message->s1ap_UECapabilityInfoIndicationIEs;
d_assert(ies, return, "Null param");
ue = mme_ue_find_by_enb_ue_s1ap_id(enb, ies->eNB_UE_S1AP_ID);
ue = enb_ue_find_by_enb_ue_s1ap_id(enb, ies->eNB_UE_S1AP_ID);
d_assert(ue, return, "No UE Context[%d]", ies->eNB_UE_S1AP_ID);
d_info("[S1AP] UE Capability Info Indication : "
@ -218,13 +257,13 @@ void s1ap_handle_initial_context_setup_response(
char buf[INET_ADDRSTRLEN];
int i = 0;
mme_ue_t *ue = NULL;
enb_ue_t *ue = NULL;
S1ap_InitialContextSetupResponseIEs_t *ies = NULL;
ies = &message->s1ap_InitialContextSetupResponseIEs;
d_assert(ies, return, "Null param");
ue = mme_ue_find_by_enb_ue_s1ap_id(enb, ies->eNB_UE_S1AP_ID);
ue = enb_ue_find_by_enb_ue_s1ap_id(enb, ies->eNB_UE_S1AP_ID);
d_assert(ue, return, "No UE Context[%d]", ies->eNB_UE_S1AP_ID);
d_info("[S1AP] Initial Context Setup Response : "
@ -239,13 +278,14 @@ void s1ap_handle_initial_context_setup_response(
{
event_t e;
mme_bearer_t *bearer = NULL;
mme_ue_t *mme_ue = ue->mme_ue;
S1ap_E_RABSetupItemCtxtSURes_t *e_rab = NULL;
e_rab = (S1ap_E_RABSetupItemCtxtSURes_t *)
ies->e_RABSetupListCtxtSURes.s1ap_E_RABSetupItemCtxtSURes.array[i];
d_assert(e_rab, return, "Null param");
bearer = mme_bearer_find_by_ebi(ue, e_rab->e_RAB_ID);
bearer = mme_bearer_find_by_ebi(mme_ue, e_rab->e_RAB_ID);
d_assert(bearer, return, "Null param");
memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf,
sizeof(bearer->enb_s1u_teid));