diff --git a/src/mme/emm_handler.c b/src/mme/emm_handler.c index 371fe0dd98..0ff84b8478 100644 --- a/src/mme/emm_handler.c +++ b/src/mme/emm_handler.c @@ -31,28 +31,12 @@ void event_emm_to_esm( c_uint8_t pti = NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED; c_uint8_t ebi = NAS_EPS_BEARER_IDENTITY_UNASSIGNED; mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; d_assert(mme_ue, return, "Null param"); d_assert(esm_message_container, return, "Null param"); d_assert(esm_message_container->len, return, "Null param"); - h = (nas_esm_header_t *)esm_message_container->data; - d_assert(h, return, "Null param"); - - pti = h->procedure_transaction_identity; - ebi = h->eps_bearer_identity; - - if (ebi != NAS_EPS_BEARER_IDENTITY_UNASSIGNED) - sess = mme_sess_find_by_ebi(mme_ue, ebi); - else if (pti != NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED) - sess = mme_sess_find_by_pti(mme_ue, pti); - else - d_assert(0, return, "Invalid pti(%d) and ebi(%d)\n", pti, ebi); - - if (!sess) - sess = mme_sess_add(mme_ue, pti); - d_assert(sess, return, "Null param"); - /* The Packet Buffer(pkbuf_t) for NAS message MUST make a HEADROOM. * When calculating AES_CMAC, we need to use the headroom of the packet. */ esmbuf = pkbuf_alloc(NAS_HEADROOM, esm_message_container->len); @@ -60,8 +44,29 @@ void event_emm_to_esm( memcpy(esmbuf->payload, esm_message_container->data, esm_message_container->len); + h = (nas_esm_header_t *)esm_message_container->data; + d_assert(h, return, "Null param"); + + pti = h->procedure_transaction_identity; + ebi = h->eps_bearer_identity; + + if (ebi != NAS_EPS_BEARER_IDENTITY_UNASSIGNED) + bearer = mme_bearer_find_by_ue_ebi(mme_ue, ebi); + else if (pti != NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED) + bearer = mme_bearer_find_by_ue_pti(mme_ue, pti); + else + d_assert(0, return, "Invalid pti(%d) and ebi(%d)\n", pti, ebi); + + if (!bearer) + { + sess = mme_sess_add(mme_ue, pti); + d_assert(sess, return, "Null param"); + bearer = mme_default_bearer_in_sess(sess); + } + d_assert(bearer, return, "Null param"); + event_set(&e, MME_EVT_ESM_MESSAGE); - event_set_param1(&e, (c_uintptr_t)sess->index); + event_set_param1(&e, (c_uintptr_t)bearer->index); event_set_param2(&e, (c_uintptr_t)esmbuf); mme_event_send(&e); } @@ -177,7 +182,7 @@ void emm_handle_attach_accept(mme_ue_t *mme_ue) d_assert(rv == CORE_OK && esmbuf, return, "esm build error"); d_trace(3, "[NAS] Activate default bearer context request : " - "EMM <-- ESM[%d]\n", sess->pti); + "EMM <-- ESM\n"); rv = emm_build_attach_accept(&emmbuf, mme_ue, esmbuf); d_assert(rv == CORE_OK && emmbuf, @@ -260,6 +265,7 @@ void emm_handle_attach_reject(mme_ue_t *mme_ue, mme_enb_t *enb = NULL; enb_ue_t *enb_ue = NULL; mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; pkbuf_t *s1apbuf = NULL, *esmbuf = NULL, *emmbuf = NULL; S1ap_Cause_t cause; @@ -272,10 +278,15 @@ void emm_handle_attach_reject(mme_ue_t *mme_ue, sess = mme_sess_first(mme_ue); if (sess) { - rv = esm_build_pdn_connectivity_reject(&esmbuf, sess->pti, esm_cause); - d_assert(rv == CORE_OK && esmbuf, return, "esm build error"); - d_trace(3, "[NAS] PDN Connectivity reject : " - "EMM <-- ESM[%d]\n", sess->pti); + bearer = mme_default_bearer_in_sess(sess); + if (bearer) + { + rv = esm_build_pdn_connectivity_reject( + &esmbuf, bearer->pti, esm_cause); + d_assert(rv == CORE_OK && esmbuf, return, "esm build error"); + d_trace(3, "[NAS] PDN Connectivity reject : EMM <-- ESM\n", + bearer->pti); + } } rv = emm_build_attach_reject(&emmbuf, emm_cause, esmbuf); diff --git a/src/mme/esm_build.c b/src/mme/esm_build.c index 10be8f9534..1c83ae0d42 100644 --- a/src/mme/esm_build.c +++ b/src/mme/esm_build.c @@ -28,13 +28,13 @@ status_t esm_build_pdn_connectivity_reject( return CORE_OK; } -status_t esm_build_information_request(pkbuf_t **pkbuf, mme_sess_t *sess) +status_t esm_build_information_request(pkbuf_t **pkbuf, mme_bearer_t *bearer) { nas_message_t message; mme_ue_t *mme_ue = NULL; - d_assert(sess, return CORE_ERROR, "Null param"); - mme_ue = sess->mme_ue; + d_assert(bearer, return CORE_ERROR, "Null param"); + mme_ue = bearer->mme_ue; d_assert(mme_ue, return CORE_ERROR, "Null param"); memset(&message, 0, sizeof(message)); @@ -43,7 +43,7 @@ status_t esm_build_information_request(pkbuf_t **pkbuf, mme_sess_t *sess) message.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; message.esm.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_ESM; - message.esm.h.procedure_transaction_identity = sess->pti; + message.esm.h.procedure_transaction_identity = bearer->pti; message.esm.h.message_type = NAS_ESM_INFORMATION_REQUEST; d_assert(nas_security_encode(pkbuf, mme_ue, &message) == CORE_OK && @@ -86,7 +86,7 @@ status_t esm_build_activate_default_bearer_context( memset(&message, 0, sizeof(message)); message.esm.h.eps_bearer_identity = bearer->ebi; message.esm.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_ESM; - message.esm.h.procedure_transaction_identity = sess->pti; + message.esm.h.procedure_transaction_identity = bearer->pti; message.esm.h.message_type = NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST; diff --git a/src/mme/esm_build.h b/src/mme/esm_build.h index 8e95ae2d12..7da78df193 100644 --- a/src/mme/esm_build.h +++ b/src/mme/esm_build.h @@ -11,7 +11,7 @@ CORE_DECLARE(status_t) esm_build_pdn_connectivity_reject(pkbuf_t **pkbuf, c_uint8_t pti, nas_esm_cause_t esm_cause); CORE_DECLARE(status_t) esm_build_information_request(pkbuf_t **pkbuf, - mme_sess_t *sess); + mme_bearer_t *bearer); CORE_DECLARE(status_t) esm_build_activate_default_bearer_context( pkbuf_t **pkbuf, mme_sess_t *sess); diff --git a/src/mme/esm_handler.c b/src/mme/esm_handler.c index e6ad429d24..5514eae31d 100644 --- a/src/mme/esm_handler.c +++ b/src/mme/esm_handler.c @@ -29,22 +29,6 @@ void esm_handle_pdn_connectivity_request(mme_sess_t *sess, } } -void esm_handle_information_request(mme_sess_t *sess) -{ - status_t rv; - pkbuf_t *esmbuf = NULL; - mme_ue_t *mme_ue = NULL; - - d_assert(sess, return, "Null param"); - mme_ue = sess->mme_ue; - d_assert(mme_ue, return, "Null param"); - - rv = esm_build_information_request(&esmbuf, sess); - d_assert(rv == CORE_OK && esmbuf, return, "esm_build failed"); - d_assert(nas_send_to_downlink_nas_transport(mme_ue, esmbuf) == CORE_OK,,); -} - - void esm_handle_information_response(mme_sess_t *sess, nas_esm_information_response_t *esm_information_response) { diff --git a/src/mme/esm_handler.h b/src/mme/esm_handler.h index 5d040fd757..49b08d18b1 100644 --- a/src/mme/esm_handler.h +++ b/src/mme/esm_handler.h @@ -11,7 +11,6 @@ extern "C" { CORE_DECLARE(void) esm_handle_pdn_connectivity_request(mme_sess_t *sess, nas_pdn_connectivity_request_t *pdn_connectivity_request); -CORE_DECLARE(void) esm_handle_information_request(mme_sess_t *sess); CORE_DECLARE(void) esm_handle_information_response(mme_sess_t *sess, nas_esm_information_response_t *bearer_information_response); diff --git a/src/mme/esm_sm.c b/src/mme/esm_sm.c index 0eb00674c1..9bb7dac2b8 100644 --- a/src/mme/esm_sm.c +++ b/src/mme/esm_sm.c @@ -10,6 +10,7 @@ #include "esm_build.h" #include "esm_handler.h" #include "mme_s11_handler.h" +#include "nas_path.h" void esm_state_initial(fsm_t *s, event_t *e) { @@ -29,15 +30,18 @@ void esm_state_final(fsm_t *s, event_t *e) void esm_state_operational(fsm_t *s, event_t *e) { - mme_sess_t *sess = NULL; mme_ue_t *mme_ue = NULL; + mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; d_assert(s, return, "Null param"); d_assert(e, return, "Null param"); mme_sm_trace(3, e); - sess = mme_sess_find(event_get_param1(e)); + bearer = mme_bearer_find(event_get_param1(e)); + d_assert(bearer, return, "Null param"); + sess = bearer->sess; d_assert(sess, return, "Null param"); mme_ue = sess->mme_ue; d_assert(mme_ue, return, "Null param"); @@ -65,7 +69,7 @@ void esm_state_operational(fsm_t *s, event_t *e) sess, &message->esm.pdn_connectivity_request); d_trace(3, "[NAS] PDN connectivity request : " "UE[%s] --> ESM[%d]\n", - mme_ue->imsi_bcd, sess->pti); + mme_ue->imsi_bcd, bearer->pti); d_assert(MME_UE_HAVE_IMSI(mme_ue), break, "No IMSI in PDN_CPNNECTIVITY_REQUEST"); @@ -85,7 +89,14 @@ void esm_state_operational(fsm_t *s, event_t *e) } else { - esm_handle_information_request(sess); + status_t rv; + pkbuf_t *esmbuf = NULL; + + rv = esm_build_information_request(&esmbuf, bearer); + d_assert(rv == CORE_OK && esmbuf, break, + "esm_build failed"); + d_assert(nas_send_to_downlink_nas_transport( + mme_ue, esmbuf) == CORE_OK,,); } break; } @@ -93,7 +104,7 @@ void esm_state_operational(fsm_t *s, event_t *e) { d_trace(3, "[NAS] ESM information response : " "UE[%s] --> ESM[%d]\n", - mme_ue->imsi_bcd, sess->pti); + mme_ue->imsi_bcd, bearer->pti); esm_handle_information_response( sess, &message->esm.esm_information_response); @@ -104,7 +115,7 @@ void esm_state_operational(fsm_t *s, event_t *e) { d_trace(3, "[NAS] Activate default eps bearer " "context accept : UE[%s] --> ESM[%d]\n", - mme_ue->imsi_bcd, sess->pti); + mme_ue->imsi_bcd, bearer->pti); break; } default: diff --git a/src/mme/mme_context.c b/src/mme/mme_context.c index 980e59621f..dfa7fcda9d 100644 --- a/src/mme/mme_context.c +++ b/src/mme/mme_context.c @@ -1472,7 +1472,6 @@ mme_sess_t *mme_sess_add(mme_ue_t *mme_ue, c_uint8_t pti) { mme_sess_t *sess = NULL; mme_bearer_t *bearer = NULL; - event_t e; d_assert(mme_ue, return NULL, "Null param"); d_assert(pti != NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, @@ -1481,37 +1480,25 @@ mme_sess_t *mme_sess_add(mme_ue_t *mme_ue, c_uint8_t pti) index_alloc(&mme_sess_pool, &sess); d_assert(sess, return NULL, "Null param"); - sess->pti = pti; - list_init(&sess->bearer_list); list_append(&mme_ue->sess_list, sess); sess->mme_ue = mme_ue; sess->sgw = mme_sgw_first(); - bearer = mme_bearer_add(sess, - NEXT_ID(mme_ue->ebi, MIN_EPS_BEARER_ID, MAX_EPS_BEARER_ID)); + bearer = mme_bearer_add(sess); d_assert(bearer, mme_sess_remove(sess); return NULL, "Can't add default bearer context"); - - event_set_param1(&e, (c_uintptr_t)sess->index); - fsm_create(&sess->sm, esm_state_initial, esm_state_final); - fsm_init(&sess->sm, &e); + bearer->pti = pti; return sess; } status_t mme_sess_remove(mme_sess_t *sess) { - event_t e; - d_assert(sess, return CORE_ERROR, "Null param"); d_assert(sess->mme_ue, return CORE_ERROR, "Null param"); - event_set_param1(&e, (c_uintptr_t)sess->index); - fsm_final(&sess->sm, &e); - fsm_clear(&sess->sm); - mme_bearer_remove_all(sess); list_remove(&sess->mme_ue->sess_list, sess); @@ -1545,16 +1532,11 @@ mme_sess_t* mme_sess_find(index_t index) mme_sess_t* mme_sess_find_by_pti(mme_ue_t *mme_ue, c_uint8_t pti) { - mme_sess_t *sess = NULL; - - sess = mme_sess_first(mme_ue); - while (sess) - { - if (pti == sess->pti) - return sess; + mme_bearer_t *bearer = NULL; - sess = mme_sess_next(sess); - } + bearer = mme_bearer_find_by_ue_pti(mme_ue, pti); + if (bearer) + return bearer->sess; return NULL; } @@ -1580,8 +1562,10 @@ mme_sess_t* mme_sess_next(mme_sess_t *sess) return list_next(sess); } -mme_bearer_t* mme_bearer_add(mme_sess_t *sess, c_uint8_t ebi) +mme_bearer_t* mme_bearer_add(mme_sess_t *sess) { + event_t e; + mme_bearer_t *bearer = NULL; mme_ue_t *mme_ue = NULL; @@ -1592,20 +1576,30 @@ mme_bearer_t* mme_bearer_add(mme_sess_t *sess, c_uint8_t ebi) index_alloc(&mme_bearer_pool, &bearer); d_assert(bearer, return NULL, "Null param"); - bearer->ebi = ebi; + bearer->ebi = NEXT_ID(mme_ue->ebi, MIN_EPS_BEARER_ID, MAX_EPS_BEARER_ID); list_append(&sess->bearer_list, bearer); bearer->mme_ue = mme_ue; bearer->sess = sess; + event_set_param1(&e, (c_uintptr_t)bearer->index); + fsm_create(&bearer->sm, esm_state_initial, esm_state_final); + fsm_init(&bearer->sm, &e); + return bearer; } status_t mme_bearer_remove(mme_bearer_t *bearer) { + event_t e; + d_assert(bearer, return CORE_ERROR, "Null param"); d_assert(bearer->sess, return CORE_ERROR, "Null param"); + + event_set_param1(&e, (c_uintptr_t)bearer->index); + fsm_final(&bearer->sm, &e); + fsm_clear(&bearer->sm); list_remove(&bearer->sess->bearer_list, bearer); index_free(&mme_bearer_pool, bearer); @@ -1638,6 +1632,42 @@ mme_bearer_t* mme_bearer_find(index_t index) return index_find(&mme_bearer_pool, index); } +mme_bearer_t* mme_bearer_find_by_sess_pti(mme_sess_t *sess, c_uint8_t pti) +{ + mme_bearer_t *bearer = NULL; + + bearer = mme_bearer_first(sess); + while(bearer) + { + if (pti == bearer->pti) + return bearer; + + bearer = mme_bearer_next(bearer); + } + + return NULL; +} + +mme_bearer_t* mme_bearer_find_by_ue_pti(mme_ue_t *mme_ue, c_uint8_t pti) +{ + mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; + + sess = mme_sess_first(mme_ue); + while (sess) + { + bearer = mme_bearer_find_by_sess_pti(sess, pti); + if (bearer) + { + return bearer; + } + + sess = mme_sess_next(sess); + } + + return NULL; +} + mme_bearer_t* mme_bearer_find_by_sess_ebi(mme_sess_t *sess, c_uint8_t ebi) { mme_bearer_t *bearer = NULL; diff --git a/src/mme/mme_context.h b/src/mme/mme_context.h index f072240828..e340d2e39c 100644 --- a/src/mme/mme_context.h +++ b/src/mme/mme_context.h @@ -242,12 +242,17 @@ struct _mme_ue_t { nas_detach_type_t detach_type; }; +#define MME_SESSION_IS_VALID(__sESS) \ + ((__sESS) && (mme_bearer_first(__sESS)) && \ + ((mme_default_bearer_in_sess(__sESS)->sgw_s1u_teid) && \ + (mme_default_bearer_in_sess(__sESS)->sgw_s1u_addr))) + +#define MME_UE_HAVE_SESSION(__mME) \ + ((__mME) && (mme_sess_first(__mME)) && \ + MME_SESSION_IS_VALID(mme_sess_first(__mME))) typedef struct _mme_sess_t { lnode_t node; /* A node of list_t */ index_t index; /* An index of this node */ - fsm_t sm; /* State Machine */ - - c_uint8_t pti; /* Procedure Trasaction Identity */ /* mme_bearer_first(sess) : Default Bearer Context */ list_t bearer_list; @@ -278,28 +283,27 @@ typedef struct _mme_sess_t { int pgw_pco_len; } mme_sess_t; +#define MME_BEARER_IS_VALID(__bEARER) \ + ((__bEARER) && ((__bEARER)->enb_s1u_teid) && ((__bEARER)->enb_s1u_addr)) typedef struct _mme_bearer_t { lnode_t node; /* A node of list_t */ index_t index; /* An index of this node */ + fsm_t sm; /* State Machine */ c_uint8_t ebi; /* EPS Bearer ID */ + c_uint8_t pti; /* Procedure Trasaction Identity */ -#define MME_SESSION_IS_VALID(__sESS) \ - ((__sESS) && (mme_bearer_first(__sESS)) && \ - ((mme_default_bearer_in_sess(__sESS)->sgw_s1u_teid) && \ - (mme_default_bearer_in_sess(__sESS)->sgw_s1u_addr))) - -#define MME_UE_HAVE_SESSION(__mME) \ - ((__mME) && (mme_sess_first(__mME)) && \ - MME_SESSION_IS_VALID(mme_sess_first(__mME))) c_uint32_t enb_s1u_teid; c_uint32_t enb_s1u_addr; c_uint32_t sgw_s1u_teid; c_uint32_t sgw_s1u_addr; + qos_t qos; + /* Related Context */ mme_ue_t *mme_ue; mme_sess_t *sess; + gtp_xact_t *xact; } mme_bearer_t; CORE_DECLARE(status_t) mme_context_init(void); @@ -356,10 +360,14 @@ CORE_DECLARE(mme_sess_t*) mme_sess_find_by_ebi( CORE_DECLARE(mme_sess_t*) mme_sess_first(mme_ue_t *mme_ue); CORE_DECLARE(mme_sess_t*) mme_sess_next(mme_sess_t *sess); -CORE_DECLARE(mme_bearer_t*) mme_bearer_add(mme_sess_t *sess, c_uint8_t ebi); +CORE_DECLARE(mme_bearer_t*) mme_bearer_add(mme_sess_t *sess); CORE_DECLARE(status_t) mme_bearer_remove(mme_bearer_t *bearer); CORE_DECLARE(status_t) mme_bearer_remove_all(mme_sess_t *sess); CORE_DECLARE(mme_bearer_t*) mme_bearer_find(index_t index); +CORE_DECLARE(mme_bearer_t*) mme_bearer_find_by_sess_pti( + mme_sess_t *sess, c_uint8_t pti); +CORE_DECLARE(mme_bearer_t*) mme_bearer_find_by_ue_pti( + mme_ue_t *mme_ue, c_uint8_t pti); CORE_DECLARE(mme_bearer_t*) mme_bearer_find_by_sess_ebi( mme_sess_t *sess, c_uint8_t ebi); CORE_DECLARE(mme_bearer_t*) mme_bearer_find_by_ue_ebi( diff --git a/src/mme/mme_s11_handler.c b/src/mme/mme_s11_handler.c index ac988e5304..cb85bb0cec 100644 --- a/src/mme/mme_s11_handler.c +++ b/src/mme/mme_s11_handler.c @@ -91,7 +91,7 @@ void mme_s11_handle_create_session_response( pdn = sess->pdn; d_assert(pdn, return, "Null param"); - /* Receive Control Plane(UL) : SGW-S11 */ + /* Control Plane(UL) : SGW-S11 */ sgw_s11_teid = rsp->sender_f_teid_for_control_plane.data; mme_ue->sgw_s11_teid = ntohl(sgw_s11_teid->teid); mme_ue->sgw_s11_addr = sgw_s11_teid->ipv4_addr; @@ -99,6 +99,7 @@ void mme_s11_handle_create_session_response( memcpy(&pdn->paa, rsp->pdn_address_allocation.data, rsp->pdn_address_allocation.len); + /* PCO */ if (rsp->protocol_configuration_options.presence) { sess->pgw_pco_len = rsp->protocol_configuration_options.len; @@ -106,7 +107,7 @@ void mme_s11_handle_create_session_response( sess->pgw_pco_len); } - /* Receive Data Plane(UL) : SGW-S1U */ + /* Data Plane(UL) : SGW-S1U */ sgw_s1u_teid = rsp->bearer_contexts_created.s1_u_enodeb_f_teid.data; bearer->sgw_s1u_teid = ntohl(sgw_s1u_teid->teid); bearer->sgw_s1u_addr = sgw_s1u_teid->ipv4_addr; @@ -118,6 +119,22 @@ void mme_s11_handle_create_session_response( d_assert(rv == CORE_OK, return, "xact_commit error"); } +void mme_s11_handle_modify_bearer_response( + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_modify_bearer_response_t *rsp) +{ + status_t rv; + + d_assert(xact, return, "Null param"); + d_assert(mme_ue, return, "Null param"); + d_assert(rsp, return, "Null param"); + + d_trace(3, "[GTP] Modify Bearer Response : " + "MME[%d] <-- SGW[%d]\n", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + + rv = gtp_xact_commit(xact); + d_assert(rv == CORE_OK, return, "xact_commit error"); +} + void mme_s11_handle_delete_all_sessions_in_ue(mme_ue_t *mme_ue) { status_t rv; @@ -186,20 +203,73 @@ void mme_s11_handle_delete_session_response( d_assert(rv == CORE_OK, return, "xact_commit error"); } -void mme_s11_handle_modify_bearer_response( - gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_modify_bearer_response_t *rsp) +void mme_s11_handle_create_bearer_request( + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_create_bearer_request_t *req) { - status_t rv; + mme_bearer_t *bearer = NULL; + mme_sess_t *sess = NULL; + + gtp_f_teid_t *sgw_s1u_teid = NULL; + gtp_bearer_qos_t bearer_qos; d_assert(xact, return, "Null param"); d_assert(mme_ue, return, "Null param"); - d_assert(rsp, return, "Null param"); + d_assert(req, return, "Null param"); - d_trace(3, "[GTP] Modify Bearer Response : " + d_trace(3, "[GTP] Create Bearer Request : " "MME[%d] <-- SGW[%d]\n", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - rv = gtp_xact_commit(xact); - d_assert(rv == CORE_OK, return, "xact_commit error"); + if (req->linked_eps_bearer_id.presence == 0) + { + d_error("No Linked EBI"); + return; + } + if (req->bearer_contexts.presence == 0) + { + d_error("No Bearer"); + return; + } + if (req->bearer_contexts.eps_bearer_id.presence == 0) + { + d_error("No EPS Bearer ID"); + return; + } + if (req->bearer_contexts.s1_u_enodeb_f_teid.presence == 0) + { + d_error("No GTP TEID"); + return; + } + if (req->bearer_contexts.bearer_level_qos.presence == 0) + { + d_error("No QoS"); + return; + } + + sess = mme_sess_find_by_ebi(mme_ue, req->linked_eps_bearer_id.u8); + d_assert(sess, return, + "No Session Context(EBI:%d)", req->linked_eps_bearer_id); + + bearer = mme_bearer_add(sess); + d_assert(bearer, return, "No Bearer Context"); + + /* Data Plane(UL) : SGW-S1U */ + sgw_s1u_teid = req->bearer_contexts.s1_u_enodeb_f_teid.data; + bearer->sgw_s1u_teid = ntohl(sgw_s1u_teid->teid); + bearer->sgw_s1u_addr = sgw_s1u_teid->ipv4_addr; + + /* Bearer QoS */ + d_assert(gtp_parse_bearer_qos(&bearer_qos, + &req->bearer_contexts.bearer_level_qos) == + req->bearer_contexts.bearer_level_qos.len, return,); + bearer->qos.qci = bearer_qos.qci; + bearer->qos.arp.priority_level = bearer_qos.priority_level; + bearer->qos.arp.pre_emption_capability = + bearer_qos.pre_emption_capability; + bearer->qos.arp.pre_emption_vulnerability = + bearer_qos.pre_emption_vulnerability; + + /* Save Transaction */ + bearer->xact = xact; } void mme_s11_handle_release_access_bearers_response( diff --git a/src/mme/mme_s11_handler.h b/src/mme/mme_s11_handler.h index 77434e7b50..7789e401f8 100644 --- a/src/mme/mme_s11_handler.h +++ b/src/mme/mme_s11_handler.h @@ -12,12 +12,14 @@ extern "C" { CORE_DECLARE(void) mme_s11_handle_create_session_request(mme_sess_t *sess); CORE_DECLARE(void) mme_s11_handle_create_session_response( gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_create_session_response_t *rsp); +CORE_DECLARE(void) mme_s11_handle_modify_bearer_response( + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_modify_bearer_response_t *rsp); CORE_DECLARE(void) mme_s11_handle_delete_all_sessions_in_ue(mme_ue_t *mme_ue); CORE_DECLARE(void) mme_s11_handle_delete_session_response( gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_delete_session_response_t *rsp); +CORE_DECLARE(void) mme_s11_handle_create_bearer_request( + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_create_bearer_request_t *rsp); -CORE_DECLARE(void) mme_s11_handle_modify_bearer_response( - gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_modify_bearer_response_t *rsp); CORE_DECLARE(void) mme_s11_handle_release_access_bearers_response( gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_release_access_bearers_response_t *rsp); diff --git a/src/mme/mme_sm.c b/src/mme/mme_sm.c index 0bd644cac5..0b541af335 100644 --- a/src/mme/mme_sm.c +++ b/src/mme/mme_sm.c @@ -223,14 +223,11 @@ void mme_state_operational(fsm_t *s, event_t *e) case MME_EVT_ESM_MESSAGE: { nas_message_t message; - mme_sess_t *sess = NULL; - mme_ue_t *mme_ue = NULL; + mme_bearer_t *bearer = NULL; pkbuf_t *pkbuf = NULL; - sess = mme_sess_find(event_get_param1(e)); - d_assert(sess, break, "No Session context"); - d_assert(mme_ue = sess->mme_ue, break, "No UE context"); - d_assert(FSM_STATE(&sess->sm), break, "No ESM State Machine"); + bearer = mme_bearer_find(event_get_param1(e)); + d_assert(bearer, break, "No Bearer context"); pkbuf = (pkbuf_t *)event_get_param2(e); d_assert(pkbuf, break, "Null param"); @@ -239,7 +236,7 @@ void mme_state_operational(fsm_t *s, event_t *e) event_set_param3(e, (c_uintptr_t)&message); - fsm_dispatch(&sess->sm, (fsm_event_t*)e); + fsm_dispatch(&bearer->sm, (fsm_event_t*)e); pkbuf_free(pkbuf); @@ -388,6 +385,10 @@ void mme_state_operational(fsm_t *s, event_t *e) break; } + case GTP_CREATE_BEARER_REQUEST_TYPE: + mme_s11_handle_create_bearer_request( + xact, mme_ue, &message.create_bearer_request); + break; case GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE: { mme_s11_handle_release_access_bearers_response( diff --git a/src/mme/s1ap_handler.c b/src/mme/s1ap_handler.c index 34e2a33121..63eb315153 100644 --- a/src/mme/s1ap_handler.c +++ b/src/mme/s1ap_handler.c @@ -92,8 +92,11 @@ static void event_s1ap_to_nas(enb_ue_t *enb_ue, S1ap_NAS_PDU_t *nasPdu) } else if (h->protocol_discriminator == NAS_PROTOCOL_DISCRIMINATOR_ESM) { - mme_sess_t *sess = NULL; mme_ue_t *mme_ue = enb_ue->mme_ue; + mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; + c_uint8_t pti = NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED; + c_uint8_t ebi = NAS_EPS_BEARER_IDENTITY_UNASSIGNED; if (!mme_ue) { @@ -102,17 +105,28 @@ static void event_s1ap_to_nas(enb_ue_t *enb_ue, S1ap_NAS_PDU_t *nasPdu) return; } - sess = mme_sess_find_by_pti(mme_ue, h->procedure_transaction_identity); - if (sess) - { - event_set(&e, MME_EVT_ESM_MESSAGE); - event_set_param1(&e, (c_uintptr_t)sess->index); - event_set_param2(&e, (c_uintptr_t)nasbuf); - mme_event_send(&e); - } + pti = h->procedure_transaction_identity; + ebi = h->eps_bearer_identity; + + if (ebi != NAS_EPS_BEARER_IDENTITY_UNASSIGNED) + bearer = mme_bearer_find_by_ue_ebi(mme_ue, ebi); + else if (pti != NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED) + bearer = mme_bearer_find_by_ue_pti(mme_ue, pti); else - d_error("Can't find ESM context(UE:%s, PTI:%d)", - mme_ue->imsi_bcd, h->procedure_transaction_identity); + d_assert(0, return, "Invalid pti(%d) and ebi(%d)\n", pti, ebi); + + if (!bearer) + { + sess = mme_sess_add(mme_ue, pti); + d_assert(sess, return, "Null param"); + bearer = mme_default_bearer_in_sess(sess); + } + d_assert(bearer, return, "Null param"); + + event_set(&e, MME_EVT_ESM_MESSAGE); + event_set_param1(&e, (c_uintptr_t)bearer->index); + event_set_param2(&e, (c_uintptr_t)nasbuf); + mme_event_send(&e); } else d_assert(0, pkbuf_free(nasbuf); return, "Unknown protocol:%d", diff --git a/src/pgw/pgw_s5c_build.c b/src/pgw/pgw_s5c_build.c index 22fe7c6e9f..6e63a135f8 100644 --- a/src/pgw/pgw_s5c_build.c +++ b/src/pgw/pgw_s5c_build.c @@ -42,7 +42,7 @@ status_t pgw_s5c_build_create_session_response( rsp->cause.len = sizeof(cause); rsp->cause.data = &cause; - /* Send Control Plane(UL) : PGW-S5C */ + /* Control Plane(UL) : PGW-S5C */ memset(&pgw_s5c_teid, 0, sizeof(gtp_f_teid_t)); pgw_s5c_teid.ipv4 = 1; pgw_s5c_teid.interface_type = GTP_F_TEID_S5_S8_PGW_GTP_C; @@ -55,6 +55,7 @@ status_t pgw_s5c_build_create_session_response( rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface. len = GTP_F_TEID_IPV4_LEN; + /* PDN Address Allocation */ d_assert(sess->ip_pool, return CORE_ERROR, "No IP Pool"); sess->pdn.paa.pdn_type = GTP_PDN_TYPE_IPV4; sess->pdn.paa.ipv4_addr = sess->ip_pool->ue_addr; @@ -63,12 +64,14 @@ status_t pgw_s5c_build_create_session_response( rsp->pdn_address_allocation.data = &sess->pdn.paa; rsp->pdn_address_allocation.len = PAA_IPV4_LEN; + /* APN Restriction */ rsp->apn_restriction.presence = 1; rsp->apn_restriction.u8 = GTP_APN_NO_RESTRICTION; /* TODO : APN-AMBR * if PCRF changes APN-AMBR, this should be included. */ + /* PCO */ if (req->protocol_configuration_options.presence == 1) { pco_len = pgw_pco_build(pco_buf, &req->protocol_configuration_options); @@ -78,6 +81,7 @@ status_t pgw_s5c_build_create_session_response( rsp->protocol_configuration_options.len = pco_len; } + /* Bearer EBI */ rsp->bearer_contexts_created.presence = 1; rsp->bearer_contexts_created.eps_bearer_id.presence = 1; rsp->bearer_contexts_created.eps_bearer_id.u8 = bearer->ebi; @@ -85,7 +89,7 @@ status_t pgw_s5c_build_create_session_response( /* TODO : Bearer QoS * if PCRF changes Bearer QoS, this should be included. */ - /* Send Data Plane(UL) : PGW-S5U */ + /* Data Plane(UL) : PGW-S5U */ memset(&pgw_s5u_teid, 0, sizeof(gtp_f_teid_t)); pgw_s5u_teid.ipv4 = 1; pgw_s5u_teid.interface_type = GTP_F_TEID_S5_S8_PGW_GTP_U; @@ -175,15 +179,17 @@ status_t pgw_s5c_build_create_bearer_request( req = >p_message.create_bearer_request; memset(>p_message, 0, sizeof(gtp_message_t)); - + + /* Linked EBI */ req->linked_eps_bearer_id.presence = 1; req->linked_eps_bearer_id.u8 = linked_bearer->ebi; + /* Bearer EBI */ req->bearer_contexts.presence = 1; - req->bearer_contexts.eps_bearer_id.presence = 1; req->bearer_contexts.eps_bearer_id.u8 = bearer->ebi; + /* Data Plane(UL) : PGW_S5U */ memset(&pgw_s5u_teid, 0, sizeof(gtp_f_teid_t)); pgw_s5u_teid.ipv4 = 1; pgw_s5u_teid.interface_type = GTP_F_TEID_S5_S8_PGW_GTP_U; @@ -193,6 +199,7 @@ status_t pgw_s5c_build_create_bearer_request( req->bearer_contexts.s5_s8_u_sgw_f_teid.data = &pgw_s5u_teid; req->bearer_contexts.s5_s8_u_sgw_f_teid.len = GTP_F_TEID_IPV4_LEN; + /* Bearer QoS */ memset(&bearer_qos, 0, sizeof(bearer_qos)); bearer_qos.qci = bearer->qos.qci; bearer_qos.priority_level = bearer->qos.arp.priority_level; diff --git a/src/pgw/pgw_s5c_handler.c b/src/pgw/pgw_s5c_handler.c index 4440e69b63..9cf1d87484 100644 --- a/src/pgw/pgw_s5c_handler.c +++ b/src/pgw/pgw_s5c_handler.c @@ -66,12 +66,12 @@ void pgw_s5c_handle_create_session_request( memcpy(sess->imsi, req->imsi.data, sess->imsi_len); core_buffer_to_bcd(sess->imsi, sess->imsi_len, sess->imsi_bcd); - /* Receive Control Plane(DL) : SGW-S5C */ + /* Control Plane(DL) : SGW-S5C */ sgw_s5c_teid = req->sender_f_teid_for_control_plane.data; sess->sgw_s5c_teid = ntohl(sgw_s5c_teid->teid); sess->sgw_s5c_addr = sgw_s5c_teid->ipv4_addr; - /* Receive Control Plane(DL) : SGW-S5U */ + /* Control Plane(DL) : SGW-S5U */ sgw_s5u_teid = req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.data; bearer->sgw_s5u_teid = ntohl(sgw_s5u_teid->teid); bearer->sgw_s5u_addr = sgw_s5u_teid->ipv4_addr;