From 414fc2e9a27d6023a46a584c59bfe5f8837376d1 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 6 Nov 2024 17:55:41 +0100 Subject: [PATCH] Add E1 CU-UP Setup Request enc/dec lib --- openair2/E1AP/lib/e1ap_interface_management.c | 202 ++++++++++++++++++ openair2/E1AP/lib/e1ap_interface_management.h | 7 + openair2/E1AP/lib/e1ap_lib_includes.h | 5 + 3 files changed, 214 insertions(+) diff --git a/openair2/E1AP/lib/e1ap_interface_management.c b/openair2/E1AP/lib/e1ap_interface_management.c index 09d524f4da..6b6c1610c1 100644 --- a/openair2/E1AP/lib/e1ap_interface_management.c +++ b/openair2/E1AP/lib/e1ap_interface_management.c @@ -32,4 +32,206 @@ #include "e1ap_messages_types.h" #include "e1ap_interface_management.h" +/* ==================================== + * GNB-CU-UP E1 SETUP REQUEST + * ==================================== */ +/** + * @brief Encode GNB-CU-UP E1 Setup Request + */ +E1AP_E1AP_PDU_t *encode_e1ap_cuup_setup_request(const e1ap_setup_req_t *msg) +{ + E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + // Message Type (M) + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, m); + m->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup; + m->criticality = E1AP_Criticality_reject; + m->value.present = E1AP_InitiatingMessage__value_PR_GNB_CU_UP_E1SetupRequest; + E1AP_GNB_CU_UP_E1SetupRequest_t *e1SetupUP = &m->value.choice.GNB_CU_UP_E1SetupRequest; + // Transaction ID (M) + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_TransactionID; + ieC1->value.choice.TransactionID = msg->transac_id; + // gNB-CU-UP ID (M) + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_ID; + asn_int642INTEGER(&ieC2->value.choice.GNB_CU_UP_ID, msg->gNB_cu_up_id); + // gNB-CU-UP Name (O) + if (msg->gNB_cu_up_name) { + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC3); + ieC3->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_Name; + ieC3->criticality = E1AP_Criticality_ignore; + ieC3->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_Name; + OCTET_STRING_fromBuf(&ieC3->value.choice.GNB_CU_UP_Name, msg->gNB_cu_up_name, strlen(msg->gNB_cu_up_name)); + } + // CN Support (M) + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC4); + ieC4->id = E1AP_ProtocolIE_ID_id_CNSupport; + ieC4->criticality = E1AP_Criticality_reject; + ieC4->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_CNSupport; + DevAssert(msg->cn_support == cn_support_5GC); /* only 5GC supported */ + ieC4->value.choice.CNSupport = msg->cn_support == cn_support_5GC ? E1AP_CNSupport_c_5gc : E1AP_CNSupport_c_epc; + // Supported PLMNs (1..) + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC5); + ieC5->id = E1AP_ProtocolIE_ID_id_SupportedPLMNs; + ieC5->criticality = E1AP_Criticality_reject; + ieC5->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_SupportedPLMNs_List; + for (int i = 0; i < msg->supported_plmns; i++) { + asn1cSequenceAdd(ieC5->value.choice.SupportedPLMNs_List.list, E1AP_SupportedPLMNs_Item_t, supportedPLMN); + // PLMN Identity (M) + const PLMN_ID_t *id = &msg->plmn[i].id; + MCC_MNC_TO_PLMNID(id->mcc, id->mnc, id->mnc_digit_length, &supportedPLMN->pLMN_Identity); + // Slice Support List (O) + int n = msg->plmn[i].supported_slices; + if (msg->plmn[i].slice != NULL && n > 0) { + supportedPLMN->slice_Support_List = calloc_or_fail(1, sizeof(*supportedPLMN->slice_Support_List)); + for (int s = 0; s < n; ++s) { + asn1cSequenceAdd(supportedPLMN->slice_Support_List->list, E1AP_Slice_Support_Item_t, slice); + e1ap_nssai_t *nssai = &msg->plmn[i].slice[s]; + INT8_TO_OCTET_STRING(nssai->sst, &slice->sNSSAI.sST); + if (nssai->sd != 0xffffff) { + slice->sNSSAI.sD = malloc_or_fail(sizeof(*slice->sNSSAI.sD)); + INT24_TO_OCTET_STRING(nssai->sd, slice->sNSSAI.sD); + } + } + } + } + return pdu; +} + +bool decode_e1ap_cuup_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_req_t *out) +{ + E1AP_GNB_CU_UP_E1SetupRequestIEs_t *ie; + E1AP_GNB_CU_UP_E1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.GNB_CU_UP_E1SetupRequest; + // Transaction ID (M) + E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_TransactionID, true); + // gNB-CU-UP ID (M) + E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID, true); + // CN Support (M) + E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_CNSupport, true); + // Supported PLMNs (1..) + E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_SupportedPLMNs, true); + // Loop over all IEs + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + AssertFatal(ie != NULL, "in->protocolIEs.list.array[i] shall not be null"); + switch (ie->id) { + case E1AP_ProtocolIE_ID_id_TransactionID: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_TransactionID); + out->transac_id = ie->value.choice.TransactionID; + break; + case E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_ID); + asn_INTEGER2ulong(&ie->value.choice.GNB_CU_UP_ID, &out->gNB_cu_up_id); + break; + case E1AP_ProtocolIE_ID_id_gNB_CU_UP_Name: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_Name); + // gNB-CU-UP Name (O) + E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_UP_Name, false); + if (ie != NULL) { + out->gNB_cu_up_name = calloc_or_fail(ie->value.choice.GNB_CU_UP_Name.size + 1, sizeof(char)); + memcpy(out->gNB_cu_up_name, ie->value.choice.GNB_CU_UP_Name.buf, ie->value.choice.GNB_CU_UP_Name.size); + } + break; + case E1AP_ProtocolIE_ID_id_CNSupport: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_CNSupport); + _E1_EQ_CHECK_INT(ie->value.choice.CNSupport, E1AP_CNSupport_c_5gc); // only 5GC CN Support supported + out->cn_support = ie->value.choice.CNSupport; + break; + case E1AP_ProtocolIE_ID_id_SupportedPLMNs: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_SupportedPLMNs_List); + out->supported_plmns = ie->value.choice.SupportedPLMNs_List.list.count; + + for (int i = 0; i < out->supported_plmns; i++) { + E1AP_SupportedPLMNs_Item_t *supported_plmn_item = + (E1AP_SupportedPLMNs_Item_t *)(ie->value.choice.SupportedPLMNs_List.list.array[i]); + + /* PLMN Identity */ + PLMN_ID_t *id = &out->plmn[i].id; + PLMNID_TO_MCC_MNC(&supported_plmn_item->pLMN_Identity, id->mcc, id->mnc, id->mnc_digit_length); + + /* NSSAI */ + if (supported_plmn_item->slice_Support_List) { + int n = supported_plmn_item->slice_Support_List->list.count; + out->plmn[i].supported_slices = n; + out->plmn[i].slice = calloc_or_fail(n, sizeof(*out->plmn[i].slice)); + for (int s = 0; s < n; ++s) { + e1ap_nssai_t *slice = &out->plmn[i].slice[s]; + const E1AP_SNSSAI_t *es = &supported_plmn_item->slice_Support_List->list.array[s]->sNSSAI; + OCTET_STRING_TO_INT8(&es->sST, slice->sst); + slice->sd = 0xffffff; + if (es->sD != NULL) + OCTET_STRING_TO_INT24(es->sD, slice->sd); + } + } + } + break; + default: + PRINT_ERROR("Handle for this IE %ld is not implemented (or) invalid IE detected\n", ie->id); + break; + } + } + return true; +} + +/** + * @brief Deep copy function for E1 CUUP Setup Request + */ +e1ap_setup_req_t cp_e1ap_cuup_setup_request(const e1ap_setup_req_t *msg) +{ + e1ap_setup_req_t cp = {0}; + cp = *msg; + if (msg->gNB_cu_up_name) { + cp.gNB_cu_up_name = strdup(msg->gNB_cu_up_name); + } + for (int i = 0; i < msg->supported_plmns; i++) { + if (msg->plmn[i].slice && msg->plmn[i].supported_slices > 0) { + cp.plmn[i].slice = calloc_or_fail(msg->plmn[i].supported_slices, sizeof(*cp.plmn[i].slice)); + for (int s = 0; s < msg->plmn[i].supported_slices; ++s) { + cp.plmn[i].slice[s] = msg->plmn[i].slice[s]; + } + } + } + return cp; +} + +/** + * @brief Free memory allocated for E1 CUUP Setup Request + */ +void free_e1ap_cuup_setup_request(e1ap_setup_req_t *msg) +{ + // gNB-CU-UP Name + free(msg->gNB_cu_up_name); + // Slice support lists within PLMNs + for (int i = 0; i < msg->supported_plmns; i++) { + free(msg->plmn[i].slice); + } +} + +/** + * @brief Equality check function for E1 CUUP Setup Request + */ +bool eq_e1ap_cuup_setup_request(const e1ap_setup_req_t *a, const e1ap_setup_req_t *b) +{ + _E1_EQ_CHECK_INT(a->transac_id, b->transac_id); + _E1_EQ_CHECK_INT(a->gNB_cu_up_id, b->gNB_cu_up_id); + if (a->gNB_cu_up_name && b->gNB_cu_up_name) + _E1_EQ_CHECK_STR(a->gNB_cu_up_name, b->gNB_cu_up_name) + _E1_EQ_CHECK_INT(a->supported_plmns, b->supported_plmns); + for (int i = 0; i < a->supported_plmns; i++) { + _E1_EQ_CHECK_INT(a->plmn[i].id.mcc, b->plmn[i].id.mcc); + _E1_EQ_CHECK_INT(a->plmn[i].id.mnc, b->plmn[i].id.mnc); + _E1_EQ_CHECK_INT(a->plmn[i].id.mnc_digit_length, b->plmn[i].id.mnc_digit_length); + _E1_EQ_CHECK_INT(a->plmn[i].supported_slices, b->plmn[i].supported_slices); + for (int s = 0; s < a->plmn[i].supported_slices; ++s) { + _E1_EQ_CHECK_INT(a->plmn[i].slice[s].sst, b->plmn[i].slice[s].sst); + _E1_EQ_CHECK_INT(a->plmn[i].slice[s].sd, b->plmn[i].slice[s].sd); + } + } + return true; +} diff --git a/openair2/E1AP/lib/e1ap_interface_management.h b/openair2/E1AP/lib/e1ap_interface_management.h index 92b9ca1407..c0d7d94d44 100644 --- a/openair2/E1AP/lib/e1ap_interface_management.h +++ b/openair2/E1AP/lib/e1ap_interface_management.h @@ -26,4 +26,11 @@ #include "openair2/COMMON/e1ap_messages_types.h" #include "common/platform_types.h" +/* GNB-CU-UP E1 Setup Request */ +struct E1AP_E1AP_PDU *encode_e1ap_cuup_setup_request(const e1ap_setup_req_t *msg); +bool decode_e1ap_cuup_setup_request(const struct E1AP_E1AP_PDU *pdu, e1ap_setup_req_t *out); +e1ap_setup_req_t cp_e1ap_cuup_setup_request(const e1ap_setup_req_t *msg); +void free_e1ap_cuup_setup_request(e1ap_setup_req_t *msg); +bool eq_e1ap_cuup_setup_request(const e1ap_setup_req_t *a, const e1ap_setup_req_t *b); + #endif /* E1AP_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/E1AP/lib/e1ap_lib_includes.h b/openair2/E1AP/lib/e1ap_lib_includes.h index 58da8f6c30..8412645cbe 100644 --- a/openair2/E1AP/lib/e1ap_lib_includes.h +++ b/openair2/E1AP/lib/e1ap_lib_includes.h @@ -53,5 +53,10 @@ #include "E1AP_QoS-Flow-Item.h" #include "E1AP_DRB-Failed-List-NG-RAN.h" #include "E1AP_DRB-Failed-Item-NG-RAN.h" +// E1 Setup +#include "E1AP_SupportedPLMNs-Item.h" +#include "E1AP_Slice-Support-List.h" +#include "E1AP_Slice-Support-Item.h" +#include "E1AP_ProtocolIE-Field.h" #endif /* E1AP_LIB_INCLUDES_H_ */