From 22b09443ce41c34786df167916d603bd17771d69 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Wed, 17 Mar 2021 14:26:57 +0900 Subject: [PATCH] feat: E-RABModificationIndication/Confirm (#834) --- src/mme/mme-context.h | 1 + src/mme/mme-gtp-path.c | 3 +- src/mme/mme-gtp-path.h | 3 +- src/mme/mme-s11-handler.c | 4 ++ src/mme/s1ap-build.c | 106 +++++++++++++++++++++++++++++--- src/mme/s1ap-build.h | 2 + src/mme/s1ap-handler.c | 123 +++++++++++++++++++++++++++++++++++++- src/mme/s1ap-handler.h | 3 + src/mme/s1ap-path.c | 14 +++++ src/mme/s1ap-path.h | 2 + src/mme/s1ap-sm.c | 3 + tests/310014/epc-test.c | 48 ++++++++++++--- tests/common/s1ap-build.c | 105 ++++++++++++++++++++++++++++++-- tests/common/s1ap-build.h | 2 + tests/common/s1ap-path.c | 2 + 15 files changed, 395 insertions(+), 26 deletions(-) diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 902ba127c..7369ef61f 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -490,6 +490,7 @@ struct mme_ue_s { #define MAX_NUM_OF_GTP_COUNTER 16 #define GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH 1 +#define GTP_COUNTER_MODIFY_BEARER_BY_E_RAB_MODIFICATION 2 struct { uint8_t request; uint8_t response; diff --git a/src/mme/mme-gtp-path.c b/src/mme/mme-gtp-path.c index 76ba40f61..1c4fc1f74 100644 --- a/src/mme/mme-gtp-path.c +++ b/src/mme/mme-gtp-path.c @@ -221,8 +221,7 @@ void mme_gtp_send_create_session_request(mme_sess_t *sess) ogs_expect(rv == OGS_OK); } -void mme_gtp_send_modify_bearer_request( - mme_bearer_t *bearer, int uli_presence) +void mme_gtp_send_modify_bearer_request(mme_bearer_t *bearer, int uli_presence) { int rv; diff --git a/src/mme/mme-gtp-path.h b/src/mme/mme-gtp-path.h index 68c8ccfd5..c91bdd2aa 100644 --- a/src/mme/mme-gtp-path.h +++ b/src/mme/mme-gtp-path.h @@ -30,8 +30,7 @@ int mme_gtp_open(void); void mme_gtp_close(void); void mme_gtp_send_create_session_request(mme_sess_t *sess); -void mme_gtp_send_modify_bearer_request( - mme_bearer_t *bearer, int uli_presence); +void mme_gtp_send_modify_bearer_request(mme_bearer_t *bearer, int uli_presence); void mme_gtp_send_delete_session_request(mme_sess_t *sess, int action); void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action); void mme_gtp_send_create_bearer_response( diff --git a/src/mme/mme-s11-handler.c b/src/mme/mme-s11-handler.c index 5b6062a9d..4a7622a93 100644 --- a/src/mme/mme-s11-handler.c +++ b/src/mme/mme-s11-handler.c @@ -295,6 +295,10 @@ void mme_s11_handle_modify_bearer_response( GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH, s1ap_send_path_switch_ack(mme_ue); ); + + GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_E_RAB_MODIFICATION, + s1ap_send_e_rab_modification_confirm(mme_ue); + ); } void mme_s11_handle_delete_session_response( diff --git a/src/mme/s1ap-build.c b/src/mme/s1ap-build.c index 087d70741..58a02a99a 100644 --- a/src/mme/s1ap-build.c +++ b/src/mme/s1ap-build.c @@ -39,8 +39,7 @@ ogs_pkbuf_t *s1ap_build_setup_rsp(void) memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t)); pdu.present = S1AP_S1AP_PDU_PR_successfulOutcome; - pdu.choice.successfulOutcome = - CALLOC(1, sizeof(S1AP_SuccessfulOutcome_t)); + pdu.choice.successfulOutcome = CALLOC(1, sizeof(S1AP_SuccessfulOutcome_t)); successfulOutcome = pdu.choice.successfulOutcome; successfulOutcome->procedureCode = S1AP_ProcedureCode_id_S1Setup; @@ -1231,6 +1230,100 @@ ogs_pkbuf_t *s1ap_build_e_rab_release_command( return ogs_s1ap_encode(&pdu); } +ogs_pkbuf_t *s1ap_build_e_rab_modification_confirm(mme_ue_t *mme_ue) +{ + S1AP_S1AP_PDU_t pdu; + S1AP_SuccessfulOutcome_t *successfulOutcome = NULL; + S1AP_E_RABModificationConfirm_t *E_RABModificationConfirm = NULL; + + S1AP_E_RABModificationConfirmIEs_t *ie = NULL; + S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL; + S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL; + S1AP_E_RABModifyListBearerModConf_t *E_RABModifyListBearerModConf = NULL; + + enb_ue_t *enb_ue = NULL; + mme_sess_t *sess = NULL; + mme_bearer_t *bearer = NULL; + + ogs_assert(mme_ue); + enb_ue = enb_ue_cycle(mme_ue->enb_ue); + ogs_assert(enb_ue); + + ogs_debug("E-RABModificationConfirm"); + + memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t)); + pdu.present = S1AP_S1AP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome = CALLOC(1, sizeof(S1AP_SuccessfulOutcome_t)); + + successfulOutcome = pdu.choice.successfulOutcome; + successfulOutcome->procedureCode = + S1AP_ProcedureCode_id_E_RABModificationIndication; + successfulOutcome->criticality = S1AP_Criticality_reject; + successfulOutcome->value.present = + S1AP_SuccessfulOutcome__value_PR_E_RABModificationConfirm; + + E_RABModificationConfirm = + &successfulOutcome->value.choice.E_RABModificationConfirm; + + ie = CALLOC(1, sizeof(S1AP_E_RABModificationConfirmIEs_t)); + ASN_SEQUENCE_ADD(&E_RABModificationConfirm->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = + S1AP_E_RABModificationConfirmIEs__value_PR_MME_UE_S1AP_ID; + + MME_UE_S1AP_ID = &ie->value.choice.MME_UE_S1AP_ID; + + ie = CALLOC(1, sizeof(S1AP_E_RABModificationConfirmIEs_t)); + ASN_SEQUENCE_ADD(&E_RABModificationConfirm->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = + S1AP_E_RABModificationConfirmIEs__value_PR_ENB_UE_S1AP_ID; + + ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID; + + ie = CALLOC(1, sizeof(S1AP_E_RABModificationConfirmIEs_t)); + ASN_SEQUENCE_ADD(&E_RABModificationConfirm->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_E_RABModifyListBearerModConf; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = + S1AP_E_RABModificationConfirmIEs__value_PR_E_RABModifyListBearerModConf; + + E_RABModifyListBearerModConf = &ie->value.choice.E_RABModifyListBearerModConf; + + ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]", + enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id); + + *MME_UE_S1AP_ID = enb_ue->mme_ue_s1ap_id; + *ENB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id; + + ogs_list_for_each(&mme_ue->sess_list, sess) { + ogs_list_for_each(&sess->bearer_list, bearer) { + S1AP_E_RABModifyItemBearerModConfIEs_t *item = NULL; + S1AP_E_RABModifyItemBearerModConf_t *e_rab = NULL; + + item = CALLOC(1, sizeof(S1AP_E_RABModifyItemBearerModConfIEs_t)); + ASN_SEQUENCE_ADD(&E_RABModifyListBearerModConf->list, item); + + item->id = S1AP_ProtocolIE_ID_id_E_RABModifyItemBearerModConf; + item->criticality = S1AP_Criticality_ignore; + item->value.present = S1AP_E_RABModifyItemBearerModConfIEs__value_PR_E_RABModifyItemBearerModConf; + + e_rab = &item->value.choice.E_RABModifyItemBearerModConf; + + e_rab->e_RAB_ID = bearer->ebi; + + ogs_debug(" EBI[%d]", bearer->ebi); + } + } + + return ogs_s1ap_encode(&pdu); +} + ogs_pkbuf_t *s1ap_build_paging( mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain) { @@ -1420,8 +1513,7 @@ ogs_pkbuf_t *s1ap_build_path_switch_ack(mme_ue_t *mme_ue) memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t)); pdu.present = S1AP_S1AP_PDU_PR_successfulOutcome; - pdu.choice.successfulOutcome = - CALLOC(1, sizeof(S1AP_SuccessfulOutcome_t)); + pdu.choice.successfulOutcome = CALLOC(1, sizeof(S1AP_SuccessfulOutcome_t)); successfulOutcome = pdu.choice.successfulOutcome; successfulOutcome->procedureCode = S1AP_ProcedureCode_id_PathSwitchRequest; @@ -1579,8 +1671,7 @@ ogs_pkbuf_t *s1ap_build_handover_command(enb_ue_t *source_ue) memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t)); pdu.present = S1AP_S1AP_PDU_PR_successfulOutcome; - pdu.choice.successfulOutcome = - CALLOC(1, sizeof(S1AP_SuccessfulOutcome_t)); + pdu.choice.successfulOutcome = CALLOC(1, sizeof(S1AP_SuccessfulOutcome_t)); successfulOutcome = pdu.choice.successfulOutcome; successfulOutcome->procedureCode = @@ -2063,8 +2154,7 @@ ogs_pkbuf_t *s1ap_build_handover_cancel_ack(enb_ue_t *source_ue) memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t)); pdu.present = S1AP_S1AP_PDU_PR_successfulOutcome; - pdu.choice.successfulOutcome = - CALLOC(1, sizeof(S1AP_SuccessfulOutcome_t)); + pdu.choice.successfulOutcome = CALLOC(1, sizeof(S1AP_SuccessfulOutcome_t)); successfulOutcome = pdu.choice.successfulOutcome; successfulOutcome->procedureCode = S1AP_ProcedureCode_id_HandoverCancel; diff --git a/src/mme/s1ap-build.h b/src/mme/s1ap-build.h index fc55463dd..019dd4c65 100644 --- a/src/mme/s1ap-build.h +++ b/src/mme/s1ap-build.h @@ -48,6 +48,8 @@ ogs_pkbuf_t *s1ap_build_e_rab_modify_request( ogs_pkbuf_t *s1ap_build_e_rab_release_command( mme_bearer_t *bearer, ogs_pkbuf_t *esmbuf, S1AP_Cause_PR group, long cause); +ogs_pkbuf_t *s1ap_build_e_rab_modification_confirm(mme_ue_t *mme_ue); + ogs_pkbuf_t *s1ap_build_paging( mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain); diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c index 1ff9d5354..7bd4ac4f6 100644 --- a/src/mme/s1ap-handler.c +++ b/src/mme/s1ap-handler.c @@ -1317,6 +1317,120 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue) } } +void s1ap_handle_e_rab_modification_indication( + mme_enb_t *enb, ogs_s1ap_message_t *message) +{ + char buf[OGS_ADDRSTRLEN]; + int rv, i; + + S1AP_InitiatingMessage_t *initiatingMessage = NULL; + S1AP_E_RABModificationIndication_t *E_RABModificationIndication = NULL; + + S1AP_E_RABModificationIndicationIEs_t *ie = NULL; + S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL; + S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL; + S1AP_E_RABToBeModifiedListBearerModInd_t + *E_RABToBeModifiedListBearerModInd = NULL; + + enb_ue_t *enb_ue = NULL; + mme_ue_t *mme_ue = NULL; + + ogs_assert(enb); + ogs_assert(enb->sctp.sock); + + ogs_assert(message); + initiatingMessage = message->choice.initiatingMessage; + ogs_assert(initiatingMessage); + E_RABModificationIndication = &initiatingMessage->value.choice.E_RABModificationIndication; + ogs_assert(E_RABModificationIndication); + + ogs_info("E_RABModificationIndication"); + + for (i = 0; i < E_RABModificationIndication->protocolIEs.list.count; i++) { + ie = E_RABModificationIndication->protocolIEs.list.array[i]; + switch (ie->id) { + case S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID: + MME_UE_S1AP_ID = &ie->value.choice.MME_UE_S1AP_ID; + break; + case S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID: + ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID; + break; + case S1AP_ProtocolIE_ID_id_E_RABToBeModifiedListBearerModInd: + E_RABToBeModifiedListBearerModInd = + &ie->value.choice.E_RABToBeModifiedListBearerModInd; + break; + default: + break; + } + } + + ogs_debug(" IP[%s] ENB_ID[%d]", + OGS_ADDR(enb->sctp.addr, buf), enb->enb_id); + + if (!MME_UE_S1AP_ID) { + ogs_error("No MME_UE_S1AP_ID"); + s1ap_send_error_indication(enb, + MME_UE_S1AP_ID, NULL, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + return; + } + enb_ue = enb_ue_find_by_mme_ue_s1ap_id(*MME_UE_S1AP_ID); + if (!enb_ue) { + ogs_warn("No ENB UE Context : MME_UE_S1AP_ID[%d]", + (int)*MME_UE_S1AP_ID); + s1ap_send_error_indication(enb, + MME_UE_S1AP_ID, NULL, + S1AP_Cause_PR_radioNetwork, + S1AP_CauseRadioNetwork_unknown_mme_ue_s1ap_id); + return; + } + + ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]", + enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id); + + mme_ue = enb_ue->mme_ue; + ogs_expect_or_return(mme_ue); + + if (!E_RABToBeModifiedListBearerModInd) { + ogs_error("No E_RABToBeModifiedListBearerModInd"); + s1ap_send_error_indication2(mme_ue, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + return; + } + + for (i = 0; i < E_RABToBeModifiedListBearerModInd->list.count; i++) { + S1AP_E_RABToBeModifiedItemBearerModIndIEs_t *item = NULL; + S1AP_E_RABToBeModifiedItemBearerModInd_t *e_rab = NULL; + + mme_bearer_t *bearer = NULL; + + item = (S1AP_E_RABToBeModifiedItemBearerModIndIEs_t *) + E_RABToBeModifiedListBearerModInd->list.array[i]; + ogs_assert(item); + + e_rab = &item->value.choice.E_RABToBeModifiedItemBearerModInd; + ogs_assert(e_rab); + + bearer = mme_bearer_find_by_ue_ebi(mme_ue, e_rab->e_RAB_ID); + if (!bearer) { + ogs_error("No Bearer [%d]", (int)e_rab->e_RAB_ID); + continue; + } + + memcpy(&bearer->enb_s1u_teid, e_rab->dL_GTP_TEID.buf, + sizeof(bearer->enb_s1u_teid)); + bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid); + rv = ogs_asn_BIT_STRING_to_ip( + &e_rab->transportLayerAddress, &bearer->enb_s1u_ip); + ogs_expect(rv == OGS_OK); + + GTP_COUNTER_INCREMENT( + mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_E_RAB_MODIFICATION); + + mme_gtp_send_modify_bearer_request(bearer, 0); + } +} + void s1ap_handle_path_switch_request( mme_enb_t *enb, ogs_s1ap_message_t *message) { @@ -1388,8 +1502,13 @@ void s1ap_handle_path_switch_request( ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->sctp.addr, buf), enb->enb_id); - ogs_assert(MME_UE_S1AP_ID); - ogs_assert(ENB_UE_S1AP_ID); + if (!MME_UE_S1AP_ID) { + ogs_error("No MME_UE_S1AP_ID"); + s1ap_send_error_indication(enb, + MME_UE_S1AP_ID, NULL, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error); + return; + } enb_ue = enb_ue_find_by_mme_ue_s1ap_id(*MME_UE_S1AP_ID); if (!enb_ue) { ogs_error("Cannot find UE from sourceMME-UE-S1AP-ID[%d] and eNB[%s:%d]", diff --git a/src/mme/s1ap-handler.h b/src/mme/s1ap-handler.h index 120482770..22f62c991 100644 --- a/src/mme/s1ap-handler.h +++ b/src/mme/s1ap-handler.h @@ -53,6 +53,9 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue); void s1ap_handle_e_rab_setup_response( mme_enb_t *enb, ogs_s1ap_message_t *message); +void s1ap_handle_e_rab_modification_indication( + mme_enb_t *enb, ogs_s1ap_message_t *message); + void s1ap_handle_path_switch_request( mme_enb_t *enb, ogs_s1ap_message_t *message); diff --git a/src/mme/s1ap-path.c b/src/mme/s1ap-path.c index 1ee6d6237..79cad6a9a 100644 --- a/src/mme/s1ap-path.c +++ b/src/mme/s1ap-path.c @@ -374,6 +374,20 @@ void s1ap_send_mme_configuration_transfer( ogs_expect(rv == OGS_OK); } +void s1ap_send_e_rab_modification_confirm(mme_ue_t *mme_ue) +{ + int rv; + ogs_pkbuf_t *s1apbuf = NULL; + + ogs_assert(mme_ue); + + s1apbuf = s1ap_build_e_rab_modification_confirm(mme_ue); + ogs_expect_or_return(s1apbuf); + + rv = nas_eps_send_to_enb(mme_ue, s1apbuf); + ogs_expect(rv == OGS_OK); +} + void s1ap_send_path_switch_ack(mme_ue_t *mme_ue) { int rv; diff --git a/src/mme/s1ap-path.h b/src/mme/s1ap-path.h index 74dbce990..73db6b835 100644 --- a/src/mme/s1ap-path.h +++ b/src/mme/s1ap-path.h @@ -62,6 +62,8 @@ void s1ap_send_mme_configuration_transfer( mme_enb_t *target_enb, S1AP_SONConfigurationTransfer_t *SONConfigurationTransfer); +void s1ap_send_e_rab_modification_confirm(mme_ue_t *mme_ue); + void s1ap_send_path_switch_ack(mme_ue_t *mme_ue); void s1ap_send_handover_command(enb_ue_t *source_ue); diff --git a/src/mme/s1ap-sm.c b/src/mme/s1ap-sm.c index 0f29b4593..9132cd00b 100644 --- a/src/mme/s1ap-sm.c +++ b/src/mme/s1ap-sm.c @@ -129,6 +129,9 @@ void s1ap_state_operational(ogs_fsm_t *s, mme_event_t *e) case S1AP_ProcedureCode_id_NASNonDeliveryIndication: /* TODO */ break; + case S1AP_ProcedureCode_id_E_RABModificationIndication: + s1ap_handle_e_rab_modification_indication(enb, pdu); + break; default: ogs_error("Not implemented(choice:%d, proc:%d)", pdu->present, (int)initiatingMessage->procedureCode); diff --git a/tests/310014/epc-test.c b/tests/310014/epc-test.c index d12f420b1..9c16228c9 100644 --- a/tests/310014/epc-test.c +++ b/tests/310014/epc-test.c @@ -23,7 +23,7 @@ static void test1_func(abts_case *tc, void *data) { int rv; ogs_socknode_t *s1ap; - ogs_socknode_t *gtpu; + ogs_socknode_t *gtpu1, *gtpu2; ogs_pkbuf_t *emmbuf; ogs_pkbuf_t *esmbuf; ogs_pkbuf_t *sendbuf; @@ -71,9 +71,12 @@ static void test1_func(abts_case *tc, void *data) s1ap = tests1ap_client(AF_INET); ABTS_PTR_NOTNULL(tc, s1ap); - /* eNB connects to SGW */ - gtpu = test_gtpu_server(1, AF_INET); - ABTS_PTR_NOTNULL(tc, gtpu); + /* Two eNB connects to SGW */ + gtpu1 = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu1); + + gtpu2 = test_gtpu_server(2, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu2); /* Send S1-Setup Reqeust */ sendbuf = test_s1ap_build_s1_setup_request( @@ -99,6 +102,7 @@ static void test1_func(abts_case *tc, void *data) ABTS_PTR_NOTNULL(tc, esmbuf); test_ue->attach_request_param.ms_network_feature_support = 1; + test_ue->attach_request_param.ue_additional_security_capability = 1; emmbuf = testemm_build_attach_request(test_ue, esmbuf); ABTS_PTR_NOTNULL(tc, emmbuf); @@ -189,11 +193,38 @@ static void test1_func(abts_case *tc, void *data) /* Send GTP-U ICMP Packet */ bearer = test_bearer_find_by_ue_ebi(test_ue, 5); ogs_assert(bearer); - rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + rv = test_gtpu_send_ping(gtpu1, bearer, TEST_PING_IPV4); ABTS_INT_EQUAL(tc, OGS_OK, rv); /* Receive GTP-U ICMP Packet */ - recvbuf = test_gtpu_read(gtpu); + recvbuf = test_gtpu_read(gtpu1); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send E-RABModificationIndication */ + ogs_list_for_each(&sess->bearer_list, bearer) { + bearer->enb_s1u_addr = test_self()->gnb2_addr; + bearer->enb_s1u_addr6 = test_self()->gnb2_addr6; + } + + sendbuf = test_s1ap_build_e_rab_modification_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RABModificationConfirm */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 5); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu2, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu2); ABTS_PTR_NOTNULL(tc, recvbuf); ogs_pkbuf_free(recvbuf); @@ -203,8 +234,9 @@ static void test1_func(abts_case *tc, void *data) /* eNB disonncect from MME */ testenb_s1ap_close(s1ap); - /* eNB disonncect from SGW */ - test_gtpu_close(gtpu); + /* Two eNB disonncect from SGW */ + testgnb_gtpu_close(gtpu1); + testgnb_gtpu_close(gtpu2); test_ue_remove(test_ue); } diff --git a/tests/common/s1ap-build.c b/tests/common/s1ap-build.c index 84b402627..cf96f6f63 100644 --- a/tests/common/s1ap-build.c +++ b/tests/common/s1ap-build.c @@ -811,7 +811,6 @@ ogs_pkbuf_t *test_s1ap_build_ue_context_release_complete(test_ue_t *test_ue) ogs_pkbuf_t *test_s1ap_build_e_rab_setup_response(test_bearer_t *bearer) { int rv; - ogs_sockaddr_t *addr = NULL; test_ue_t *test_ue = NULL; test_sess_t *sess = NULL; @@ -911,7 +910,6 @@ ogs_pkbuf_t *test_s1ap_build_e_rab_setup_response(test_bearer_t *bearer) ogs_pkbuf_t *test_s1ap_build_e_rab_modify_response(test_bearer_t *bearer) { int rv; - ogs_sockaddr_t *addr = NULL; test_ue_t *test_ue = NULL; test_sess_t *sess = NULL; @@ -995,7 +993,6 @@ ogs_pkbuf_t *test_s1ap_build_e_rab_modify_response(test_bearer_t *bearer) ogs_pkbuf_t *test_s1ap_build_e_rab_release_response(test_bearer_t *bearer) { int rv; - ogs_sockaddr_t *addr = NULL; test_ue_t *test_ue = NULL; test_sess_t *sess = NULL; @@ -1079,6 +1076,107 @@ ogs_pkbuf_t *test_s1ap_build_e_rab_release_response(test_bearer_t *bearer) return ogs_s1ap_encode(&pdu); } +ogs_pkbuf_t *test_s1ap_build_e_rab_modification_indication(test_ue_t *test_ue) +{ + int rv; + + test_sess_t *sess = NULL; + test_bearer_t *bearer = NULL; + + S1AP_S1AP_PDU_t pdu; + S1AP_InitiatingMessage_t *initiatingMessage = NULL; + S1AP_E_RABModificationIndication_t *E_RABModificationIndication = NULL; + + S1AP_E_RABModificationIndicationIEs_t *ie = NULL; + S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL; + S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL; + S1AP_E_RABToBeModifiedListBearerModInd_t + *E_RABToBeModifiedListBearerModInd = NULL; + + memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t)); + pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage = CALLOC(1, sizeof(S1AP_InitiatingMessage_t)); + + initiatingMessage = pdu.choice.initiatingMessage; + initiatingMessage->procedureCode = + S1AP_ProcedureCode_id_E_RABModificationIndication; + initiatingMessage->criticality = S1AP_Criticality_reject; + initiatingMessage->value.present = + S1AP_InitiatingMessage__value_PR_E_RABModificationIndication; + + E_RABModificationIndication = + &initiatingMessage->value.choice.E_RABModificationIndication; + + ie = CALLOC(1, sizeof(S1AP_E_RABModificationIndicationIEs_t)); + ASN_SEQUENCE_ADD(&E_RABModificationIndication->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = + S1AP_E_RABModificationIndicationIEs__value_PR_MME_UE_S1AP_ID; + MME_UE_S1AP_ID = &ie->value.choice.MME_UE_S1AP_ID; + + ie = CALLOC(1, sizeof(S1AP_E_RABModificationIndicationIEs_t)); + ASN_SEQUENCE_ADD(&E_RABModificationIndication->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = + S1AP_E_RABModificationIndicationIEs__value_PR_ENB_UE_S1AP_ID; + + ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID; + + ie = CALLOC(1, sizeof(S1AP_E_RABModificationIndicationIEs_t)); + ASN_SEQUENCE_ADD(&E_RABModificationIndication->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_E_RABToBeModifiedListBearerModInd; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_E_RABModificationIndicationIEs__value_PR_E_RABToBeModifiedListBearerModInd; + + E_RABToBeModifiedListBearerModInd = + &ie->value.choice.E_RABToBeModifiedListBearerModInd; + + *ENB_UE_S1AP_ID = test_ue->enb_ue_s1ap_id; + *MME_UE_S1AP_ID = test_ue->mme_ue_s1ap_id; + + ogs_list_for_each(&test_ue->sess_list, sess) { + ogs_list_for_each(&sess->bearer_list, bearer) { + S1AP_E_RABToBeModifiedItemBearerModIndIEs_t *item = NULL; + S1AP_E_RABToBeModifiedItemBearerModInd_t *e_rab = NULL; + + ogs_gtp_f_teid_t f_teid; + ogs_ip_t ip; + int len; + + item = CALLOC(1, + sizeof(S1AP_E_RABToBeModifiedItemBearerModIndIEs_t)); + ASN_SEQUENCE_ADD(&E_RABToBeModifiedListBearerModInd->list, item); + + item->id = S1AP_ProtocolIE_ID_id_E_RABToBeModifiedItemBearerModInd; + item->criticality = S1AP_Criticality_reject; + item->value.present = S1AP_E_RABToBeModifiedItemBearerModIndIEs__value_PR_E_RABToBeModifiedItemBearerModInd; + + e_rab = &item->value.choice.E_RABToBeModifiedItemBearerModInd; + + e_rab->e_RAB_ID = bearer->ebi; + + rv = ogs_gtp_sockaddr_to_f_teid( + bearer->enb_s1u_addr, bearer->enb_s1u_addr6, &f_teid, &len); + ogs_assert(rv == OGS_OK); + + rv = ogs_gtp_f_teid_to_ip(&f_teid, &ip); + ogs_assert(rv == OGS_OK); + + rv = ogs_asn_ip_to_BIT_STRING(&ip, &e_rab->transportLayerAddress); + ogs_assert(rv == OGS_OK); + ogs_asn_uint32_to_OCTET_STRING( + bearer->enb_s1u_teid, &e_rab->dL_GTP_TEID); + } + } + + return ogs_s1ap_encode(&pdu); +} + ogs_pkbuf_t *test_s1ap_build_path_switch_request(test_ue_t *test_ue) { int rv; @@ -1174,7 +1272,6 @@ ogs_pkbuf_t *test_s1ap_build_path_switch_request(test_ue_t *test_ue) S1AP_E_RABToBeSwitchedDLItemIEs_t *item = NULL; S1AP_E_RABToBeSwitchedDLItem_t *e_rab = NULL; - ogs_sockaddr_t *addr = NULL; ogs_gtp_f_teid_t f_teid; ogs_ip_t ip; int len; diff --git a/tests/common/s1ap-build.h b/tests/common/s1ap-build.h index 63f251872..7c87d8f3b 100644 --- a/tests/common/s1ap-build.h +++ b/tests/common/s1ap-build.h @@ -47,6 +47,8 @@ ogs_pkbuf_t *test_s1ap_build_e_rab_setup_response(test_bearer_t *bearer); ogs_pkbuf_t *test_s1ap_build_e_rab_modify_response(test_bearer_t *bearer); ogs_pkbuf_t *test_s1ap_build_e_rab_release_response(test_bearer_t *bearer); +ogs_pkbuf_t *test_s1ap_build_e_rab_modification_indication(test_ue_t *test_ue); + ogs_pkbuf_t *test_s1ap_build_path_switch_request(test_ue_t *test_ue); ogs_pkbuf_t *test_s1ap_build_handover_required( diff --git a/tests/common/s1ap-path.c b/tests/common/s1ap-path.c index 25af15f69..c85a34435 100644 --- a/tests/common/s1ap-path.c +++ b/tests/common/s1ap-path.c @@ -106,6 +106,8 @@ void tests1ap_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf) break; case S1AP_ProcedureCode_id_Reset: break; + case S1AP_ProcedureCode_id_E_RABModificationIndication: + break; default: ogs_error("Not implemented(choice:%d, proc:%d)", pdu->present, (int)successfulOutcome->procedureCode);