diff --git a/lib/s1ap/s1ap_decoder.c b/lib/s1ap/s1ap_decoder.c index b2ca0f53f..87690c5c4 100644 --- a/lib/s1ap/s1ap_decoder.c +++ b/lib/s1ap/s1ap_decoder.c @@ -161,7 +161,14 @@ static int s1ap_decode_successfull_outcome(s1ap_message_t *message, s1ap_xer_print_s1ap_initialcontextsetupresponse, s1ap_xer__print2sp, message); break; - + case S1ap_ProcedureCode_id_E_RABSetup: + ret = s1ap_decode_s1ap_e_rabsetupresponseies( + &message->s1ap_E_RABSetupResponseIEs, + &successfullOutcome_p->value); + s1ap_decode_xer_print_message( + s1ap_xer_print_s1ap_e_rabsetupresponse, + s1ap_xer__print2sp, message); + break; case S1ap_ProcedureCode_id_UEContextRelease: ret = s1ap_decode_s1ap_uecontextreleasecomplete_ies( &message->s1ap_UEContextReleaseComplete_IEs, @@ -206,7 +213,6 @@ static int s1ap_decode_unsuccessfull_outcome(s1ap_message_t *message, s1ap_xer_print_s1ap_initialcontextsetupfailure, s1ap_xer__print2sp, message); break; - default: d_error("Unknown procedure ID (%d) for " "unsuccessfull outcome message", diff --git a/lib/s1ap/s1ap_free.c b/lib/s1ap/s1ap_free.c index 92abed83c..a185745a1 100644 --- a/lib/s1ap/s1ap_free.c +++ b/lib/s1ap/s1ap_free.c @@ -113,6 +113,11 @@ static inline int s1ap_free_successfull_outcome(s1ap_message_t *message) &message->s1ap_InitialContextSetupResponseIEs); break; + case S1ap_ProcedureCode_id_E_RABSetup: + s1ap_free_s1ap_e_rabsetupresponseies( + &message->s1ap_E_RABSetupResponseIEs); + break; + case S1ap_ProcedureCode_id_UEContextRelease: s1ap_free_s1ap_uecontextreleasecomplete_ies( &message->s1ap_UEContextReleaseComplete_IEs); diff --git a/src/mme/mme_s11_build.c b/src/mme/mme_s11_build.c index cd5ff1823..233067d33 100644 --- a/src/mme/mme_s11_build.c +++ b/src/mme/mme_s11_build.c @@ -169,11 +169,12 @@ status_t mme_s11_build_modify_bearer_request( memset(>p_message, 0, sizeof(gtp_message_t)); + /* Bearer Context : EBI */ req->bearer_contexts_to_be_modified.presence = 1; req->bearer_contexts_to_be_modified.eps_bearer_id.presence = 1; req->bearer_contexts_to_be_modified.eps_bearer_id.u8 = bearer->ebi; - /* Send Data Plane(DL) : ENB-S1U */ + /* Data Plane(DL) : ENB-S1U */ memset(&enb_s1u_teid, 0, sizeof(gtp_f_teid_t)); enb_s1u_teid.ipv4 = 1; enb_s1u_teid.interface_type = GTP_F_TEID_S1_U_ENODEB_GTP_U; @@ -241,6 +242,51 @@ status_t mme_s11_build_delete_session_request( return CORE_OK; } +status_t mme_s11_build_create_bearer_response( + pkbuf_t **pkbuf, c_uint8_t type, mme_bearer_t *bearer) +{ + status_t rv; + gtp_message_t gtp_message; + gtp_create_bearer_response_t *rsp = >p_message.create_bearer_response; + + gtp_cause_t cause; + gtp_f_teid_t enb_s1u_teid; + + d_assert(bearer, return CORE_ERROR, "Null param"); + + memset(>p_message, 0, sizeof(gtp_message_t)); + + /* Set Cause */ + memset(&cause, 0, sizeof(cause)); + cause.value = GTP_CAUSE_REQUEST_ACCEPTED; + rsp->cause.presence = 1; + rsp->cause.len = sizeof(cause); + rsp->cause.data = &cause; + + /* Bearer Context : EBI */ + rsp->bearer_contexts.presence = 1; + rsp->bearer_contexts.eps_bearer_id.presence = 1; + rsp->bearer_contexts.eps_bearer_id.u8 = bearer->ebi; + + /* Data Plane(DL) : ENB-S1U */ + memset(&enb_s1u_teid, 0, sizeof(gtp_f_teid_t)); + enb_s1u_teid.ipv4 = 1; + enb_s1u_teid.interface_type = GTP_F_TEID_S1_U_ENODEB_GTP_U; + enb_s1u_teid.ipv4_addr = bearer->enb_s1u_addr; + enb_s1u_teid.teid = htonl(bearer->enb_s1u_teid); + rsp->bearer_contexts.s1_u_enodeb_f_teid.presence = 1; + rsp->bearer_contexts.s1_u_enodeb_f_teid.data = &enb_s1u_teid; + rsp->bearer_contexts.s1_u_enodeb_f_teid.len = GTP_F_TEID_IPV4_LEN; + + /* TODO : UE Time Zone */ + + gtp_message.h.type = type; + rv = gtp_build_msg(pkbuf, >p_message); + d_assert(rv == CORE_OK, return CORE_ERROR, "gtp build failed"); + + return CORE_OK; +} + status_t mme_s11_build_release_access_bearers_request( pkbuf_t **pkbuf, c_uint8_t type) { diff --git a/src/mme/mme_s11_build.h b/src/mme/mme_s11_build.h index 636006f83..dd5614f63 100644 --- a/src/mme/mme_s11_build.h +++ b/src/mme/mme_s11_build.h @@ -13,6 +13,8 @@ CORE_DECLARE(status_t) mme_s11_build_modify_bearer_request( pkbuf_t **pkbuf, c_uint8_t type, mme_bearer_t *bearer); CORE_DECLARE(status_t) mme_s11_build_delete_session_request( pkbuf_t **pkbuf, c_uint8_t type, mme_sess_t *sess); +CORE_DECLARE(status_t) mme_s11_build_create_bearer_response( + pkbuf_t **pkbuf, c_uint8_t type, mme_bearer_t *bearer); CORE_DECLARE(status_t) mme_s11_build_release_access_bearers_request( pkbuf_t **pkbuf, c_uint8_t type); CORE_DECLARE(status_t) mme_s11_build_downlink_data_notification_ack( diff --git a/src/mme/s1ap_handler.c b/src/mme/s1ap_handler.c index 63eb31515..675c6503f 100644 --- a/src/mme/s1ap_handler.c +++ b/src/mme/s1ap_handler.c @@ -300,9 +300,9 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, s1ap_message_t *message) d_assert(enb->s1ap_sock, enb_ue_remove(enb_ue); return,); d_trace(3, "[S1AP] InitialUEMessage : " "UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n", - enb_ue->enb_ue_s1ap_id, - INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf), - enb->enb_id); + enb_ue->enb_ue_s1ap_id, + INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf), + enb->enb_id); event_s1ap_to_nas(enb_ue, &ies->nas_pdu); } @@ -319,13 +319,13 @@ void s1ap_handle_uplink_nas_transport( d_assert(ies, return, "Null param"); enb_ue = enb_ue_find_by_enb_ue_s1ap_id(enb, ies->eNB_UE_S1AP_ID); - d_assert(enb_ue, return, "Null param"); + d_assert(enb_ue, return, "No UE Context[%d]", ies->eNB_UE_S1AP_ID); d_trace(3, "[S1AP] uplinkNASTransport : " "UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n", - enb_ue->enb_ue_s1ap_id, - INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf), - enb->enb_id); + enb_ue->enb_ue_s1ap_id, + INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf), + enb->enb_id); event_s1ap_to_nas(enb_ue, &ies->nas_pdu); } @@ -377,8 +377,8 @@ void s1ap_handle_ue_capability_info_indication( d_trace(3, "[S1AP] UE Capability Info Indication : " "UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n", enb_ue->enb_ue_s1ap_id, - INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf), - enb->enb_id); + INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf), + enb->enb_id); } void s1ap_handle_initial_context_setup_response( @@ -399,12 +399,11 @@ void s1ap_handle_initial_context_setup_response( d_trace(3, "[S1AP] Initial Context Setup Response : " "UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n", enb_ue->enb_ue_s1ap_id, - INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf), - enb->enb_id); + INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf), + enb->enb_id); - for (i = 0; - i < ies->e_RABSetupListCtxtSURes.s1ap_E_RABSetupItemCtxtSURes.count; - i++) + for (i = 0; i < ies->e_RABSetupListCtxtSURes. + s1ap_E_RABSetupItemCtxtSURes.count; i++) { status_t rv; gtp_header_t h; @@ -445,6 +444,72 @@ void s1ap_handle_initial_context_setup_response( } } +void s1ap_handle_e_rab_setup_response( + mme_enb_t *enb, s1ap_message_t *message) +{ + char buf[INET_ADDRSTRLEN]; + int i; + + enb_ue_t *enb_ue = NULL; + S1ap_E_RABSetupResponseIEs_t *ies = NULL; + + d_assert(enb, return, "Null param"); + d_assert(message, return, "Null param"); + + ies = &message->s1ap_E_RABSetupResponseIEs; + d_assert(ies, return, "Null param"); + + enb_ue = enb_ue_find_by_enb_ue_s1ap_id(enb, ies->eNB_UE_S1AP_ID); + d_assert(enb_ue, return, "No UE Context[%d]", ies->eNB_UE_S1AP_ID); + + d_trace(3, "[S1AP] E-RAB Setup Response : " + "UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n", + enb_ue->enb_ue_s1ap_id, + INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf), + enb->enb_id); + + for (i = 0; i < ies->e_RABSetupListBearerSURes. + s1ap_E_RABSetupItemBearerSURes.count; i++) + { + status_t rv; + gtp_header_t h; + gtp_xact_t *xact = NULL; + pkbuf_t *pkbuf = NULL; + + mme_bearer_t *bearer = NULL; + mme_ue_t *mme_ue = enb_ue->mme_ue; + S1ap_E_RABSetupItemBearerSURes_t *e_rab = NULL; + + e_rab = (S1ap_E_RABSetupItemBearerSURes_t *)ies-> + e_RABSetupListBearerSURes.s1ap_E_RABSetupItemBearerSURes.array[i]; + d_assert(e_rab, return, "Null param"); + + bearer = mme_bearer_find_by_ue_ebi(mme_ue, e_rab->e_RAB_ID); + d_assert(bearer, return, "Null param"); + xact = bearer->xact; + d_assert(xact, return, "Null param"); + + memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf, + sizeof(bearer->enb_s1u_teid)); + bearer->enb_s1u_teid = ntohl(bearer->enb_s1u_teid); + memcpy(&bearer->enb_s1u_addr, e_rab->transportLayerAddress.buf, + sizeof(bearer->enb_s1u_addr)); + + memset(&h, 0, sizeof(gtp_header_t)); + h.type = GTP_CREATE_BEARER_RESPONSE_TYPE; + h.teid = mme_ue->sgw_s11_teid; + + rv = mme_s11_build_create_bearer_response(&pkbuf, h.type, bearer); + d_assert(rv == CORE_OK, return, "S11 build error"); + + rv = gtp_xact_update_tx(xact, &h, pkbuf); + d_assert(xact, return, "Null param"); + + rv = gtp_xact_commit(xact); + d_assert(rv == CORE_OK, return, "xact_commit error"); + } +} + void s1ap_handle_ue_context_release_request( mme_enb_t *enb, s1ap_message_t *message) { @@ -570,8 +635,8 @@ void s1ap_handle_ue_context_release_complete( d_trace(3, "[S1AP] UE Context Release Complete : " "UE[mME-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n", enb_ue->mme_ue_s1ap_id, - INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf), - enb->enb_id); + INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf), + enb->enb_id); enb_ue_remove(enb_ue); } diff --git a/src/mme/s1ap_handler.h b/src/mme/s1ap_handler.h index a97ee25cf..a77990f5b 100644 --- a/src/mme/s1ap_handler.h +++ b/src/mme/s1ap_handler.h @@ -18,6 +18,8 @@ CORE_DECLARE(void) s1ap_handle_ue_capability_info_indication( mme_enb_t *enb, s1ap_message_t *message); CORE_DECLARE(void) s1ap_handle_initial_context_setup_response( mme_enb_t *enb, s1ap_message_t *message); +CORE_DECLARE(void) s1ap_handle_e_rab_setup_response( + mme_enb_t *enb, s1ap_message_t *message); CORE_DECLARE(void) s1ap_handle_ue_context_release_request( mme_enb_t *enb, s1ap_message_t *message); diff --git a/src/mme/s1ap_sm.c b/src/mme/s1ap_sm.c index 2ccf615df..7defff457 100644 --- a/src/mme/s1ap_sm.c +++ b/src/mme/s1ap_sm.c @@ -106,6 +106,11 @@ void s1ap_state_operational(fsm_t *s, event_t *e) enb, message); break; } + case S1ap_ProcedureCode_id_E_RABSetup : + { + s1ap_handle_e_rab_setup_response(enb, message); + break; + } case S1ap_ProcedureCode_id_UEContextRelease : { s1ap_handle_ue_context_release_complete( diff --git a/test/testpacket.c b/test/testpacket.c index e6dd9ca0d..46a303784 100644 --- a/test/testpacket.c +++ b/test/testpacket.c @@ -750,3 +750,89 @@ status_t tests1ap_build_service_request(pkbuf_t **pkbuf, int i) return CORE_OK; } +status_t tests1ap_build_e_rab_setup_response(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "2005002600000300 004005c00200003c 0008400300010000 1c400f000027400a" + "0c1f0a012da50100 b410", + "", + "", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 42, + 0, + 0, + + 0, + 0, + 0, + + 59, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + +status_t tests1ap_build_activate_dedicated_bearer_accept( + pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000d403700000500" + "000005c00200003c 0008000300010000 1a000a0927c035da 96036200c6006440" + "080000f1109d67aa 50004340060000f1 102b67", + "", + "", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 59, + 0, + 0, + + 0, + 0, + 0, + + 59, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = pkbuf_alloc(0, MAX_SDU_LEN); + if (!(*pkbuf)) return CORE_ERROR; + + (*pkbuf)->len = len[i]; + memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf), + (*pkbuf)->len); + + return CORE_OK; +} + diff --git a/test/testpacket.h b/test/testpacket.h index f2a2570fc..215481979 100644 --- a/test/testpacket.h +++ b/test/testpacket.h @@ -35,6 +35,10 @@ CORE_DECLARE(status_t) tests1ap_build_ue_context_release_complete( pkbuf_t **pkbuf, int i); CORE_DECLARE(status_t) tests1ap_build_service_request( pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_activate_dedicated_bearer_accept( + pkbuf_t **pkbuf, int i); +CORE_DECLARE(status_t) tests1ap_build_e_rab_setup_response( + pkbuf_t **pkbuf, int i); #ifdef __cplusplus } diff --git a/test/volte_test.c b/test/volte_test.c index e53948b6d..7fb0739ea 100644 --- a/test/volte_test.c +++ b/test/volte_test.c @@ -224,6 +224,20 @@ static void volte_test1(abts_case *tc, void *data) ABTS_INT_NEQUAL(tc, 0, rc); pkbuf_free(recvbuf); + /* Send E-RAB Setup */ + rv = tests1ap_build_e_rab_setup_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + core_sleep(time_from_msec(300)); + + /* Send Activate dedicated EPS bearer context accept */ + rv = tests1ap_build_activate_dedicated_bearer_accept(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = tests1ap_enb_send(sock, sendbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + /********** Remove Subscriber in Database */ doc = BCON_NEW("imsi", BCON_UTF8("001010123456819")); ABTS_PTR_NOTNULL(tc, doc);