mme: s1ap: Implement tx of MME DIRECT INFORMATION TRANSFER

Triggered when receiving a GTPv1C RAN Information Relay message on
Gn interface, targeted at one of the eNBs under the MME.
This commit is contained in:
Pau Espin 2023-07-11 14:48:50 +02:00 committed by Sukchan Lee
parent 158bd79bdd
commit 5c0c8ec4f2
5 changed files with 174 additions and 1 deletions

View File

@ -29,6 +29,8 @@
#include "mme-gn-build.h"
#include "mme-gn-handler.h"
#include "s1ap-path.h"
void mme_gn_handle_echo_request(
ogs_gtp_xact_t *xact, ogs_gtp1_echo_request_t *req)
{
@ -46,10 +48,97 @@ void mme_gn_handle_echo_response(
/* Not Implemented */
}
static int decode_global_enb_id(S1AP_Global_ENB_ID_t *glob_enb_id, const uint8_t *buf, size_t buf_len)
{
asn_dec_rval_t dec_ret = {0};
memset(glob_enb_id, 0, sizeof(S1AP_Global_ENB_ID_t));
dec_ret = aper_decode(NULL, &asn_DEF_S1AP_Global_ENB_ID, (void **)&glob_enb_id,
buf, buf_len, 0, 0);
if (dec_ret.code != RC_OK) {
ogs_warn("Failed to decode ASN-PDU [code:%d,consumed:%d]",
dec_ret.code, (int)dec_ret.consumed);
return OGS_ERROR;
}
if (ogs_log_get_domain_level(OGS_LOG_DOMAIN) >= OGS_LOG_TRACE)
asn_fprint(stdout, &asn_DEF_S1AP_Global_ENB_ID, glob_enb_id);
return OGS_OK;
}
/* TS 29.060 7.5.14.1 */
void mme_gn_handle_ran_information_relay(
ogs_gtp_xact_t *xact, ogs_gtp1_ran_information_relay_t *req)
{
uint8_t discr;
ogs_eps_tai_t *target_tai;
S1AP_Global_ENB_ID_t global_ENB_ID;
uint32_t target_enb_id;
mme_enb_t *target_enb = NULL;
int rv;
ogs_debug("[Gn] Receiving RAN Information Relay");
/* Not Implemented */
if (req->ran_transparent_container.len == 0 ||
req->ran_transparent_container.data == NULL) {
ogs_warn("[Gn] Receiving RAN Information Relay with empty container!");
return;
}
/* "If RIM Routing Address Discriminator IE is not included, the RIM Routing
* Address shall be processed as an RNC identifier". Hence, not for us! */
if (req->rim_routing_address_discriminator.presence == false) {
ogs_warn("[Gn] Rx RAN Information Relay: no RIM Routing Address Discriminator!");
return;
}
if (req->rim_routing_address_discriminator.len != 1) {
ogs_warn("[Gn] Rx RAN Information Relay: RIM Routing Address Discriminator len != 1");
return;
}
/* 3GPP TS 48.018 RIM Routing Information IE */
discr = *((uint8_t*)req->rim_routing_address_discriminator.data) & 0x0f;
if (discr != 2) {/* 2: An eNB identifier is used to identify an E-UTRAN eNodeB or HeNB */
ogs_warn("[Gn] Rx RAN Information Relay: RIM Routing Address Discriminator %u unexpected", discr);
return;
}
if (req->rim_routing_address.presence == false) {
ogs_warn("[Gn] Rx RAN Information Relay: no RIM Routing Address!");
return;
}
if (req->rim_routing_address.len < sizeof(ogs_eps_tai_t)) {
ogs_warn("[Gn] Rx RAN Information Relay: RIM Routing Address len < %zu", sizeof(ogs_eps_tai_t));
return;
}
target_tai = req->rim_routing_address.data;
rv = decode_global_enb_id(&global_ENB_ID,
((uint8_t *)req->rim_routing_address.data) + sizeof(ogs_eps_tai_t),
req->rim_routing_address.len - sizeof(ogs_eps_tai_t));
if (rv != OGS_OK)
return;
ogs_s1ap_ENB_ID_to_uint32(&global_ENB_ID.eNB_ID, &target_enb_id);
ogs_debug(" Target : ENB_ID[%s:%d], TAC[%d]",
global_ENB_ID.eNB_ID.present ==
S1AP_ENB_ID_PR_homeENB_ID ? "Home" :
global_ENB_ID.eNB_ID.present ==
S1AP_ENB_ID_PR_macroENB_ID ? "Macro" : "Others",
target_enb_id, target_tai->tac);
target_enb = mme_enb_find_by_enb_id(target_enb_id);
if (target_enb == NULL) {
ogs_warn("[Gn] Rx RAN Information Relay: cannot find target eNB-id[0x%x]", target_enb_id);
return;
}
s1ap_send_mme_direct_information_transfer(
target_enb,
req->ran_transparent_container.data,
req->ran_transparent_container.len);
}

View File

@ -1559,6 +1559,60 @@ ogs_pkbuf_t *s1ap_build_mme_configuration_transfer(
return ogs_s1ap_encode(&pdu);
}
/* 3GPP TS 36.413 8.14 MME Direct Information Transfer */
ogs_pkbuf_t *s1ap_build_direct_information_transfer(const uint8_t *buf, size_t buf_len)
{
S1AP_S1AP_PDU_t pdu;
S1AP_InitiatingMessage_t *initiatingMessage = NULL;
S1AP_MMEDirectInformationTransfer_t *MMEDirectInformationTransfer = NULL;
S1AP_MMEDirectInformationTransferIEs_t *ie = NULL;
S1AP_Inter_SystemInformationTransferType_t *Inter_SystemInformationTransferType = NULL;
S1AP_RIMTransfer_t *rIMTransfer = NULL;
ogs_assert(buf);
ogs_assert(buf_len > 0);
ogs_debug("MMEDirectInformationTransfer");
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_MMEDirectInformationTransfer;
initiatingMessage->criticality = S1AP_Criticality_ignore;
initiatingMessage->value.present =
S1AP_InitiatingMessage__value_PR_MMEDirectInformationTransfer;
MMEDirectInformationTransfer =
&initiatingMessage->value.choice.MMEDirectInformationTransfer;
ie = CALLOC(1, sizeof(S1AP_MMEDirectInformationTransferIEs_t));
ASN_SEQUENCE_ADD(&MMEDirectInformationTransfer->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_Inter_SystemInformationTransferTypeMDT;
ie->criticality = S1AP_Criticality_reject;
ie->value.present =
S1AP_MMEDirectInformationTransferIEs__value_PR_Inter_SystemInformationTransferType;
Inter_SystemInformationTransferType = &ie->value.choice.Inter_SystemInformationTransferType;
Inter_SystemInformationTransferType->present = S1AP_Inter_SystemInformationTransferType_PR_rIMTransfer;
Inter_SystemInformationTransferType->choice.rIMTransfer = CALLOC(1, sizeof(S1AP_RIMTransfer_t));
rIMTransfer = Inter_SystemInformationTransferType->choice.rIMTransfer;
rIMTransfer->rIMInformation.size = buf_len;
rIMTransfer->rIMInformation.buf = CALLOC(buf_len, sizeof(uint8_t));
memcpy(rIMTransfer->rIMInformation.buf, buf, buf_len);
/* "The RIM Routing Address IE shall not be present since the eNB is the final destination node": */
rIMTransfer->rIMRoutingAddress = NULL;
return ogs_s1ap_encode(&pdu);
}
ogs_pkbuf_t *s1ap_build_path_switch_ack(
mme_ue_t *mme_ue, bool e_rab_to_switched_in_uplink_list)
{

View File

@ -56,6 +56,8 @@ ogs_pkbuf_t *s1ap_build_paging(
ogs_pkbuf_t *s1ap_build_mme_configuration_transfer(
S1AP_SONConfigurationTransfer_t *son_configuration_transfer);
ogs_pkbuf_t *s1ap_build_direct_information_transfer(const uint8_t *buf, size_t buf_len);
ogs_pkbuf_t *s1ap_build_path_switch_ack(
mme_ue_t *mme_ue, bool e_rab_to_switched_in_uplink_list);
ogs_pkbuf_t *s1ap_build_path_switch_failure(

View File

@ -489,6 +489,31 @@ int s1ap_send_mme_configuration_transfer(
return rv;
}
int s1ap_send_mme_direct_information_transfer(
mme_enb_t *target_enb, const uint8_t *buf, size_t buf_len)
{
int rv;
ogs_pkbuf_t *s1apbuf = NULL;
ogs_debug("Tx MME Direct Information Transfer");
if (!mme_enb_cycle(target_enb)) {
ogs_error("eNB has already been removed");
return OGS_NOTFOUND;
}
s1apbuf = s1ap_build_direct_information_transfer(buf, buf_len);
if (!s1apbuf) {
ogs_error("s1ap_build_direct_information_transfer() failed");
return OGS_ERROR;
}
rv = s1ap_send_to_enb(target_enb, s1apbuf, S1AP_NON_UE_SIGNALLING);
ogs_expect(rv == OGS_OK);
return rv;
}
int s1ap_send_e_rab_modification_confirm(mme_ue_t *mme_ue)
{
int rv;

View File

@ -64,6 +64,9 @@ int s1ap_send_mme_configuration_transfer(
mme_enb_t *target_enb,
S1AP_SONConfigurationTransfer_t *SONConfigurationTransfer);
int s1ap_send_mme_direct_information_transfer(
mme_enb_t *target_enb, const uint8_t *buf, size_t buf_len);
int s1ap_send_e_rab_modification_confirm(mme_ue_t *mme_ue);
int s1ap_send_path_switch_ack(