From e472bbdd1b7e648a0f58fe11ec623b6fbf73d8aa Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 7 Apr 2025 12:13:23 +0200 Subject: [PATCH 01/10] Add missing stdint.h include in e1ap_bearer_context_management.c The header was included via other headers, however since int types are direcltly used in this file, the include is necessary. --- openair2/E1AP/lib/e1ap_bearer_context_management.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index a8f68e70d6..ad5d3dd337 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -27,6 +27,7 @@ */ #include +#include #include "common/utils/assertions.h" #include "openair3/UTILS/conversions.h" From 254e04357d1e8b6ccc8f2798ebd8abcdde931a52 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 7 Apr 2025 12:25:58 +0200 Subject: [PATCH 02/10] Add function name to E1AP PRINT_ERROR macro --- openair2/E1AP/lib/e1ap_lib_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/E1AP/lib/e1ap_lib_common.h b/openair2/E1AP/lib/e1ap_lib_common.h index 6fda2cd8ca..ea6aa7f2ef 100644 --- a/openair2/E1AP/lib/e1ap_lib_common.h +++ b/openair2/E1AP/lib/e1ap_lib_common.h @@ -29,7 +29,7 @@ #include "e1ap_messages_types.h" #ifdef E1AP_LOG_ERRORS -#define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__); +#define PRINT_ERROR(fmt, ...) fprintf(stderr, "[%s] " fmt, __func__, ##__VA_ARGS__) #else #define PRINT_ERROR(...) // Do nothing #endif From 25a093494122684143c1e0f48807f637ec9c32af Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 7 Apr 2025 12:15:19 +0200 Subject: [PATCH 03/10] Fix missing deref on pointer types in Bearer Context Management lib Note: the equality check macros are using a PRINT_ERROR function that is enabled only when E1AP_LOG_ERRORS is defined. --- openair2/E1AP/lib/e1ap_bearer_context_management.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index ad5d3dd337..42065c53f2 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -516,7 +516,7 @@ static bool eq_pdu_session_item(const pdu_session_to_setup_t *a, const pdu_sessi return false; _E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimer); if (a->inactivityTimer && b->inactivityTimer) - _E1_EQ_CHECK_INT(a->inactivityTimer, b->inactivityTimer); + _E1_EQ_CHECK_INT(*a->inactivityTimer, *b->inactivityTimer); _E1_EQ_CHECK_OPTIONAL_IE(a, b, dlAggregateMaxBitRate, _E1_EQ_CHECK_LONG); return true; } @@ -767,7 +767,7 @@ bool eq_bearer_context_setup_request(const e1ap_bearer_setup_req_t *a, const e1a // Check optional IEs _E1_EQ_CHECK_OPTIONAL_PTR(a, b, inactivityTimerUE); if (a->inactivityTimerUE && b->inactivityTimerUE) - _E1_EQ_CHECK_INT(a->inactivityTimerUE, b->inactivityTimerUE); + _E1_EQ_CHECK_INT(*a->inactivityTimerUE, *b->inactivityTimerUE); _E1_EQ_CHECK_OPTIONAL_IE(a, b, ueDlMaxIPBitRate, _E1_EQ_CHECK_LONG); return true; } From 673770d34627263d898b7438c08d5c6de8ecfee4 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 19 Feb 2025 12:47:34 +0100 Subject: [PATCH 04/10] Bugfix in e1_decode_pdu_session_to_mod_item: missing check on allocation of optional pointer The Bearer Context Modification Request test is adding 1 QoS Flow, therefore the encoding/decoding is done and this bug does not show. The issue is there when no QoS Flow is mapped in the DRBnGRanModList, therefore when no memory is allocated for the optional IE, and the member is accessed in the decoding of the Flow Mapping Information. --- openair2/E1AP/lib/e1ap_bearer_context_management.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index 42065c53f2..6035258e95 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -1350,10 +1350,12 @@ static bool e1_decode_pdu_session_to_mod_item(pdu_session_to_mod_t *out, const E } } // QoS Flows Information To Be Setup (O) - E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = drb2Mod->flow_Mapping_Information; - drb->numQosFlow2Setup = qos2SetupList->list.count; - for (int k = 0; k < qos2SetupList->list.count; k++) { - CHECK_E1AP_DEC(e1_decode_qos_flow_to_setup(drb->qosFlows + k, qos2SetupList->list.array[k])); + if (drb2Mod->flow_Mapping_Information) { + E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = drb2Mod->flow_Mapping_Information; + drb->numQosFlow2Setup = qos2SetupList->list.count; + for (int k = 0; k < qos2SetupList->list.count; k++) { + CHECK_E1AP_DEC(e1_decode_qos_flow_to_setup(drb->qosFlows + k, qos2SetupList->list.array[k])); + } } } return true; From 248380b6a42f33ea82597cbd61346886cb1e4eaa Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 17 Feb 2025 10:40:47 +0100 Subject: [PATCH 05/10] Refactor E1 Security Information decoding function * adopt changes from 182b05bd * add checks on optional IEs * add checks on encoded buffer sizes --- .../E1AP/lib/e1ap_bearer_context_management.c | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index 6035258e95..b200813ddc 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -84,19 +84,29 @@ static E1AP_SecurityInformation_t e1_encode_security_info(const security_informa return ie; } -/** - * @brief Decode E1AP_SecurityInformation_t - */ +/** @brief Decode Security Information IE (3GPP TS 38.463, 9.3.1.10) */ static bool e1_decode_security_info(security_information_t *out, const E1AP_SecurityInformation_t *in) { + // Security Algorithm (M) (9.3.1.31) + // Ciphering Algorithm (M) out->cipheringAlgorithm = in->securityAlgorithm.cipheringAlgorithm; + // Integrity Protection Algorithm (O) + out->integrityProtectionAlgorithm = + in->securityAlgorithm.integrityProtectionAlgorithm == NULL ? 0 : *in->securityAlgorithm.integrityProtectionAlgorithm; + + // User Plane Security Keys (M) (9.3.1.32) + // Encryption Key (M) + _E1_EQ_CHECK_INT((int)in->uPSecuritykey.encryptionKey.size, E1AP_SECURITY_KEY_SIZE); memcpy(out->encryptionKey, in->uPSecuritykey.encryptionKey.buf, in->uPSecuritykey.encryptionKey.size); - if (in->securityAlgorithm.integrityProtectionAlgorithm) - out->integrityProtectionAlgorithm = *in->securityAlgorithm.integrityProtectionAlgorithm; + // Integrity Protection Key (O) if (in->uPSecuritykey.integrityProtectionKey) { E1AP_IntegrityProtectionKey_t *ipKey = in->uPSecuritykey.integrityProtectionKey; - memcpy(out->integrityProtectionKey, ipKey->buf, ipKey->size); + _E1_EQ_CHECK_INT((int)ipKey->size, E1AP_SECURITY_KEY_SIZE); + memcpy(out->integrityProtectionKey, ipKey->buf, E1AP_SECURITY_KEY_SIZE); + } else { + memset(out->integrityProtectionKey, 0, E1AP_SECURITY_KEY_SIZE); } + return true; } From 489e2ba4a4caf2f978745a156602008d3995a6c7 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 19 Feb 2025 12:46:45 +0100 Subject: [PATCH 06/10] Use E1 Bearer Context Modification Request lib in stack --- openair2/E1AP/e1ap.c | 225 ++----------------------------- openair2/RRC/NR/cucp_cuup_e1ap.c | 2 +- 2 files changed, 10 insertions(+), 217 deletions(-) diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 0b5582ea39..205c3725ef 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -427,103 +427,10 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upc return -1; } -/* - BEARER CONTEXT MODIFICATION REQUEST -*/ - -static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_mod_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu) -{ - pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu->choice.initiatingMessage, msg); - msg->procedureCode = E1AP_ProcedureCode_id_bearerContextModification; - msg->criticality = E1AP_Criticality_reject; - msg->value.present = E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest; - E1AP_BearerContextModificationRequest_t *out = &pdu->choice.initiatingMessage->value.choice.BearerContextModificationRequest; - /* mandatory */ - /* c1. gNB-CU-CP UE E1AP ID */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC1); - ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; - ieC1->criticality = E1AP_Criticality_reject; - ieC1->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; - ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = bearerCxt->gNB_cu_cp_ue_id; - /* mandatory */ - /* c2. gNB-CU-UP UE E1AP ID */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC2); - ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; - ieC2->criticality = E1AP_Criticality_reject; - ieC2->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; - ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = bearerCxt->gNB_cu_up_ue_id; - /* optional */ - /* Security Information */ - if (bearerCxt->secInfo) { - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ie); - ie->id = E1AP_ProtocolIE_ID_id_SecurityInformation; - ie->criticality = E1AP_Criticality_reject; - ie->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_SecurityInformation; - E1AP_SecurityAlgorithm_t *securityAlgorithm = &ie->value.choice.SecurityInformation.securityAlgorithm; - E1AP_UPSecuritykey_t *uPSecuritykey = &ie->value.choice.SecurityInformation.uPSecuritykey; - securityAlgorithm->cipheringAlgorithm = bearerCxt->secInfo->cipheringAlgorithm; - OCTET_STRING_fromBuf(&uPSecuritykey->encryptionKey, bearerCxt->secInfo->encryptionKey, E1AP_SECURITY_KEY_SIZE); - asn1cCallocOne(securityAlgorithm->integrityProtectionAlgorithm, bearerCxt->secInfo->integrityProtectionAlgorithm); - asn1cCalloc(uPSecuritykey->integrityProtectionKey, protKey); - OCTET_STRING_fromBuf(protKey, bearerCxt->secInfo->integrityProtectionKey, E1AP_SECURITY_KEY_SIZE); - } - /* optional */ - /* c3. E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC3); - ieC3->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest; - ieC3->criticality = E1AP_Criticality_reject; - ieC3->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest; - ieC3->value.choice.System_BearerContextModificationRequest.present = E1AP_System_BearerContextModificationRequest_PR_nG_RAN_BearerContextModificationRequest; - E1AP_ProtocolIE_Container_4932P26_t *msgNGRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P26_t)); - ieC3->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest = (struct E1AP_ProtocolIE_Container *) msgNGRAN_list; - asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextModificationRequest_t, msgNGRAN); - msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List; - msgNGRAN->criticality = E1AP_Criticality_reject; - msgNGRAN->value.present = E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List; - E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List; - for (pdu_session_to_mod_t *i = bearerCxt->pduSessionMod; i < bearerCxt->pduSessionMod + bearerCxt->numPDUSessionsMod; i++) { - asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Modify_Item_t, ieC3_1); - ieC3_1->pDU_Session_ID = i->sessionId; - for (DRB_nGRAN_to_mod_t *j = i->DRBnGRanModList; j < i->DRBnGRanModList + i->numDRB2Modify; j++) { - asn1cCalloc(ieC3_1->dRB_To_Modify_List_NG_RAN, drb2Mod_List); - asn1cSequenceAdd(drb2Mod_List->list, E1AP_DRB_To_Modify_Item_NG_RAN_t, drb2Mod); - drb2Mod->dRB_ID = j->id; - asn1cCalloc(drb2Mod->pDCP_Configuration, pDCP_Configuration); - if (j->pdcp_config && j->pdcp_config->pDCP_Reestablishment) { - asn1cCallocOne(pDCP_Configuration->pDCP_Reestablishment, E1AP_PDCP_Reestablishment_true); - } - if (j->numDlUpParam > 0) { - asn1cCalloc(drb2Mod->dL_UP_Parameters, DL_UP_Param_List); - for (up_params_t *k = j->DlUpParamList; k < j->DlUpParamList + j->numDlUpParam; k++) { - asn1cSequenceAdd(DL_UP_Param_List->list, E1AP_UP_Parameters_Item_t, DL_UP_Param); - DL_UP_Param->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; - asn1cCalloc(DL_UP_Param->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tl_info.tlAddress, &gTPTunnel->transportLayerAddress); - INT32_TO_OCTET_STRING(k->tl_info.teId, &gTPTunnel->gTP_TEID); - - DL_UP_Param->cell_Group_ID = k->cell_group_id; - } - } - } - } - /* c4. E1AP_ProtocolIE_ID_id_BearerContextStatusChange */ - if (bearerCxt->bearerContextStatus && *bearerCxt->bearerContextStatus == BEARER_SUSPEND) { - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC4); - ieC4->id = E1AP_ProtocolIE_ID_id_BearerContextStatusChange; - ieC4->criticality = E1AP_Criticality_reject; - ieC4->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange; - /* Bearer Context Status Change */ - ieC4->value.choice.BearerContextStatusChange = E1AP_BearerContextStatusChange_suspend; - } - return 0; -} - static void e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_bearer_mod_req_t *const bearerCxt) { - E1AP_E1AP_PDU_t pdu = {0}; - fill_BEARER_CONTEXT_MODIFICATION_REQUEST(bearerCxt, &pdu); - e1ap_encode_send(CPtype, assoc_id, &pdu, 0, __func__); + E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_mod_request(bearerCxt); + e1ap_encode_send(CPtype, assoc_id, pdu, 0, __func__); } static void fill_BEARER_CONTEXT_MODIFICATION_RESPONSE(const e1ap_bearer_modif_resp_t *resp, E1AP_E1AP_PDU_t *pdu) @@ -597,121 +504,6 @@ int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance) return -1; } -/** - * @brief Process E1AP PDU and extract Bearer Context Modification Request - */ -static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_mod_req_t *bearerCxt) -{ - const E1AP_BearerContextModificationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextModificationRequest; - E1AP_BearerContextModificationRequestIEs_t *ie; - - LOG_D(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count); - - for (int i = 0; i < in->protocolIEs.list.count; i++) { - ie = in->protocolIEs.list.array[i]; - - switch(ie->id) { - case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); - bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; - break; - - case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); - bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; - break; - - case E1AP_ProtocolIE_ID_id_SecurityInformation: { - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_SecurityInformation); - E1AP_SecurityInformation_t *sec = &ie->value.choice.SecurityInformation; - DevAssert(sec->uPSecuritykey.encryptionKey.size == E1AP_SECURITY_KEY_SIZE); - DevAssert(sec->uPSecuritykey.integrityProtectionKey == NULL - || sec->uPSecuritykey.integrityProtectionKey->size == E1AP_SECURITY_KEY_SIZE); - bearerCxt->secInfo = malloc_or_fail(sizeof(*bearerCxt->secInfo)); - bearerCxt->secInfo->cipheringAlgorithm = sec->securityAlgorithm.cipheringAlgorithm; - bearerCxt->secInfo->integrityProtectionAlgorithm = sec->securityAlgorithm.integrityProtectionAlgorithm == NULL - ? 0 - : *sec->securityAlgorithm.integrityProtectionAlgorithm; - memcpy(bearerCxt->secInfo->encryptionKey, sec->uPSecuritykey.encryptionKey.buf, E1AP_SECURITY_KEY_SIZE); - if (sec->securityAlgorithm.integrityProtectionAlgorithm == NULL) - memset(bearerCxt->secInfo->integrityProtectionKey, 0, E1AP_SECURITY_KEY_SIZE); - else - memcpy(bearerCxt->secInfo->integrityProtectionKey, sec->uPSecuritykey.integrityProtectionKey->buf, E1AP_SECURITY_KEY_SIZE); - break; - } - - case E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest); - DevAssert(ie->value.choice.System_BearerContextModificationRequest.present == - E1AP_System_BearerContextModificationRequest_PR_nG_RAN_BearerContextModificationRequest); - DevAssert(ie->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest != NULL); - E1AP_ProtocolIE_Container_4932P26_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P26_t *) ie->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest; - E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = msgNGRAN_list->list.array[0]; - DevAssert(msgNGRAN_list->list.count == 1); - DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List); - DevAssert(msgNGRAN->value.present = - E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List); - /* PDU Session Resource To Modify List (see 9.3.3.11 of TS 38.463) */ - E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2ModList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List; - bearerCxt->numPDUSessionsMod = pdu2ModList->list.count; - for (int i = 0; i < pdu2ModList->list.count; i++) { - pdu_session_to_mod_t *pdu_session = bearerCxt->pduSessionMod + i; - E1AP_PDU_Session_Resource_To_Modify_Item_t *pdu2Mod = pdu2ModList->list.array[i]; - pdu_session->sessionId = pdu2Mod->pDU_Session_ID; - E1AP_DRB_To_Modify_List_NG_RAN_t *drb2ModList = pdu2Mod->dRB_To_Modify_List_NG_RAN; - pdu_session->numDRB2Modify = drb2ModList->list.count; - /* DRBs to modify */ - for (int j = 0; j < drb2ModList->list.count; j++) { - DRB_nGRAN_to_mod_t *drb = pdu_session->DRBnGRanModList + j; - E1AP_DRB_To_Modify_Item_NG_RAN_t *drb2Mod = drb2ModList->list.array[j]; - drb->id = drb2Mod->dRB_ID; - if (drb2Mod->pDCP_Configuration != NULL - && drb2Mod->pDCP_Configuration->pDCP_Reestablishment != NULL - && *drb2Mod->pDCP_Configuration->pDCP_Reestablishment == E1AP_PDCP_Reestablishment_true) { - drb->pdcp_config = malloc_or_fail(sizeof(*drb->pdcp_config)); - drb->pdcp_config->pDCP_Reestablishment = true; - } - if (drb2Mod->dL_UP_Parameters) { /* Optional IE in the DRB To Modify Item */ - E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters; - drb->numDlUpParam = dl_up_paramList->list.count; - for (int k = 0; k < dl_up_paramList->list.count; k++) { - up_params_t *dl_up_param = drb->DlUpParamList + k; - E1AP_UP_Parameters_Item_t *dl_up_param_in = dl_up_paramList->list.array[k]; - if (dl_up_param_in->uP_TNL_Information.choice.gTPTunnel) { // Optional IE - DevAssert(dl_up_param_in->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel); - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4( - &dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->transportLayerAddress, - dl_up_param->tl_info.tlAddress); - OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->tl_info.teId); - } else { - AssertFatal(false, "gTPTunnel IE is missing. It is mandatory at this point\n"); - } - dl_up_param->cell_group_id = dl_up_param_in->cell_Group_ID; - } - } - } - } - break; - - case E1AP_ProtocolIE_ID_id_BearerContextStatusChange: - /* Bearer Context Status Change */ - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange); - bearerCxt->bearerContextStatus = malloc_or_fail(*bearerCxt->bearerContextStatus); - *bearerCxt->bearerContextStatus = (ie->value.choice.BearerContextStatusChange == E1AP_BearerContextStatusChange_suspend) ? BEARER_SUSPEND : BEARER_ACTIVE; - break; - - default: - LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); - break; - } - } -} - /** * @brief Extract Bearer Context Modification Request from E1AP PDU * and prepare Bearer Context Modification Response @@ -720,14 +512,14 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu) { - DevAssert(pdu != NULL); - DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage); - DevAssert(pdu->choice.initiatingMessage->procedureCode == E1AP_ProcedureCode_id_bearerContextModification); - DevAssert(pdu->choice.initiatingMessage->criticality == E1AP_Criticality_reject); - DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest); e1ap_bearer_mod_req_t bearerCxt = {0}; - extract_BEARER_CONTEXT_MODIFICATION_REQUEST(pdu, &bearerCxt); + if (!decode_E1_bearer_context_mod_request(pdu, &bearerCxt)) { + LOG_E(E1AP, "Failed to handle Bearer Context Modification Request\n"); + free_e1ap_context_mod_request(&bearerCxt); + return -1; + } e1_bearer_context_modif(&bearerCxt); + free_e1ap_context_mod_request(&bearerCxt); return 0; } @@ -1296,6 +1088,7 @@ void *E1AP_CUCP_task(void *arg) case E1AP_BEARER_CONTEXT_MODIFICATION_REQ: e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_MODIFICATION_REQ(msg)); + free_e1ap_context_mod_request(&E1AP_BEARER_CONTEXT_MODIFICATION_REQ(msg)); break; case E1AP_BEARER_CONTEXT_RELEASE_CMD: diff --git a/openair2/RRC/NR/cucp_cuup_e1ap.c b/openair2/RRC/NR/cucp_cuup_e1ap.c index 538cd3f524..fc98f8740d 100644 --- a/openair2/RRC/NR/cucp_cuup_e1ap.c +++ b/openair2/RRC/NR/cucp_cuup_e1ap.c @@ -44,7 +44,7 @@ static void cucp_cuup_bearer_context_mod_e1ap(sctp_assoc_t assoc_id, const e1ap_ MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_REQ); msg->ittiMsgHeader.originInstance = assoc_id; e1ap_bearer_mod_req_t *req_msg = &E1AP_BEARER_CONTEXT_MODIFICATION_REQ(msg); - memcpy(req_msg, req, sizeof(*req)); + *req_msg = cp_bearer_context_mod_request(req); itti_send_msg_to_task(TASK_CUCP_E1, 0, msg); } From c12c5bb5b1177a6d575a7ddcea81e0eed732507f Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Nov 2024 19:17:20 +0100 Subject: [PATCH 07/10] Add enc/dec library for E1 Bearer Context Modification Response --- openair2/COMMON/e1ap_messages_types.h | 19 + .../E1AP/lib/e1ap_bearer_context_management.c | 448 +++++++++++++++++- .../E1AP/lib/e1ap_bearer_context_management.h | 6 + openair2/E1AP/lib/e1ap_lib_includes.h | 13 + 4 files changed, 483 insertions(+), 3 deletions(-) diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index 2f59cb62d6..ccac11b19d 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -344,6 +344,7 @@ typedef enum qos_flow_mapping_indication_e { QF_BOTH } qos_flow_mapping_indication_t; +// 9.3.1.12 QoS Flow List typedef struct qos_flow_list_s { long qfi; // qos flow identifier qos_flow_mapping_indication_t *indication; @@ -517,6 +518,12 @@ typedef struct e1ap_bearer_release_cplt_s { uint32_t gNB_cu_up_ue_id; } e1ap_bearer_release_cplt_t; +// 9.3.1.45 Flow Failed List +typedef struct qos_flow_failed_s { + long qfi; + e1ap_cause_t cause; +} qos_flow_failed_t; + typedef struct DRB_nGRAN_setup_s { // DRB ID (M) long id; @@ -525,6 +532,9 @@ typedef struct DRB_nGRAN_setup_s { // Flow Setup List (M) int numQosFlowSetup; qos_flow_list_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; + // Flow Failed List (O) + int numQosFlowFailed; + qos_flow_failed_t qosFlowsFailed[E1AP_MAX_NUM_QOS_FLOWS]; } DRB_nGRAN_setup_t; /* DRB Modified Item */ @@ -537,6 +547,9 @@ typedef struct DRB_nGRAN_modified_s { // Flow Setup List (O) int numQosFlowSetup; qos_flow_list_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; + // Flow Failed List (O) + int numQosFlowFailed; + qos_flow_failed_t qosFlowsFailed[E1AP_MAX_NUM_QOS_FLOWS]; // Old QoS Flow List (O) int numOldQosFlow; qos_flow_list_t oldQosFlows[E1AP_MAX_NUM_QOS_FLOWS]; @@ -569,9 +582,15 @@ typedef struct pdu_session_modif_s { // DRB Modified List (O) int numDRBModified; DRB_nGRAN_modified_t DRBnGRanModList[E1AP_MAX_NUM_DRBS]; + // DRB Failed to Modify List (O) + int numDRBFailedToMod; + DRB_nGRAN_failed_t DRBnGRanFailedModList[E1AP_MAX_NUM_DRBS]; // DRB Setup List (O) int numDRBSetup; DRB_nGRAN_setup_t DRBnGRanSetupList[E1AP_MAX_NUM_DRBS]; + // DRB Failed List (O) + int numDRBFailed; + DRB_nGRAN_failed_t DRBnGRanFailedList[E1AP_MAX_NUM_DRBS]; } pdu_session_modif_t; typedef struct e1ap_bearer_setup_resp_s { diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index b200813ddc..628fb00cda 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -782,6 +782,26 @@ bool eq_bearer_context_setup_request(const e1ap_bearer_setup_req_t *a, const e1a return true; } +/** Decode DRB Failed Item. Applies to both E1AP_DRB_Failed_To_Modify_Item_NG_RAN_t + * and E1AP_DRB_Failed_Item_NG_RAN_t */ +static void decode_drb_failed_item(DRB_nGRAN_failed_t *out, const E1AP_DRB_Failed_Item_NG_RAN_t *in) +{ + // DRB ID (M) + out->id = in->dRB_ID; + // Cause (M) + out->cause = e1_decode_cause_ie(&in->cause); +} + +/** Encode DRB Failed Item. Applies to both E1AP_DRB_Failed_To_Modify_Item_NG_RAN_t + * and E1AP_DRB_Failed_Item_NG_RAN_t */ +static void encode_drb_failed_item(E1AP_DRB_Failed_Item_NG_RAN_t *out, const DRB_nGRAN_failed_t *in) +{ + // DRB ID (M) + out->dRB_ID = in->id; + // Cause (M) + out->cause = e1_encode_cause_ie(&in->cause); +} + /* ====================================== * E1AP Bearer Context Setup Response * ====================================== */ @@ -1047,8 +1067,8 @@ bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e const DRB_nGRAN_failed_t *drbf_a = &ps_a->DRBnGRanFailedList[j]; const DRB_nGRAN_failed_t *drbf_b = &ps_b->DRBnGRanFailedList[j]; _E1_EQ_CHECK_LONG(drbf_a->id, drbf_b->id); - _E1_EQ_CHECK_LONG(drbf_a->cause.type, drbf_b->cause.type); - _E1_EQ_CHECK_LONG(drbf_a->cause.value, drbf_b->cause.value); + _E1_EQ_CHECK_INT(drbf_a->cause.type, drbf_b->cause.type); + _E1_EQ_CHECK_INT(drbf_a->cause.value, drbf_b->cause.value); } } return true; @@ -1507,7 +1527,7 @@ bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_beare } default: - PRINT_ERROR("System Bearer Context Modification Request: this IE is not implemented (or) invalid IE detected\n"); + PRINT_ERROR("%s: handle for this IE %ld is not implemented (or) invalid IE detected\n", __func__, ie->id); return false; break; } @@ -1693,3 +1713,425 @@ void free_e1ap_context_mod_request(const e1ap_bearer_mod_req_t *msg) for (int i = 0; i < msg->numPDUSessionsMod; i++) free_pdu_session_to_mod_item(&msg->pduSessionMod[i]); } + +/* ============================================ + * E1AP Bearer Context Modification Response + * ============================================ */ + +/** Encode QoS Flow Item (9.3.1.12 3GPP TS 38.463) */ +static void encode_qos_flow_failed_item(E1AP_QoS_Flow_Failed_Item_t *out, const qos_flow_failed_t *in) +{ + // QFI (M) + out->qoS_Flow_Identifier = in->qfi; + // Cause (M) + out->cause = e1_encode_cause_ie(&in->cause); +} + +/** + * @brief Bearer Context Modification Response encoding (9.2.2.5 3GPP TS 38.463) + * gNB-CU-UP → gNB-CU-CP + */ +struct E1AP_E1AP_PDU *encode_E1_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *msg) +{ + E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, type); + type->procedureCode = E1AP_ProcedureCode_id_bearerContextModification; + type->criticality = E1AP_Criticality_reject; + type->value.present = E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse; + E1AP_BearerContextModificationResponse_t *out = &pdu->choice.successfulOutcome->value.choice.BearerContextModificationResponse; + // gNB-CU-CP UE E1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ie1); + ie1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ie1->criticality = E1AP_Criticality_reject; + ie1->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ie1->value.choice.GNB_CU_CP_UE_E1AP_ID = msg->gNB_cu_cp_ue_id; + // gNB-CU-UP UE E1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ie2); + ie2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; + ie2->criticality = E1AP_Criticality_reject; + ie2->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; + ie2->value.choice.GNB_CU_UP_UE_E1AP_ID = msg->gNB_cu_up_ue_id; + // NG-RAN PDU Session Resource Modified List (O) + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ie3); + ie3->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse; + ie3->criticality = E1AP_Criticality_ignore; + // CHOICE System (O) + ie3->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse; + E1AP_System_BearerContextModificationResponse_t *sys = &ie3->value.choice.System_BearerContextModificationResponse; + // NG-RAN + E1AP_ProtocolIE_Container_4932P29_t *ngran = calloc_or_fail(1, sizeof(*ngran)); + sys->present = E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse; + sys->choice.nG_RAN_BearerContextModificationResponse = (struct E1AP_ProtocolIE_Container *)ngran; + asn1cSequenceAdd(ngran->list, E1AP_NG_RAN_BearerContextModificationResponse_t, list); + // PDU Session Resource Modified List (O) + list->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List; + list->criticality = E1AP_Criticality_reject; + list->value.present = E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List; + E1AP_PDU_Session_Resource_Modified_List_t *pdu_mod_l = &list->value.choice.PDU_Session_Resource_Modified_List; + for (int i = 0; i < msg->numPDUSessionsMod; ++i) { + // PDU Session Resource Modified Item (1..maxnoofPDUSessionResource) + const pdu_session_modif_t *pdu = &msg->pduSessionMod[i]; + asn1cSequenceAdd(pdu_mod_l->list, E1AP_PDU_Session_Resource_Modified_Item_t, iePdu); + // PDU Session ID (M) + iePdu->pDU_Session_ID = pdu->id; + // Security Result (O) + if (pdu->confidentialityProtectionIndication || pdu->integrityProtectionIndication) { + iePdu->securityResult = calloc_or_fail(1, sizeof(*iePdu->securityResult)); + if (pdu->confidentialityProtectionIndication) + iePdu->securityResult->confidentialityProtectionResult = *pdu->confidentialityProtectionIndication; + if (pdu->integrityProtectionIndication) + iePdu->securityResult->integrityProtectionResult = *pdu->integrityProtectionIndication; + } + // NG DL UP Transport Layer Information (O) + if (pdu->ng_DL_UP_TL_info) { + iePdu->nG_DL_UP_TNL_Information = calloc_or_fail(1, sizeof(*iePdu->nG_DL_UP_TNL_Information)); + *iePdu->nG_DL_UP_TNL_Information = e1_encode_up_tnl_info(pdu->ng_DL_UP_TL_info); + } + // DRB Modified List (O) + if (pdu->numDRBModified > 0) { + iePdu->dRB_Modified_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Modified_List_NG_RAN)); + E1AP_DRB_Modified_List_NG_RAN_t *drb_mod_l = iePdu->dRB_Modified_List_NG_RAN; + for (int j = 0; j < pdu->numDRBModified; ++j) { + const DRB_nGRAN_modified_t *drb = &pdu->DRBnGRanModList[j]; + asn1cSequenceAdd(drb_mod_l->list, E1AP_DRB_Modified_Item_NG_RAN_t, drb_mod); + // DRB ID (M) + drb_mod->dRB_ID = drb->id; + // Flow Setup List (O) + if (drb->numQosFlowSetup) + drb_mod->flow_Setup_List = calloc_or_fail(1, sizeof(*drb_mod->flow_Setup_List)); + for (int q = 0; q < drb->numQosFlowSetup; ++q) { + asn1cSequenceAdd(drb_mod->flow_Setup_List->list, E1AP_QoS_Flow_Item_t, qos_mod); + qos_mod->qoS_Flow_Identifier = drb->qosFlows[q].qfi; + } + // Flow Failed List (O) + if (drb->numQosFlowFailed) + drb_mod->flow_Failed_List = calloc_or_fail(1, sizeof(*drb_mod->flow_Failed_List)); + for (int q = 0; q < drb->numQosFlowFailed; ++q) { + asn1cSequenceAdd(drb_mod->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail); + encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]); + } + // UL UP Parameters (O) + if (drb->numUpParam) + drb_mod->uL_UP_Transport_Parameters = calloc_or_fail(1, sizeof(*drb_mod->uL_UP_Transport_Parameters)); + for (const up_params_t *k = drb->ul_UP_Params; k < drb->ul_UP_Params + drb->numUpParam; k++) { + asn1cSequenceAdd(drb_mod->uL_UP_Transport_Parameters->list, E1AP_UP_Parameters_Item_t, up); + up->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info); + up->cell_Group_ID = k->cell_group_id; + } + } + } + // DRB Failed To Modify List (O) + if (pdu->numDRBFailedToMod > 0) { + iePdu->dRB_Failed_To_Modify_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Failed_To_Modify_List_NG_RAN)); + E1AP_DRB_Failed_To_Modify_List_NG_RAN_t *ngran = iePdu->dRB_Failed_To_Modify_List_NG_RAN; + for (int j = 0; j < pdu->numDRBFailedToMod; ++j) { + const DRB_nGRAN_failed_t *drb = &pdu->DRBnGRanFailedModList[j]; + asn1cSequenceAdd(ngran->list, E1AP_DRB_Failed_To_Modify_Item_NG_RAN_t, fail_to_mod); + encode_drb_failed_item((E1AP_DRB_Failed_Item_NG_RAN_t *)fail_to_mod, drb); + } + } + // DRB Setup List (O) + if (pdu->numDRBSetup > 0) { + iePdu->dRB_Setup_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Setup_List_NG_RAN)); + E1AP_DRB_Setup_List_NG_RAN_t *drb_setup = iePdu->dRB_Setup_List_NG_RAN; + for (int j = 0; j < pdu->numDRBModified; ++j) { + const DRB_nGRAN_setup_t *drb = &pdu->DRBnGRanSetupList[j]; + asn1cSequenceAdd(drb_setup->list, E1AP_DRB_Setup_Item_NG_RAN_t, item); + // DRB ID (M) + item->dRB_ID = drb->id; + // UL UP Parameters (M) + for (const up_params_t *k = drb->UpParamList; k < drb->UpParamList + drb->numUpParam; k++) { + asn1cSequenceAdd(item->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, up); + up->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info); + up->cell_Group_ID = drb->UpParamList->cell_group_id; + } + // Flow Setup List (M) + for (int q = 0; q < drb->numQosFlowSetup; ++q) { + asn1cSequenceAdd(item->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, qos); + qos->qoS_Flow_Identifier = drb->qosFlows[q].qfi; + } + // Flow Failed List (O) + if (drb->numQosFlowFailed) + item->flow_Failed_List = calloc_or_fail(1, sizeof(*item->flow_Failed_List)); + for (int q = 0; q < drb->numQosFlowFailed; ++q) { + asn1cSequenceAdd(item->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail); + encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]); + } + } + } + // DRB Failed List (O) + if (pdu->numDRBFailed) { + iePdu->dRB_Failed_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Failed_List_NG_RAN)); + E1AP_DRB_Failed_List_NG_RAN_t *ngran = iePdu->dRB_Failed_List_NG_RAN; + for (int j = 0; j < pdu->numDRBFailed; ++j) { + const DRB_nGRAN_failed_t *drb = &pdu->DRBnGRanFailedList[j]; + asn1cSequenceAdd(ngran->list, E1AP_DRB_Failed_Item_NG_RAN_t, fail); + encode_drb_failed_item(fail, drb); + } + } + } + return pdu; +} + +/** Decode QoS Flow Item (9.3.1.12 3GPP TS 38.463) */ +static qos_flow_failed_t decode_qos_flow_failed_item(const E1AP_QoS_Flow_Failed_Item_t *in) +{ + qos_flow_failed_t out = {0}; + // QFI (M) + out.qfi = in->qoS_Flow_Identifier; + // Cause (M) + out.cause = e1_decode_cause_ie(&in->cause); + return out; +} + +/** + * @brief Bearer Context Modification Response decoding (9.2.2.5 3GPP TS 38.463) + * gNB-CU-UP → gNB-CU-CP + */ +bool decode_E1_bearer_context_mod_response(e1ap_bearer_modif_resp_t *out, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + _E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome); + E1AP_SuccessfulOutcome_t *type = pdu->choice.successfulOutcome; + _E1_EQ_CHECK_LONG(type->procedureCode, E1AP_ProcedureCode_id_bearerContextModification); + _E1_EQ_CHECK_INT(type->value.present, E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse); + const E1AP_BearerContextModificationResponse_t *in = &type->value.choice.BearerContextModificationResponse; + // Check mandatory IEs first + E1AP_BearerContextModificationResponseIEs_t *ie; + E1AP_LIB_FIND_IE(E1AP_BearerContextModificationResponseIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID, true); + E1AP_LIB_FIND_IE(E1AP_BearerContextModificationResponseIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID, true); + // Process all IEs + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + // gNB-CU-CP UE E1AP ID (M) + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + out->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: + // gNB-CU-UP UE E1AP ID (M) + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); + out->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse: + // CHOICE System (O) + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse); + // NG-RAN System + E1AP_System_BearerContextModificationResponse_t *system = &ie->value.choice.System_BearerContextModificationResponse; + _E1_EQ_CHECK_INT(system->present, E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse); + // NG-RAN List + E1AP_ProtocolIE_Container_4932P29_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P29_t *)system->choice.nG_RAN_BearerContextModificationResponse; + _E1_EQ_CHECK_INT(msgNGRAN_list->list.count, 1); + E1AP_NG_RAN_BearerContextModificationResponse_t *msgNGRAN = msgNGRAN_list->list.array[0]; + _E1_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List); + _E1_EQ_CHECK_INT(msgNGRAN->value.present, E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List); + // PDU Session Resource Modified list (O) + E1AP_PDU_Session_Resource_Modified_List_t *list = &msgNGRAN->value.choice.PDU_Session_Resource_Modified_List; + out->numPDUSessionsMod = list->list.count; + for (int i = 0; i < list->list.count; i++) { + // PDU Session Resource Modified item (1..maxnoofPDUSessionResource) + pdu_session_modif_t *pduModified = &out->pduSessionMod[i]; + E1AP_PDU_Session_Resource_Modified_Item_t *pduIE = list->list.array[i]; + // PDU Session ID (M) + pduModified->id = pduIE->pDU_Session_ID; + // NG DL UP Transport Layer Information (O) + if (pduIE->nG_DL_UP_TNL_Information) { + pduModified->ng_DL_UP_TL_info = malloc_or_fail(sizeof(*pduModified->ng_DL_UP_TL_info)); + e1_decode_up_tnl_info(pduModified->ng_DL_UP_TL_info, pduIE->nG_DL_UP_TNL_Information); + } + // Security Result (O) + if (pduIE->securityResult) { + pduModified->confidentialityProtectionIndication = malloc_or_fail(sizeof(*pduModified->confidentialityProtectionIndication)); + *pduModified->confidentialityProtectionIndication = pduIE->securityResult->confidentialityProtectionResult; + pduModified->integrityProtectionIndication = malloc_or_fail(sizeof(*pduModified->integrityProtectionIndication)); + *pduModified->integrityProtectionIndication = pduIE->securityResult->integrityProtectionResult; + } + // DRB Setup list + if (pduIE->dRB_Setup_List_NG_RAN) { + pduModified->numDRBSetup = pduIE->dRB_Setup_List_NG_RAN->list.count; + for (int j = 0; j < pduIE->dRB_Setup_List_NG_RAN->list.count; j++) { + // DRB Setup item + DRB_nGRAN_setup_t *drbMod = &pduModified->DRBnGRanSetupList[j]; + E1AP_DRB_Setup_Item_NG_RAN_t *drbIE = pduIE->dRB_Setup_List_NG_RAN->list.array[j]; + drbMod->id = drbIE->dRB_ID; + // UL UP Parameters (M) + if (drbIE->uL_UP_Transport_Parameters.list.count) { + drbMod->numUpParam = decode_dl_up_parameters(drbMod->UpParamList, &drbIE->uL_UP_Transport_Parameters); + } + // Flow Setup List (O) + if (drbIE->flow_Failed_List) { + drbMod->numQosFlowFailed = drbIE->flow_Failed_List->list.count; + for (int i = 0; i < drbMod->numQosFlowSetup; i++) { + drbMod->qosFlowsFailed[i] = decode_qos_flow_failed_item(drbIE->flow_Failed_List->list.array[i]); + } + } + // Flow Setup List (M) + if (drbIE->flow_Setup_List.list.count) { + drbMod->numQosFlowSetup = drbIE->flow_Setup_List.list.count; + for (int i = 0; i < drbMod->numQosFlowSetup; i++) + drbMod->qosFlows[i].qfi = drbIE->flow_Setup_List.list.array[i]->qoS_Flow_Identifier; + } + } + } + // DRB Failed list + if (pduIE->dRB_Failed_List_NG_RAN) { + pduModified->numDRBFailed = pduIE->dRB_Failed_List_NG_RAN->list.count; + for (int j = 0; j < pduIE->dRB_Failed_List_NG_RAN->list.count; j++) { + decode_drb_failed_item(&pduModified->DRBnGRanFailedList[j], pduIE->dRB_Failed_List_NG_RAN->list.array[j]); + } + } + // DRB Modified list (0..1) + if (pduIE->dRB_Modified_List_NG_RAN) { + pduModified->numDRBModified = pduIE->dRB_Modified_List_NG_RAN->list.count; + for (int j = 0; j < pduIE->dRB_Modified_List_NG_RAN->list.count; j++) { + // DRB Modified item + DRB_nGRAN_modified_t *drbMod = &pduModified->DRBnGRanModList[j]; + E1AP_DRB_Modified_Item_NG_RAN_t *drbIE = pduIE->dRB_Modified_List_NG_RAN->list.array[j]; + // DRB ID (M) + drbMod->id = drbIE->dRB_ID; + // UL UP Parameters (O) + if (drbIE->uL_UP_Transport_Parameters) { + drbMod->numUpParam = decode_dl_up_parameters(drbMod->ul_UP_Params, drbIE->uL_UP_Transport_Parameters); + } + // Flow Setup List (O) + if (drbIE->flow_Setup_List) { + drbMod->numQosFlowSetup = drbIE->flow_Setup_List->list.count; + for (int i = 0; i < drbMod->numQosFlowSetup; i++) + drbMod->qosFlows[i].qfi = drbIE->flow_Setup_List->list.array[i]->qoS_Flow_Identifier; + } + // Flow Failed List (O) + if (drbIE->flow_Failed_List) { + drbMod->numQosFlowFailed = drbIE->flow_Failed_List->list.count; + for (int i = 0; i < drbMod->numQosFlowFailed; i++) { + drbMod->qosFlowsFailed[i] = decode_qos_flow_failed_item(drbIE->flow_Failed_List->list.array[i]); + } + } + } + } + // DRB Failed to Mod list + if (pduIE->dRB_Failed_To_Modify_List_NG_RAN) { + pduModified->numDRBFailedToMod = pduIE->dRB_Failed_To_Modify_List_NG_RAN->list.count; + for (int j = 0; j < pduIE->dRB_Failed_To_Modify_List_NG_RAN->list.count; j++) { + decode_drb_failed_item(&pduModified->DRBnGRanFailedModList[j], + (E1AP_DRB_Failed_Item_NG_RAN_t *)pduIE->dRB_Failed_To_Modify_List_NG_RAN->list.array[j]); + } + } + } + break; + } + } + return true; +} + +/** @brief Deep copy for PDU Session Modified Item */ +static pdu_session_modif_t cp_pdu_session_mod_item(const pdu_session_modif_t *msg) +{ + pdu_session_modif_t cp = {0}; + // shallow copy + cp = *msg; + // Optional IE + _E1_CP_OPTIONAL_IE(&cp, msg, integrityProtectionIndication); + _E1_CP_OPTIONAL_IE(&cp, msg, confidentialityProtectionIndication); + _E1_CP_OPTIONAL_IE(&cp, msg, ng_DL_UP_TL_info); + return cp; +} + +/** @brief Deep copy for Bearer Context Modification Response */ +e1ap_bearer_modif_resp_t cp_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *msg) +{ + e1ap_bearer_modif_resp_t cp = {0}; + // Shallow copy + cp = *msg; + // Deep copy PDU sessions modified items + for (int i = 0; i < msg->numPDUSessionsMod; i++) + cp.pduSessionMod[i] = cp_pdu_session_mod_item(&msg->pduSessionMod[i]); + return cp; +} + +/** + * @brief E1AP Bearer Modification Response equality check + */ +bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1ap_bearer_modif_resp_t *b) +{ + if (!a || !b) return false; // Null-check both inputs + + // Basic members + _E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id); + _E1_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id); + _E1_EQ_CHECK_INT(a->numPDUSessionsMod, b->numPDUSessionsMod); + + // PDU Session Modified List + for (int i = 0; i < a->numPDUSessionsMod; i++) { + const pdu_session_modif_t *pduA = &a->pduSessionMod[i]; + const pdu_session_modif_t *pduB = &b->pduSessionMod[i]; + + _E1_EQ_CHECK_LONG(pduA->id, pduB->id); + _E1_EQ_CHECK_OPTIONAL_IE(pduA, pduB, confidentialityProtectionIndication, _E1_EQ_CHECK_INT); + _E1_EQ_CHECK_OPTIONAL_IE(pduA, pduB, integrityProtectionIndication, _E1_EQ_CHECK_INT); + + _E1_EQ_CHECK_OPTIONAL_PTR(pduA, pduB, ng_DL_UP_TL_info); + if (pduA->ng_DL_UP_TL_info && pduB->ng_DL_UP_TL_info) + eq_up_tl_info(pduA->ng_DL_UP_TL_info, pduB->ng_DL_UP_TL_info); + + // DRB Modified List + _E1_EQ_CHECK_INT(pduA->numDRBModified, pduB->numDRBModified); + for (int j = 0; j < pduA->numDRBModified; j++) { + const DRB_nGRAN_modified_t *drbModA = &pduA->DRBnGRanModList[j]; + const DRB_nGRAN_modified_t *drbModB = &pduB->DRBnGRanModList[j]; + _E1_EQ_CHECK_LONG(drbModA->id, drbModB->id); + _E1_EQ_CHECK_INT(drbModA->numQosFlowSetup, drbModB->numQosFlowSetup); + for (int j = 0; j < drbModA->numQosFlowSetup; j++) { + _E1_EQ_CHECK_LONG(drbModA->qosFlows[j].qfi, drbModB->qosFlows[j].qfi); + } + } + + // DRB Failed to Modify List + _E1_EQ_CHECK_INT(pduA->numDRBFailedToMod, pduB->numDRBFailedToMod); + for (int j = 0; j < pduA->numDRBFailedToMod; j++) { + _E1_EQ_CHECK_LONG(pduA->DRBnGRanFailedModList[j].id, pduB->DRBnGRanFailedModList[j].id); + _E1_EQ_CHECK_INT(pduA->DRBnGRanFailedModList[j].cause.value, pduB->DRBnGRanFailedModList[j].cause.value); + _E1_EQ_CHECK_INT(pduA->DRBnGRanFailedModList[j].cause.type, pduB->DRBnGRanFailedModList[j].cause.type); + } + + // DRB Setup List + _E1_EQ_CHECK_INT(pduA->numDRBSetup, pduB->numDRBSetup); + for (int j = 0; j < pduA->numDRBSetup; j++) { + const DRB_nGRAN_setup_t *drbSetupA = &pduA->DRBnGRanSetupList[j]; + const DRB_nGRAN_setup_t *drbSetupB = &pduB->DRBnGRanSetupList[j]; + + _E1_EQ_CHECK_LONG(drbSetupA->id, drbSetupB->id); + _E1_EQ_CHECK_INT(drbSetupA->numQosFlowSetup, drbSetupB->numQosFlowSetup); + for (int j = 0; j < drbSetupA->numQosFlowSetup; j++) { + _E1_EQ_CHECK_LONG(drbSetupA->qosFlows[j].qfi, drbSetupB->qosFlows[j].qfi); + } + } + + // DRB Failed to Setup List + _E1_EQ_CHECK_INT(pduA->numDRBFailed, pduB->numDRBFailed); + for (int j = 0; j < pduA->numDRBFailed; j++) { + _E1_EQ_CHECK_LONG(pduA->DRBnGRanFailedList[j].id, pduB->DRBnGRanFailedList[j].id); + _E1_EQ_CHECK_INT(pduA->DRBnGRanFailedList[j].cause.value, pduB->DRBnGRanFailedList[j].cause.value); + _E1_EQ_CHECK_INT(pduA->DRBnGRanFailedList[j].cause.type, pduB->DRBnGRanFailedList[j].cause.type); + } + + } + + return true; +} + +/** + * @brief E1AP Bearer Context Modification Response memory management + */ +void free_e1ap_context_mod_response(const e1ap_bearer_modif_resp_t *msg) +{ + for (int i = 0; i < msg->numPDUSessionsMod; i++) { + free(msg->pduSessionMod[i].confidentialityProtectionIndication); + free(msg->pduSessionMod[i].integrityProtectionIndication); + free(msg->pduSessionMod[i].ng_DL_UP_TL_info); + } +} diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.h b/openair2/E1AP/lib/e1ap_bearer_context_management.h index 132c1857e1..fb8c57e011 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.h +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.h @@ -46,4 +46,10 @@ void free_e1ap_context_mod_request(const e1ap_bearer_mod_req_t *msg); e1ap_bearer_mod_req_t cp_bearer_context_mod_request(const e1ap_bearer_mod_req_t *msg); bool eq_bearer_context_mod_request(const e1ap_bearer_mod_req_t *a, const e1ap_bearer_mod_req_t *b); +struct E1AP_E1AP_PDU *encode_E1_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *msg); +bool decode_E1_bearer_context_mod_response(e1ap_bearer_modif_resp_t *out, const struct E1AP_E1AP_PDU *pdu); +void free_e1ap_context_mod_response(const e1ap_bearer_modif_resp_t *msg); +e1ap_bearer_modif_resp_t cp_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *msg); +bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1ap_bearer_modif_resp_t *b); + #endif /* E1AP_BEARER_CONTEXT_MANAGEMENT_H_ */ diff --git a/openair2/E1AP/lib/e1ap_lib_includes.h b/openair2/E1AP/lib/e1ap_lib_includes.h index 46d09f5aa9..028993e6fd 100644 --- a/openair2/E1AP/lib/e1ap_lib_includes.h +++ b/openair2/E1AP/lib/e1ap_lib_includes.h @@ -41,6 +41,11 @@ #include "E1AP_Cell-Group-Information-Item.h" #include "E1AP_Dynamic5QIDescriptor.h" #include "E1AP_Non-Dynamic5QIDescriptor.h" +#include "E1AP_SecurityResult.h" +#include "E1AP_Data-Forwarding-Information.h" +#include "E1AP_PDCP-SN-Status-Information.h" +#include "E1AP_PDCP-Count.h" + // E1 Bearer Context Setup Request #include "E1AP_BearerContextSetupRequest.h" #include "E1AP_GNB-CU-CP-E1SetupRequest.h" @@ -73,5 +78,13 @@ #include "E1AP_DRB-To-Modify-Item-NG-RAN.h" #include "E1AP_PDU-Session-Resource-To-Setup-Mod-Item.h" #include "E1AP_DRB-To-Setup-Mod-Item-NG-RAN.h" +// E1 Bearer Context Modification Response +#include "E1AP_PDU-Session-Resource-Modified-Item.h" +#include "E1AP_DRB-Modified-List-NG-RAN.h" +#include "E1AP_DRB-Modified-Item-NG-RAN.h" +#include "E1AP_DRB-Failed-To-Modify-List-NG-RAN.h" +#include "E1AP_QoS-Flow-Failed-List.h" +#include "E1AP_QoS-Flow-Failed-Item.h" +#include "E1AP_DRB-Failed-To-Modify-Item-NG-RAN.h" #endif /* E1AP_LIB_INCLUDES_H_ */ From 906b564ed065e407d008fac3963bcc928e7422aa Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 3 Dec 2024 23:21:19 +0100 Subject: [PATCH 08/10] Add unit tests for Bearer Context Modification Response One for successful setup and the other for setup failure. --- openair2/E1AP/tests/e1ap_lib_test.c | 166 ++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/openair2/E1AP/tests/e1ap_lib_test.c b/openair2/E1AP/tests/e1ap_lib_test.c index 59e6f08e66..68ce89cae1 100644 --- a/openair2/E1AP/tests/e1ap_lib_test.c +++ b/openair2/E1AP/tests/e1ap_lib_test.c @@ -453,6 +453,170 @@ static void test_bearer_context_modification_request(void) free_e1ap_context_mod_request(&orig); } +const e1ap_cause_t dummy_cause = { + .value = E1AP_RADIO_CAUSE_UNSPECIFIED, + .type = E1AP_CAUSE_RADIO_NETWORK, +}; + +const DRB_nGRAN_failed_t dummy_drb_failed = { + .id = 2, + .cause.value = E1AP_RADIO_CAUSE_UNKNOWN_DRB_ID, + .cause.type = E1AP_CAUSE_RADIO_NETWORK, +}; + +/** + * @brief Test E1AP Bearer Context Modification Response encoding/decoding + */ +static void test_bearer_context_modification_response(void) +{ + // DRB Modified List + DRB_nGRAN_modified_t drb_mod = { + .id = 1, + .numQosFlowSetup = 1, + .qosFlows[0].qfi = 1, + }; + + // DRB Setup List + DRB_nGRAN_setup_t setup = { + .id = 1, + .numUpParam = 1, + .UpParamList[0].cell_group_id = MCG, + .UpParamList[0].tl_info = create_up_tl_info(), + .numQosFlowSetup = 1, + .qosFlows[0].qfi = 1, + .numQosFlowFailed = 1, + .qosFlowsFailed[0].qfi = 9, + .qosFlowsFailed[0].cause = dummy_cause, + }; + + // PDU Session Modified + pdu_session_modif_t pdu_mod = { + .id = 1, + .integrityProtectionIndication = malloc_or_fail(sizeof(*pdu_mod.integrityProtectionIndication)), + .confidentialityProtectionIndication = malloc_or_fail(sizeof(*pdu_mod.confidentialityProtectionIndication)), + .ng_DL_UP_TL_info = malloc_or_fail(sizeof(*pdu_mod.ng_DL_UP_TL_info)), + .numDRBModified = 1, + .DRBnGRanModList[0] = drb_mod, + .numDRBFailedToMod = 1, + .DRBnGRanFailedModList[0] = dummy_drb_failed, + .numDRBSetup = 1, + .DRBnGRanSetupList[0] = setup, + .numDRBFailed = 1, + .DRBnGRanFailedList[0] = dummy_drb_failed, + }; + + *pdu_mod.integrityProtectionIndication = SECURITY_PREFERRED; + *pdu_mod.confidentialityProtectionIndication = SECURITY_PREFERRED; + *pdu_mod.ng_DL_UP_TL_info = create_up_tl_info(); + + e1ap_bearer_modif_resp_t orig = { + .gNB_cu_cp_ue_id = 0x1234, + .gNB_cu_up_ue_id = 0x5678, + .numPDUSessionsMod = 1, + .pduSessionMod[0] = pdu_mod, + }; + + // Encode the original message + E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_mod_response(&orig); + + // Decode the encoded message + E1AP_E1AP_PDU_t *dec = e1ap_encode_decode(enc); + + // Free the encoded message + e1ap_msg_free(enc); + + // Decode the message into a new struct + e1ap_bearer_modif_resp_t decoded = {0}; + bool ret = decode_E1_bearer_context_mod_response(&decoded, dec); + AssertFatal(ret, "decode_E1_bearer_context_mod_response(): could not decode message\n"); + + // Free the decoded E1AP message + e1ap_msg_free(dec); + + // Compare the original and decoded structs + ret = eq_bearer_context_mod_response(&orig, &decoded); + AssertFatal(ret, "eq_bearer_context_mod_response(): decoded message doesn't match\n"); + + // Free the memory for the decoded message + free_e1ap_context_mod_response(&decoded); + + // Deep copy the original message + e1ap_bearer_modif_resp_t cp = cp_bearer_context_mod_response(&orig); + + // Verify the deep copy matches the original + ret = eq_bearer_context_mod_response(&orig, &cp); + AssertFatal(ret, "eq_bearer_context_mod_response(): copied message doesn't match\n"); + + // Free the copied and original message + free_e1ap_context_mod_response(&cp); + free_e1ap_context_mod_response(&orig); +} + +/** @brief Test E1AP Bearer Context Modification Response encoding/decoding + * with failed DRBs (setup and modification) */ +static void test_bearer_context_modification_response_fail(void) +{ + const e1ap_cause_t cause = { + .value = E1AP_PROTOCOL_CAUSE_SEMANTIC_ERROR, + .type = E1AP_CAUSE_PROTOCOL, + }; + + DRB_nGRAN_failed_t failed_setup_drb = { + .id = 5, + .cause = cause, + }; + + DRB_nGRAN_failed_t failed_mod_drb = { + .id = 6, + .cause = cause, + }; + + pdu_session_modif_t pdu_mod = { + .id = 2, + .numDRBModified = 0, + .numDRBFailedToMod = 1, + .DRBnGRanFailedModList[0] = failed_mod_drb, + .numDRBSetup = 0, + .numDRBFailed = 1, + .DRBnGRanFailedList[0] = failed_setup_drb, + .integrityProtectionIndication = NULL, + .confidentialityProtectionIndication = NULL, + .ng_DL_UP_TL_info = NULL, + }; + + e1ap_bearer_modif_resp_t orig = { + .gNB_cu_cp_ue_id = 0xABCD, + .gNB_cu_up_ue_id = 0xDCBA, + .numPDUSessionsMod = 1, + .pduSessionMod[0] = pdu_mod, + }; + + // Encode the original message + E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_mod_response(&orig); + + // Decode the encoded message + E1AP_E1AP_PDU_t *dec = e1ap_encode_decode(enc); + + // Free the encoded message + e1ap_msg_free(enc); + + // Decode into a new struct + e1ap_bearer_modif_resp_t decoded = {0}; + bool ret = decode_E1_bearer_context_mod_response(&decoded, dec); + AssertFatal(ret, "decode_E1_bearer_context_mod_response(): could not decode failed DRB setup+mod case\n"); + + // Free the decoded E1AP message + e1ap_msg_free(dec); + + // Compare the original and decoded structs + ret = eq_bearer_context_mod_response(&orig, &decoded); + AssertFatal(ret, "eq_bearer_context_mod_response(): failed DRB setup+mod case mismatch\n"); + + // Free all memory + free_e1ap_context_mod_response(&decoded); + free_e1ap_context_mod_response(&orig); +} + int main() { // E1 Bearer Context Setup @@ -464,5 +628,7 @@ int main() test_e1_cuup_setup_failure(); // E1 Bearer Context Modification Request test_bearer_context_modification_request(); + test_bearer_context_modification_response(); + test_bearer_context_modification_response_fail(); return 0; } From e2e3ed09a9f68b574f74237ba1d5a764464cfa1c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Nov 2024 19:18:25 +0100 Subject: [PATCH 09/10] Use in stack enc/dec library for E1 Bearer Context Modification Response --- openair2/E1AP/e1ap.c | 144 ++------------------------------------ openair2/RRC/NR/rrc_gNB.c | 1 + 2 files changed, 8 insertions(+), 137 deletions(-) diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 205c3725ef..f0e4d5578d 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -433,69 +433,10 @@ static void e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc e1ap_encode_send(CPtype, assoc_id, pdu, 0, __func__); } -static void fill_BEARER_CONTEXT_MODIFICATION_RESPONSE(const e1ap_bearer_modif_resp_t *resp, E1AP_E1AP_PDU_t *pdu) -{ - pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu->choice.successfulOutcome, msg); - msg->procedureCode = E1AP_ProcedureCode_id_bearerContextModification; - msg->criticality = E1AP_Criticality_reject; - msg->value.present = E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse; - E1AP_BearerContextModificationResponse_t *out = &pdu->choice.successfulOutcome->value.choice.BearerContextModificationResponse; - - /* mandatory */ - /* c1. gNB-CU-CP UE E1AP ID */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ieCuCpId); - ieCuCpId->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; - ieCuCpId->criticality = E1AP_Criticality_reject; - ieCuCpId->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; - ieCuCpId->value.choice.GNB_CU_CP_UE_E1AP_ID = resp->gNB_cu_cp_ue_id; - - /* mandatory */ - /* c2. gNB-CU-UP UE E1AP ID */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ieCuUpId); - ieCuUpId->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; - ieCuUpId->criticality = E1AP_Criticality_reject; - ieCuUpId->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; - ieCuUpId->value.choice.GNB_CU_UP_UE_E1AP_ID = resp->gNB_cu_up_ue_id; - - /* optional */ - /* PDU sessions that have been modified */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ieSys); - ieSys->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse; - ieSys->criticality = E1AP_Criticality_ignore; - ieSys->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse; - - E1AP_System_BearerContextModificationResponse_t *sys = &ieSys->value.choice.System_BearerContextModificationResponse; - E1AP_ProtocolIE_Container_4932P29_t *piel = calloc(1, sizeof(*piel)); - sys->present = E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse; - sys->choice.nG_RAN_BearerContextModificationResponse = (struct E1AP_ProtocolIE_Container *)piel; - asn1cSequenceAdd(piel->list, E1AP_NG_RAN_BearerContextModificationResponse_t, ngran_bcmr); - ngran_bcmr->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List; - ngran_bcmr->criticality = E1AP_Criticality_reject; - ngran_bcmr->value.present = E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List; - E1AP_PDU_Session_Resource_Modified_List_t *pdu_mod_l = &ngran_bcmr->value.choice.PDU_Session_Resource_Modified_List; - for (int i = 0; i < resp->numPDUSessionsMod; ++i) { - const pdu_session_modif_t *pdu = &resp->pduSessionMod[i]; - asn1cSequenceAdd(pdu_mod_l->list, E1AP_PDU_Session_Resource_Modified_Item_t, iePdu); - iePdu->pDU_Session_ID = pdu->id; - if (pdu->numDRBModified > 0) { - iePdu->dRB_Modified_List_NG_RAN = calloc(1, sizeof(*iePdu->dRB_Modified_List_NG_RAN)); - AssertFatal(iePdu->dRB_Modified_List_NG_RAN != NULL, "out of memory\n"); - E1AP_DRB_Modified_List_NG_RAN_t *drb_mod_l = iePdu->dRB_Modified_List_NG_RAN; - for (int j = 0; j < pdu->numDRBModified; ++j) { - const DRB_nGRAN_modified_t *drb = &pdu->DRBnGRanModList[j]; - asn1cSequenceAdd(drb_mod_l->list, E1AP_DRB_Modified_Item_NG_RAN_t, drb_mod); - drb_mod->dRB_ID = drb->id; - } - } - } -} - static int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, const e1ap_bearer_modif_resp_t *resp) { - E1AP_E1AP_PDU_t pdu = {0}; - fill_BEARER_CONTEXT_MODIFICATION_RESPONSE(resp, &pdu); - return e1ap_encode_send(UPtype, assoc_id, &pdu, 0, __func__); + E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_mod_response(resp); + return e1ap_encode_send(UPtype, assoc_id, pdu, 0, __func__); } int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance) @@ -523,88 +464,16 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, return 0; } -static void extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_modif_resp_t *resp) -{ - memset(resp, 0, sizeof(*resp)); - const E1AP_BearerContextModificationResponse_t *in = - &pdu->choice.successfulOutcome->value.choice.BearerContextModificationResponse; - - for (int i = 0; i < in->protocolIEs.list.count; ++i) { - E1AP_BearerContextModificationResponseIEs_t *ie = in->protocolIEs.list.array[i]; - - switch (ie->id) { - case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); - resp->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; - break; - - case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); - resp->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; - break; - - case E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse: - DevAssert(ie->criticality == E1AP_Criticality_ignore); - DevAssert(ie->value.present - == E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse); - DevAssert(ie->value.choice.System_BearerContextModificationResponse.present - == E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse); - E1AP_ProtocolIE_Container_4932P29_t *msgNGRAN_list = - (E1AP_ProtocolIE_Container_4932P29_t *) - ie->value.choice.System_BearerContextModificationResponse.choice.nG_RAN_BearerContextModificationResponse; - DevAssert(msgNGRAN_list->list.count == 1); - E1AP_NG_RAN_BearerContextModificationResponse_t *msgNGRAN = msgNGRAN_list->list.array[0]; - DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List); - DevAssert(msgNGRAN->criticality == E1AP_Criticality_reject); - DevAssert(msgNGRAN->value.present - == E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List); - E1AP_PDU_Session_Resource_Modified_List_t *pduModifiedList = &msgNGRAN->value.choice.PDU_Session_Resource_Modified_List; - resp->numPDUSessionsMod = pduModifiedList->list.count; - - for (int i = 0; i < pduModifiedList->list.count; i++) { - pdu_session_modif_t *pduModified = &resp->pduSessionMod[i]; - E1AP_PDU_Session_Resource_Modified_Item_t *mod_it = pduModifiedList->list.array[i]; - pduModified->id = mod_it->pDU_Session_ID; - - AssertFatal(mod_it->nG_DL_UP_TNL_Information == NULL, "not implemented\n"); - AssertFatal(mod_it->securityResult == NULL, "not implemented\n"); - AssertFatal(mod_it->pDU_Session_Data_Forwarding_Information_Response == NULL, "not implemented\n"); - AssertFatal(mod_it->dRB_Setup_List_NG_RAN == NULL, "not implemented\n"); - AssertFatal(mod_it->dRB_Failed_List_NG_RAN == NULL, "not implemented\n"); - AssertFatal(mod_it->dRB_Failed_To_Modify_List_NG_RAN == NULL, "not implemented\n"); - - pduModified->numDRBModified = mod_it->dRB_Modified_List_NG_RAN->list.count; - for (int j = 0; j < mod_it->dRB_Modified_List_NG_RAN->list.count; j++) { - DRB_nGRAN_modified_t *drbModified = &pduModified->DRBnGRanModList[j]; - E1AP_DRB_Modified_Item_NG_RAN_t *drb = mod_it->dRB_Modified_List_NG_RAN->list.array[j]; - - drbModified->id = drb->dRB_ID; - - AssertFatal(drb->uL_UP_Transport_Parameters == NULL, "not implemented\n"); - AssertFatal(drb->pDCP_SN_Status_Information == NULL, "not implemented\n"); - AssertFatal(drb->flow_Setup_List == NULL, "not implemented\n"); - AssertFatal(drb->flow_Failed_List == NULL, "not implemented\n"); - } - } - break; - } - } -} - int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu) { - DevAssert(pdu != NULL); - DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome); - DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_bearerContextModification); - DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject); - DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse); MessageDef *msg = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_RESP); e1ap_bearer_modif_resp_t *modif = &E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg); - extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(pdu, modif); + if(!decode_E1_bearer_context_mod_response(modif, pdu)) { + free_e1ap_context_mod_response(modif); + return -1; + } itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); return 0; } @@ -1164,6 +1033,7 @@ void *E1AP_CUUP_task(void *arg) const e1ap_upcp_inst_t *inst = getCxtE1(myInstance); AssertFatal(inst, "no E1 instance found for instance %ld\n", myInstance); e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_RESPONSE(inst->cuup.assoc_id, resp); + free_e1ap_context_mod_response(resp); } break; case E1AP_BEARER_CONTEXT_RELEASE_CPLT: { diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 281af514fa..ab60efcff2 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2668,6 +2668,7 @@ void *rrc_gnb_task(void *args_p) { case E1AP_BEARER_CONTEXT_MODIFICATION_RESP: rrc_gNB_process_e1_bearer_context_modif_resp(&E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg_p)); + free_e1ap_context_mod_response(&E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg_p)); break; case E1AP_BEARER_CONTEXT_RELEASE_CPLT: From e9dcbc66f0121bf047e0faea0c06844f6b3cef8a Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 5 Feb 2025 10:57:11 +0100 Subject: [PATCH 10/10] Adopt DRB failed item enc/dec in PDU Session Resource Setup List item enc/dec --- openair2/E1AP/lib/e1ap_bearer_context_management.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index 628fb00cda..81ac737cf6 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -839,13 +839,9 @@ static bool e1_decode_pdu_session_setup_item(pdu_session_setup_t *pduSetup, E1AP } // DRB Failed to Setup List (O) if (in->dRB_Failed_List_NG_RAN) { + pduSetup->numDRBFailed = in->dRB_Failed_List_NG_RAN->list.count; for (int j = 0; j < in->dRB_Failed_List_NG_RAN->list.count; j++) { - DRB_nGRAN_failed_t *drbFailed = pduSetup->DRBnGRanFailedList + j; - E1AP_DRB_Failed_Item_NG_RAN_t *item = in->dRB_Failed_List_NG_RAN->list.array[j]; - // DRB ID (M) - drbFailed->id = item->dRB_ID; - // Cause (M) - drbFailed->cause = e1_decode_cause_ie(&item->cause); + decode_drb_failed_item(&pduSetup->DRBnGRanFailedList[j], in->dRB_Failed_List_NG_RAN->list.array[j]); } } return true; @@ -879,10 +875,7 @@ static bool e1_encode_pdu_session_setup_item(E1AP_PDU_Session_Resource_Setup_Ite // DRB Failed Item for (const DRB_nGRAN_failed_t *j = in->DRBnGRanFailedList; j < in->DRBnGRanFailedList + in->numDRBFailed; j++) { asn1cSequenceAdd(item->dRB_Failed_List_NG_RAN->list, E1AP_DRB_Failed_Item_NG_RAN_t, ieC3_1_1); - // DRB ID (M) - ieC3_1_1->dRB_ID = j->id; - // Cause (M) - ieC3_1_1->cause = e1_encode_cause_ie(&j->cause); + encode_drb_failed_item(ieC3_1_1, j); } return true; }