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/e1ap.c b/openair2/E1AP/e1ap.c index 0b5582ea39..f0e4d5578d 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -427,168 +427,16 @@ 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__); -} - -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; - } - } - } + E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_mod_request(bearerCxt); + e1ap_encode_send(CPtype, assoc_id, pdu, 0, __func__); } 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) @@ -597,121 +445,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,99 +453,27 @@ 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); - e1_bearer_context_modif(&bearerCxt); - 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; - } + 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; } 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; } @@ -1296,6 +957,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: @@ -1371,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/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index a8f68e70d6..81ac737cf6 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" @@ -83,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; } @@ -515,7 +526,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; } @@ -766,11 +777,31 @@ 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; } +/** 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 * ====================================== */ @@ -808,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; @@ -848,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; } @@ -1036,8 +1060,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; @@ -1349,10 +1373,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; @@ -1494,7 +1520,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; } @@ -1680,3 +1706,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_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 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_ */ 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; } 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); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 6978d0684e..a110e4af53 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2866,6 +2866,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: