From fffd654391076339af8bd129fcfe62942c1fe2d0 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Wed, 17 Jan 2018 15:41:45 +0900 Subject: [PATCH] NAS modify bearer request/accept is done --- lib/s1ap/s1ap_decoder.c | 9 ++++ lib/s1ap/s1ap_encoder.c | 47 ++++++++++++++++++ lib/s1ap/s1ap_free.c | 10 ++++ src/mme/esm_build.c | 58 +++++++++++++++++++++- src/mme/esm_build.h | 2 + src/mme/esm_sm.c | 12 +++++ src/mme/mme_s11_handler.c | 100 ++++++++++++++++++++++++++++++++++++++ src/mme/mme_s11_handler.h | 2 + src/mme/mme_sm.c | 4 ++ src/mme/nas_path.c | 35 +++++++++++++ src/mme/nas_path.h | 2 + src/mme/s1ap_build.c | 89 +++++++++++++++++++++++++++++++++ src/mme/s1ap_build.h | 2 + src/mme/s1ap_sm.c | 4 ++ src/sgw/sgw_s5c_handler.c | 45 +++++++++++++++++ src/sgw/sgw_s5c_handler.h | 2 + src/sgw/sgw_sm.c | 4 ++ test/rx/testpacket.c | 93 +++++++++++++++++++++++++++++++++++ test/rx/testpacket.h | 4 ++ test/rx/volte_test.c | 23 ++++++++- 20 files changed, 544 insertions(+), 3 deletions(-) diff --git a/lib/s1ap/s1ap_decoder.c b/lib/s1ap/s1ap_decoder.c index 9f0e2463d4..936acd905d 100644 --- a/lib/s1ap/s1ap_decoder.c +++ b/lib/s1ap/s1ap_decoder.c @@ -218,6 +218,15 @@ static int s1ap_decode_successfull_outcome(s1ap_message_t *message, s1ap_xer__print2sp, message); break; + case S1ap_ProcedureCode_id_E_RABModify: + ret = s1ap_decode_s1ap_e_rabmodifyresponseies( + &message->s1ap_E_RABModifyResponseIEs, + &successfullOutcome_p->value); + s1ap_decode_xer_print_message( + s1ap_xer_print_s1ap_e_rabmodifyresponse, + s1ap_xer__print2sp, message); + break; + case S1ap_ProcedureCode_id_E_RABRelease: ret = s1ap_decode_s1ap_e_rabreleaseresponseies( &message->s1ap_E_RABReleaseResponseIEs, diff --git a/lib/s1ap/s1ap_encoder.c b/lib/s1ap/s1ap_encoder.c index d87ce50687..1e792e9baa 100644 --- a/lib/s1ap/s1ap_encoder.c +++ b/lib/s1ap/s1ap_encoder.c @@ -29,6 +29,8 @@ static inline int s1ap_encode_e_rab_setup_request( s1ap_message_t *message_p, pkbuf_t *pkbuf); static inline int s1ap_encode_e_rab_setup_response( s1ap_message_t *message_p, pkbuf_t *pkbuf); +static inline int s1ap_encode_e_rab_modify_request( + s1ap_message_t *message_p, pkbuf_t *pkbuf); static inline int s1ap_encode_e_rab_release_command( s1ap_message_t *message_p, pkbuf_t *pkbuf); static inline int s1ap_encode_ue_context_release_command( @@ -134,6 +136,13 @@ static inline int s1ap_encode_initiating_message( ret = s1ap_encode_e_rab_setup_request(message_p, pkbuf); break; + case S1ap_ProcedureCode_id_E_RABModify: + s1ap_encode_xer_print_message( + s1ap_xer_print_s1ap_e_rabmodifyrequest, + s1ap_xer__print2sp, message_p); + ret = s1ap_encode_e_rab_modify_request(message_p, pkbuf); + break; + case S1ap_ProcedureCode_id_E_RABRelease: s1ap_encode_xer_print_message( s1ap_xer_print_s1ap_e_rabreleasecommand, @@ -587,6 +596,44 @@ static inline int s1ap_encode_e_rab_setup_response( return enc_ret.encoded; } +static inline int s1ap_encode_e_rab_modify_request( + s1ap_message_t *message_p, pkbuf_t *pkbuf) +{ + asn_enc_rval_t enc_ret = {0}; + + S1AP_PDU_t pdu; + S1ap_E_RABModifyRequest_t req; + asn_TYPE_descriptor_t *td = &asn_DEF_S1ap_E_RABModifyRequest; + + memset(&req, 0, sizeof(S1ap_E_RABModifyRequest_t)); + if (s1ap_encode_s1ap_e_rabmodifyrequesties( + &req, &message_p->s1ap_E_RABModifyRequestIEs) < 0) + { + d_error("Encoding of %s failed", td->name); + return -1; + } + + memset(&pdu, 0, sizeof (S1AP_PDU_t)); + pdu.present = S1AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage.procedureCode = message_p->procedureCode; + pdu.choice.initiatingMessage.criticality = S1ap_Criticality_reject; + ANY_fromType_aper(&pdu.choice.initiatingMessage.value, td, &req); + + enc_ret = aper_encode_to_buffer(&asn_DEF_S1AP_PDU, + &pdu, pkbuf->payload, MAX_SDU_LEN); + + ASN_STRUCT_FREE_CONTENTS_ONLY(*td, &req); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_S1AP_PDU, &pdu); + + if (enc_ret.encoded < 0) + { + d_error("Encoding of %s failed", td->name); + } + + return enc_ret.encoded; +} + + static inline int s1ap_encode_e_rab_release_command( s1ap_message_t *message_p, pkbuf_t *pkbuf) { diff --git a/lib/s1ap/s1ap_free.c b/lib/s1ap/s1ap_free.c index 639849d706..82a295ecb7 100644 --- a/lib/s1ap/s1ap_free.c +++ b/lib/s1ap/s1ap_free.c @@ -70,6 +70,11 @@ static inline int s1ap_free_initiating_message(s1ap_message_t *message) &message->s1ap_E_RABSetupRequestIEs); break; + case S1ap_ProcedureCode_id_E_RABModify: + s1ap_free_s1ap_e_rabmodifyrequesties( + &message->s1ap_E_RABModifyRequestIEs); + break; + case S1ap_ProcedureCode_id_E_RABRelease: s1ap_free_s1ap_e_rabreleasecommandies( &message->s1ap_E_RABReleaseCommandIEs); @@ -163,6 +168,11 @@ static inline int s1ap_free_successfull_outcome(s1ap_message_t *message) &message->s1ap_E_RABSetupResponseIEs); break; + case S1ap_ProcedureCode_id_E_RABModify: + s1ap_free_s1ap_e_rabmodifyresponseies( + &message->s1ap_E_RABModifyResponseIEs); + break; + case S1ap_ProcedureCode_id_E_RABRelease: s1ap_free_s1ap_e_rabmodifyresponseies( &message->s1ap_E_RABModifyResponseIEs); diff --git a/src/mme/esm_build.c b/src/mme/esm_build.c index b620dc747a..aac6c2a8a8 100644 --- a/src/mme/esm_build.c +++ b/src/mme/esm_build.c @@ -234,6 +234,61 @@ status_t esm_build_activate_dedicated_bearer_context_request( return CORE_OK; } +status_t esm_build_modify_bearer_context_request( + pkbuf_t **pkbuf, mme_bearer_t *bearer, int qos_presence, int tft_presence) +{ + mme_ue_t *mme_ue = NULL; + mme_sess_t *sess = NULL; + + nas_message_t message; + nas_modify_eps_bearer_context_request_t + *modify_eps_bearer_context_request = + &message.esm.modify_eps_bearer_context_request; + nas_eps_quality_of_service_t *new_eps_qos = + &modify_eps_bearer_context_request->new_eps_qos; + nas_traffic_flow_template_t *tft = + &modify_eps_bearer_context_request->tft; + + d_assert(bearer, return CORE_ERROR, "Null param"); + sess = bearer->sess; + d_assert(sess, return CORE_ERROR, "Null param"); + mme_ue = bearer->mme_ue; + d_assert(mme_ue, return CORE_ERROR, "Null param"); + + memset(&message, 0, sizeof(message)); + message.h.security_header_type = + NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED; + message.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; + 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.message_type = NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST; + + if (qos_presence == 1) + { + modify_eps_bearer_context_request->presencemask |= + NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_EPS_QOS_PRESENT; + eps_qos_build(new_eps_qos, bearer->qos.qci, + bearer->qos.mbr.downlink, bearer->qos.mbr.uplink, + bearer->qos.gbr.downlink, bearer->qos.gbr.uplink); + } + + if (tft_presence == 1) + { + modify_eps_bearer_context_request->presencemask |= + NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_TFT_PRESENT; + tft->length = bearer->tft.len; + d_assert(tft->length, return CORE_ERROR, "No TFT Len"); + d_assert(bearer->tft.data, return CORE_ERROR, "Null param"); + memcpy(tft->buffer, bearer->tft.data, tft->length); + } + + d_assert(nas_security_encode(pkbuf, mme_ue, &message) == CORE_OK && + *pkbuf, return CORE_ERROR,); + + return CORE_OK; +} + status_t esm_build_deactivate_bearer_context_request( pkbuf_t **pkbuf, mme_bearer_t *bearer, nas_esm_cause_t esm_cause) { @@ -258,8 +313,7 @@ status_t esm_build_deactivate_bearer_context_request( 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.message_type = - NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST; + message.esm.h.message_type = NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST; deactivate_eps_bearer_context_request->esm_cause = esm_cause; diff --git a/src/mme/esm_build.h b/src/mme/esm_build.h index 215de4d26b..17cd296571 100644 --- a/src/mme/esm_build.h +++ b/src/mme/esm_build.h @@ -15,6 +15,8 @@ CORE_DECLARE(status_t) esm_build_activate_default_bearer_context_request( pkbuf_t **pkbuf, mme_sess_t *sess); CORE_DECLARE(status_t) esm_build_activate_dedicated_bearer_context_request( pkbuf_t **pkbuf, mme_bearer_t *bearer); +CORE_DECLARE(status_t) esm_build_modify_bearer_context_request( + pkbuf_t **pkbuf, mme_bearer_t *bearer, int qos_presence, int tft_presence); CORE_DECLARE(status_t) esm_build_deactivate_bearer_context_request( pkbuf_t **pkbuf, mme_bearer_t *bearer, nas_esm_cause_t esm_cause); diff --git a/src/mme/esm_sm.c b/src/mme/esm_sm.c index 281f4e816e..f85168ef30 100644 --- a/src/mme/esm_sm.c +++ b/src/mme/esm_sm.c @@ -212,6 +212,18 @@ void esm_state_active(fsm_t *s, event_t *e) FSM_TRAN(s, esm_state_pdn_will_disconnect); break; } + case NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT: + { + d_trace(3, "[NAS] Modify EPS bearer context accept : " + "UE[%s] --> ESM[EBI:%d] in ACTIVE state\n", + mme_ue->imsi_bcd, bearer->ebi); +#if 0 + rv = mme_gtp_send_update_bearer_response(bearer); + d_assert(rv == CORE_OK, return, + "mme_gtp_send_delete_session_request error"); +#endif + break; + } case NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT: { d_trace(3, "[NAS] Deactivate EPS bearer context accept : " diff --git a/src/mme/mme_s11_handler.c b/src/mme/mme_s11_handler.c index bdaec5d678..23e173607c 100644 --- a/src/mme/mme_s11_handler.c +++ b/src/mme/mme_s11_handler.c @@ -339,6 +339,106 @@ void mme_s11_handle_create_bearer_request( } } +void mme_s11_handle_update_bearer_request( + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_update_bearer_request_t *req) +{ + status_t rv; + mme_bearer_t *bearer = NULL; + gtp_bearer_qos_t bearer_qos; + + d_assert(xact, return, "Null param"); + d_assert(mme_ue, return, "Null param"); + d_assert(req, return, "Null param"); + + d_trace(3, "[MME] Update Bearer Request : MME[%d] <-- SGW[%d]\n", + mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + + 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; + } + + bearer = mme_bearer_find_by_ue_ebi(mme_ue, + req->bearer_contexts.eps_bearer_id.u8); + d_assert(bearer, return, + "No Bearer Context(EBI:%d)", req->bearer_contexts.eps_bearer_id.u8); + + /* Save Transaction. will be handled after EMM-attached */ + bearer->xact = xact; + + if (/* Check if Activate Default/Dedicated Bearer Accept is received */ + FSM_CHECK(&bearer->sm, esm_state_active) && + /* Check if Initial Context Setup Response or + * E-RAB Setup Response is received */ + MME_HAVE_ENB_S1U_PATH(bearer)) + { + if (req->bearer_contexts.bearer_level_qos.presence == 1) + { + /* 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; + bearer->qos.mbr.downlink = bearer_qos.dl_mbr; + bearer->qos.mbr.uplink = bearer_qos.ul_mbr; + bearer->qos.gbr.downlink = bearer_qos.dl_gbr; + bearer->qos.gbr.uplink = bearer_qos.ul_gbr; + } + + if (req->bearer_contexts.tft.presence == 1) + { + /* Save Bearer TFT */ + TLV_STORE_DATA(&bearer->tft, &req->bearer_contexts.tft); + } + + if (req->bearer_contexts.bearer_level_qos.presence == 1 || + req->bearer_contexts.tft.presence == 1) + { + rv = nas_send_modify_bearer_context_request( + bearer, + req->bearer_contexts.bearer_level_qos.presence, + req->bearer_contexts.tft.presence); + d_assert(rv == CORE_OK, return, + "nas_send_deactivate_bearer_context_request failed"); + } + else + { + d_warn("ignore Update Bearer Request : " + "Both QoS and TFT is NULL"); +#if 0 + rv = mme_gtp_send_update_bearer_response(bearer); + d_assert(rv == CORE_OK, return, + "mme_gtp_send_delete_session_request error"); +#endif + } + } + else + { + if (!FSM_CHECK(&bearer->sm, esm_state_active)) + { + d_assert(0,, "Invalid Bearer State"); + } + else if (!MME_HAVE_ENB_S1U_PATH(bearer)) + { + d_assert(0,, "No ENB S1U PATH"); + } + else + d_assert(0,,); + } + +} + void mme_s11_handle_delete_bearer_request( gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_delete_bearer_request_t *req) { diff --git a/src/mme/mme_s11_handler.h b/src/mme/mme_s11_handler.h index 781b892f78..86049a7627 100644 --- a/src/mme/mme_s11_handler.h +++ b/src/mme/mme_s11_handler.h @@ -17,6 +17,8 @@ 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_update_bearer_request( + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_update_bearer_request_t *rsp); CORE_DECLARE(void) mme_s11_handle_delete_bearer_request( gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_delete_bearer_request_t *rsp); diff --git a/src/mme/mme_sm.c b/src/mme/mme_sm.c index c5fcb9aed6..6ab052220d 100644 --- a/src/mme/mme_sm.c +++ b/src/mme/mme_sm.c @@ -431,6 +431,10 @@ void mme_state_operational(fsm_t *s, event_t *e) mme_s11_handle_create_bearer_request( xact, mme_ue, &message.create_bearer_request); break; + case GTP_UPDATE_BEARER_REQUEST_TYPE: + mme_s11_handle_update_bearer_request( + xact, mme_ue, &message.update_bearer_request); + break; case GTP_DELETE_BEARER_REQUEST_TYPE: mme_s11_handle_delete_bearer_request( xact, mme_ue, &message.delete_bearer_request); diff --git a/src/mme/nas_path.c b/src/mme/nas_path.c index 293bb1f8ff..576bfb8fea 100644 --- a/src/mme/nas_path.c +++ b/src/mme/nas_path.c @@ -305,6 +305,41 @@ status_t nas_send_activate_dedicated_bearer_context_request( return CORE_OK; } +status_t nas_send_modify_bearer_context_request( + mme_bearer_t *bearer, int qos_presence, int tft_presence) +{ + status_t rv; + pkbuf_t *esmbuf = NULL, *s1apbuf = NULL; + mme_ue_t *mme_ue = NULL; + + d_assert(bearer, return CORE_ERROR, "Null param"); + mme_ue = bearer->mme_ue; + d_assert(mme_ue, return CORE_ERROR, "Null param"); + + rv = esm_build_modify_bearer_context_request( + &esmbuf, bearer, qos_presence, tft_presence); + d_assert(rv == CORE_OK && esmbuf, return CORE_ERROR, "esm build error"); + + d_trace(3, "[NAS] Modify bearer context request : EMM <-- ESM\n"); + + if (qos_presence == 1) + { + rv = s1ap_build_e_rab_modify_request(&s1apbuf, bearer, esmbuf); + d_assert(rv == CORE_OK && s1apbuf, + pkbuf_free(esmbuf); return CORE_ERROR, "s1ap build error"); + + rv = nas_send_to_enb(mme_ue, s1apbuf); + d_assert(rv == CORE_OK, return CORE_ERROR, "nas send error"); + } + else + { + rv = nas_send_to_downlink_nas_transport(mme_ue, esmbuf); + d_assert(rv == CORE_OK, return CORE_ERROR, "nas send failed"); + } + + return CORE_OK; +} + status_t nas_send_deactivate_bearer_context_request(mme_bearer_t *bearer) { status_t rv; diff --git a/src/mme/nas_path.h b/src/mme/nas_path.h index bc66eeba2f..5b0bc864c7 100644 --- a/src/mme/nas_path.h +++ b/src/mme/nas_path.h @@ -33,6 +33,8 @@ CORE_DECLARE(status_t) nas_send_activate_default_bearer_context_request( mme_bearer_t *bearer); CORE_DECLARE(status_t) nas_send_activate_dedicated_bearer_context_request( mme_bearer_t *bearer); +CORE_DECLARE(status_t) nas_send_modify_bearer_context_request( + mme_bearer_t *bearer, int qos_presence, int tft_presence); CORE_DECLARE(status_t) nas_send_deactivate_bearer_context_request( mme_bearer_t *bearer); diff --git a/src/mme/s1ap_build.c b/src/mme/s1ap_build.c index 3f48f465d5..ecd1e6555d 100644 --- a/src/mme/s1ap_build.c +++ b/src/mme/s1ap_build.c @@ -405,6 +405,95 @@ status_t s1ap_build_e_rab_setup_request( return CORE_OK; } +status_t s1ap_build_e_rab_modify_request( + pkbuf_t **s1apbuf, mme_bearer_t *bearer, pkbuf_t *esmbuf) +{ + char buf[CORE_ADDRSTRLEN]; + + int encoded; + s1ap_message_t message; + S1ap_E_RABModifyRequestIEs_t *ies = &message.s1ap_E_RABModifyRequestIEs; + S1ap_E_RABToBeModifiedItemBearerModReq_t *e_rab = NULL; + struct S1ap_GBR_QosInformation *gbrQosInformation = NULL; /* OPTIONAL */ + S1ap_NAS_PDU_t *nasPdu = NULL; + mme_ue_t *mme_ue = NULL; + enb_ue_t *enb_ue = NULL; + + d_assert(esmbuf, return CORE_ERROR, "Null param"); + d_assert(bearer, return CORE_ERROR, "Null param"); + + mme_ue = bearer->mme_ue; + d_assert(mme_ue, return CORE_ERROR, "Null param"); + enb_ue = mme_ue->enb_ue; + d_assert(enb_ue, return CORE_ERROR, "Null param"); + + memset(&message, 0, sizeof(s1ap_message_t)); + + ies->mme_ue_s1ap_id = enb_ue->mme_ue_s1ap_id; + ies->eNB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id; + + e_rab = (S1ap_E_RABToBeModifiedItemBearerModReq_t *) + core_calloc(1, sizeof(S1ap_E_RABToBeModifiedItemBearerModReq_t)); + e_rab->e_RAB_ID = bearer->ebi; + e_rab->e_RABLevelQoSParameters.qCI = bearer->qos.qci; + + e_rab->e_RABLevelQoSParameters.allocationRetentionPriority. + priorityLevel = bearer->qos.arp.priority_level; + e_rab->e_RABLevelQoSParameters.allocationRetentionPriority. + pre_emptionCapability = !(bearer->qos.arp.pre_emption_capability); + e_rab->e_RABLevelQoSParameters.allocationRetentionPriority. + pre_emptionVulnerability = !(bearer->qos.arp.pre_emption_vulnerability); + + if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink || + bearer->qos.gbr.downlink || bearer->qos.gbr.uplink) + { + if (bearer->qos.mbr.downlink == 0) + bearer->qos.mbr.downlink = MAX_BIT_RATE; + if (bearer->qos.mbr.uplink == 0) + bearer->qos.mbr.uplink = MAX_BIT_RATE; + if (bearer->qos.gbr.downlink == 0) + bearer->qos.gbr.downlink = MAX_BIT_RATE; + if (bearer->qos.gbr.uplink == 0) + bearer->qos.gbr.uplink = MAX_BIT_RATE; + + gbrQosInformation = + core_calloc(1, sizeof(struct S1ap_GBR_QosInformation)); + asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateDL, + bearer->qos.mbr.downlink); + asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateUL, + bearer->qos.mbr.uplink); + asn_uint642INTEGER(&gbrQosInformation->e_RAB_GuaranteedBitrateDL, + bearer->qos.gbr.downlink); + asn_uint642INTEGER(&gbrQosInformation->e_RAB_GuaranteedBitrateUL, + bearer->qos.gbr.uplink); + e_rab->e_RABLevelQoSParameters.gbrQosInformation = gbrQosInformation; + } + + nasPdu = &e_rab->nAS_PDU; + nasPdu->size = esmbuf->len; + nasPdu->buf = core_calloc(nasPdu->size, sizeof(c_uint8_t)); + memcpy(nasPdu->buf, esmbuf->payload, nasPdu->size); + + ASN_SEQUENCE_ADD(&ies->e_RABToBeModifiedListBearerModReq, e_rab); + + message.procedureCode = S1ap_ProcedureCode_id_E_RABModify; + message.direction = S1AP_PDU_PR_initiatingMessage; + + encoded = s1ap_encode_pdu(s1apbuf, &message); + s1ap_free_pdu(&message); + + d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,); + + d_trace(3, "[S1AP] E-RAB Modify Request : " + "UE[eNB-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n", + enb_ue->enb_ue_s1ap_id, + CORE_ADDR(enb_ue->enb->addr, buf), enb_ue->enb->enb_id); + + pkbuf_free(esmbuf); + + return CORE_OK; +} + status_t s1ap_build_e_rab_release_command(pkbuf_t **s1apbuf, mme_bearer_t *bearer, pkbuf_t *esmbuf, S1ap_Cause_t *cause) { diff --git a/src/mme/s1ap_build.h b/src/mme/s1ap_build.h index 540dfff2fd..24d69f1469 100644 --- a/src/mme/s1ap_build.h +++ b/src/mme/s1ap_build.h @@ -17,6 +17,8 @@ CORE_DECLARE(status_t) s1ap_build_initial_context_setup_request( pkbuf_t **s1apbuf, mme_ue_t *mme_ue, pkbuf_t *emmbuf); CORE_DECLARE(status_t) s1ap_build_e_rab_setup_request( pkbuf_t **s1apbuf, mme_bearer_t *bearer, pkbuf_t *esmbuf); +CORE_DECLARE(status_t) s1ap_build_e_rab_modify_request( + pkbuf_t **s1apbuf, mme_bearer_t *bearer, pkbuf_t *esmbuf); CORE_DECLARE(status_t) s1ap_build_e_rab_release_command(pkbuf_t **s1apbuf, mme_bearer_t *bearer, pkbuf_t *esmbuf, S1ap_Cause_t *cause); CORE_DECLARE(status_t) s1ap_build_ue_context_release_commmand( diff --git a/src/mme/s1ap_sm.c b/src/mme/s1ap_sm.c index 17fb46a51d..b57e405ccb 100644 --- a/src/mme/s1ap_sm.c +++ b/src/mme/s1ap_sm.c @@ -137,6 +137,10 @@ void s1ap_state_operational(fsm_t *s, event_t *e) s1ap_handle_e_rab_setup_response(enb, message); break; } + case S1ap_ProcedureCode_id_E_RABModify : + { + break; + } case S1ap_ProcedureCode_id_E_RABRelease : { break; diff --git a/src/sgw/sgw_s5c_handler.c b/src/sgw/sgw_s5c_handler.c index 20e034b798..c9d5de48bc 100644 --- a/src/sgw/sgw_s5c_handler.c +++ b/src/sgw/sgw_s5c_handler.c @@ -313,6 +313,51 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact, s5u_tunnel->local_teid, s5u_tunnel->remote_teid); } +void sgw_s5c_handle_update_bearer_request(gtp_xact_t *s5c_xact, + sgw_sess_t *sess, gtp_message_t *gtp_message) +{ + status_t rv; + gtp_xact_t *s11_xact = NULL; + gtp_update_bearer_request_t *req = NULL; + pkbuf_t *pkbuf = NULL; + sgw_ue_t *sgw_ue = NULL; + + d_assert(sess, return, "Null param"); + sgw_ue = sess->sgw_ue; + d_assert(sgw_ue, return, "Null param"); + d_assert(s5c_xact, return, "Null param"); + d_assert(gtp_message, return, "Null param"); + + req = >p_message->update_bearer_request; + + 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; + } + + gtp_message->h.type = GTP_UPDATE_BEARER_REQUEST_TYPE; + gtp_message->h.teid = sgw_ue->mme_s11_teid; + + rv = gtp_build_msg(&pkbuf, gtp_message); + d_assert(rv == CORE_OK, return, "gtp build failed"); + + s11_xact = gtp_xact_local_create(sgw_ue->gnode, >p_message->h, pkbuf); + d_assert(s11_xact, return, "Null param"); + + gtp_xact_associate(s5c_xact, s11_xact); + + rv = gtp_xact_commit(s11_xact); + d_assert(rv == CORE_OK, return, "xact_commit error"); + + d_trace(3, "[SGW] Update Bearer Request : SGW <-- PGW\n"); +} + void sgw_s5c_handle_delete_bearer_request(gtp_xact_t *s5c_xact, sgw_sess_t *sess, gtp_message_t *gtp_message) { diff --git a/src/sgw/sgw_s5c_handler.h b/src/sgw/sgw_s5c_handler.h index d243ac2f8c..27af94ecdb 100644 --- a/src/sgw/sgw_s5c_handler.h +++ b/src/sgw/sgw_s5c_handler.h @@ -15,6 +15,8 @@ CORE_DECLARE(void) sgw_s5c_handle_delete_session_response(gtp_xact_t *s5c_xact, sgw_sess_t *sess, gtp_message_t *gtp_message); CORE_DECLARE(void) sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact, sgw_sess_t *sess, gtp_message_t *gtp_message); +CORE_DECLARE(void) sgw_s5c_handle_update_bearer_request(gtp_xact_t *s5c_xact, + sgw_sess_t *sess, gtp_message_t *gtp_message); CORE_DECLARE(void) sgw_s5c_handle_delete_bearer_request(gtp_xact_t *s5c_xact, sgw_sess_t *sess, gtp_message_t *gtp_message); diff --git a/src/sgw/sgw_sm.c b/src/sgw/sgw_sm.c index a6055b88d2..585e0c1ff4 100644 --- a/src/sgw/sgw_sm.c +++ b/src/sgw/sgw_sm.c @@ -171,6 +171,10 @@ void sgw_state_operational(fsm_t *s, event_t *e) sgw_s5c_handle_create_bearer_request(xact, sess, &message); break; + case GTP_UPDATE_BEARER_REQUEST_TYPE: + sgw_s5c_handle_update_bearer_request(xact, sess, + &message); + break; case GTP_DELETE_BEARER_REQUEST_TYPE: sgw_s5c_handle_delete_bearer_request(xact, sess, &message); diff --git a/test/rx/testpacket.c b/test/rx/testpacket.c index 07462e5206..fe87182120 100644 --- a/test/rx/testpacket.c +++ b/test/rx/testpacket.c @@ -1104,6 +1104,48 @@ status_t tests1ap_build_e_rab_setup_response( return CORE_OK; } +status_t tests1ap_build_e_rab_modify_response(pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "2006" + "001b000003000040 0480000001000840 020001001f400600 002500010e", + "", + "", + + "", + "", + "", + + "", + "", + "", + + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 31, + 0, + 0, + + 0, + 0, + 0, + + 0, + 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_e_rab_release_response(pkbuf_t **pkbuf, int i) { char *payload[TESTS1AP_MAX_MESSAGE] = { @@ -1247,6 +1289,57 @@ status_t tests1ap_build_activate_dedicated_bearer_accept( return CORE_OK; } +status_t tests1ap_build_modify_bearer_accept( + pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "000d" + "4035000005000000 0480000001000800 020001001a000a09 27a5c0d564067200" + "ca006440080064f0 430020a000004340 060064f043020a", + "", + "", + + "", + "", + "", + + "", + "", + "", + + "", + "", + "", + }; + c_uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 57, + 0, + 0, + + 0, + 0, + 0, + + 0, + 0, + 0, + + 0, + 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_deactivate_bearer_accept( pkbuf_t **pkbuf, int i) { diff --git a/test/rx/testpacket.h b/test/rx/testpacket.h index 3f61854e03..c2b30b4f8d 100644 --- a/test/rx/testpacket.h +++ b/test/rx/testpacket.h @@ -53,12 +53,16 @@ CORE_DECLARE(status_t) tests1ap_build_e_rab_setup_response( pkbuf_t **pkbuf, c_uint32_t mme_ue_s1ap_id, c_uint32_t enb_ue_s1ap_id, c_uint8_t ebi, c_uint32_t teid); +CORE_DECLARE(status_t) tests1ap_build_e_rab_modify_response( + pkbuf_t **pkbuf, int i); CORE_DECLARE(status_t) tests1ap_build_e_rab_release_response( pkbuf_t **pkbuf, int i); CORE_DECLARE(status_t) tests1ap_build_activate_default_bearer_accept( 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_modify_bearer_accept( + pkbuf_t **pkbuf, int i); CORE_DECLARE(status_t) tests1ap_build_deactivate_bearer_accept( pkbuf_t **pkbuf, int i); CORE_DECLARE(status_t) tests1ap_build_path_switch_request( diff --git a/test/rx/volte_test.c b/test/rx/volte_test.c index cb5e5290f4..419b0aa5cc 100644 --- a/test/rx/volte_test.c +++ b/test/rx/volte_test.c @@ -237,7 +237,7 @@ static void volte_test1(abts_case *tc, void *data) core_sleep(time_from_msec(300)); /* Send AA-Request */ - pcscf_rx_send_aar(&rx_sid, "45.45.0.3", 1, 1); + pcscf_rx_send_aar(&rx_sid, "45.45.0.3", 0, 1); /* Receive E-RAB Setup Request + * Activate dedicated EPS bearer context request */ @@ -265,6 +265,27 @@ static void volte_test1(abts_case *tc, void *data) /* Send AA-Request without Flow */ pcscf_rx_send_aar(&rx_sid, "45.45.0.3", 1, 0); + /* Receive E-RAB Modify Request + + * Modify EPS bearer context request */ + recvbuf = pkbuf_alloc(0, MAX_SDU_LEN); + rv = tests1ap_enb_read(sock, recvbuf); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + pkbuf_free(recvbuf); + + /* Send E-RAB Modify Response */ + rv = tests1ap_build_e_rab_modify_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 Modify EPS bearer context accept */ + rv = tests1ap_build_modify_bearer_accept(&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(1000)); #if 0