forked from acouzens/open5gs
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:
parent
158bd79bdd
commit
5c0c8ec4f2
|
@ -29,6 +29,8 @@
|
||||||
#include "mme-gn-build.h"
|
#include "mme-gn-build.h"
|
||||||
#include "mme-gn-handler.h"
|
#include "mme-gn-handler.h"
|
||||||
|
|
||||||
|
#include "s1ap-path.h"
|
||||||
|
|
||||||
void mme_gn_handle_echo_request(
|
void mme_gn_handle_echo_request(
|
||||||
ogs_gtp_xact_t *xact, ogs_gtp1_echo_request_t *req)
|
ogs_gtp_xact_t *xact, ogs_gtp1_echo_request_t *req)
|
||||||
{
|
{
|
||||||
|
@ -46,10 +48,97 @@ void mme_gn_handle_echo_response(
|
||||||
/* Not Implemented */
|
/* 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(
|
void mme_gn_handle_ran_information_relay(
|
||||||
ogs_gtp_xact_t *xact, ogs_gtp1_ran_information_relay_t *req)
|
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");
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1559,6 +1559,60 @@ ogs_pkbuf_t *s1ap_build_mme_configuration_transfer(
|
||||||
return ogs_s1ap_encode(&pdu);
|
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(
|
ogs_pkbuf_t *s1ap_build_path_switch_ack(
|
||||||
mme_ue_t *mme_ue, bool e_rab_to_switched_in_uplink_list)
|
mme_ue_t *mme_ue, bool e_rab_to_switched_in_uplink_list)
|
||||||
{
|
{
|
||||||
|
|
|
@ -56,6 +56,8 @@ ogs_pkbuf_t *s1ap_build_paging(
|
||||||
ogs_pkbuf_t *s1ap_build_mme_configuration_transfer(
|
ogs_pkbuf_t *s1ap_build_mme_configuration_transfer(
|
||||||
S1AP_SONConfigurationTransfer_t *son_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(
|
ogs_pkbuf_t *s1ap_build_path_switch_ack(
|
||||||
mme_ue_t *mme_ue, bool e_rab_to_switched_in_uplink_list);
|
mme_ue_t *mme_ue, bool e_rab_to_switched_in_uplink_list);
|
||||||
ogs_pkbuf_t *s1ap_build_path_switch_failure(
|
ogs_pkbuf_t *s1ap_build_path_switch_failure(
|
||||||
|
|
|
@ -489,6 +489,31 @@ int s1ap_send_mme_configuration_transfer(
|
||||||
return rv;
|
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 s1ap_send_e_rab_modification_confirm(mme_ue_t *mme_ue)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
|
@ -64,6 +64,9 @@ int s1ap_send_mme_configuration_transfer(
|
||||||
mme_enb_t *target_enb,
|
mme_enb_t *target_enb,
|
||||||
S1AP_SONConfigurationTransfer_t *SONConfigurationTransfer);
|
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_e_rab_modification_confirm(mme_ue_t *mme_ue);
|
||||||
|
|
||||||
int s1ap_send_path_switch_ack(
|
int s1ap_send_path_switch_ack(
|
||||||
|
|
Loading…
Reference in New Issue