From bb63aa79b23ccd402387482e5389866f04e778ac Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 5 Jun 2023 14:08:00 +0200 Subject: [PATCH] Implement F1AP UE Context Modification Required/Confirm/Refuse F1AP messages --- openair2/F1AP/f1ap_cu_ue_context_management.c | 250 +++++++++++++++++- openair2/F1AP/f1ap_du_ue_context_management.c | 237 ++++++++++++++++- 2 files changed, 481 insertions(+), 6 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index b5d3ea0ec8..4b91903d5f 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -1703,18 +1703,262 @@ int CU_handle_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance, int CU_handle_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - AssertFatal(false, "%s() not implemented yet\n", __func__); + DevAssert(pdu != NULL); + + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_MODIFICATION_REQUIRED); + f1ap_ue_context_modif_required_t *required = &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg_p); + + F1AP_UEContextModificationRequired_t *container = &pdu->choice.initiatingMessage->value.choice.UEContextModificationRequired; + F1AP_UEContextModificationRequiredIEs_t *ie = NULL; + + /* required: GNB_CU_UE_F1AP_ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + required->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + + /* required: GNB_DU_UE_F1AP_ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + required->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + + /* optional: Resource Coordination Transfer Container */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer, + false); + AssertFatal(ie == NULL, "handling of Resource Coordination Transfer Container not implemented\n"); + + /* optional: DU to CU RRC Information */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_DUtoCURRCInformation, + false); + if (ie != NULL) { + F1AP_DUtoCURRCInformation_t *du2cu = &ie->value.choice.DUtoCURRCInformation; + required->du_to_cu_rrc_information = malloc(sizeof(*required->du_to_cu_rrc_information)); + AssertFatal(required->du_to_cu_rrc_information != NULL, "memory allocation failed\n"); + + required->du_to_cu_rrc_information->cellGroupConfig = malloc(du2cu->cellGroupConfig.size); + AssertFatal(required->du_to_cu_rrc_information->cellGroupConfig != NULL, "memory allocation failed\n"); + memcpy(required->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig.buf, du2cu->cellGroupConfig.size); + required->du_to_cu_rrc_information->cellGroupConfig_length = du2cu->cellGroupConfig.size; + + AssertFatal(du2cu->measGapConfig == NULL, "handling of measGapConfig not implemented\n"); + AssertFatal(du2cu->requestedP_MaxFR1 == NULL, "handling of requestedP_MaxFR1 not implemented\n"); + } + + /* optional: DRB Required to Be Modified List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_DRBs_Required_ToBeModified_List, + false); + AssertFatal(ie == NULL, "handling of DRBs Required to be modified list not implemented\n"); + + /* optional: SRB Required to be Released List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_SRBs_Required_ToBeReleased_List, + false); + AssertFatal(ie == NULL, "handling of SRBs Required to be released list not implemented\n"); + + /* optional: DRB Required to be Released List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_DRBs_Required_ToBeReleased_List, + false); + AssertFatal(ie == NULL, "handling of DRBs Required to be released list not implemented\n"); + + /* mandatory: Cause */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Cause, true); + switch (ie->value.choice.Cause.present) { + case F1AP_Cause_PR_radioNetwork: + required->cause = F1AP_CAUSE_RADIO_NETWORK; + required->cause_value = ie->value.choice.Cause.choice.radioNetwork; + break; + case F1AP_Cause_PR_transport: + required->cause = F1AP_CAUSE_TRANSPORT; + required->cause_value = ie->value.choice.Cause.choice.transport; + break; + case F1AP_Cause_PR_protocol: + required->cause = F1AP_CAUSE_PROTOCOL; + required->cause_value = ie->value.choice.Cause.choice.protocol; + break; + case F1AP_Cause_PR_misc: + required->cause = F1AP_CAUSE_MISC; + required->cause_value = ie->value.choice.Cause.choice.misc; + break; + default: + LOG_W(F1AP, "Unknown cause for UE Context Modification required message\n"); + /* fall through */ + case F1AP_Cause_PR_NOTHING: + required->cause = F1AP_CAUSE_NOTHING; + break; + } + + /* optional: BH RLC Channel Required to be Released List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_BHChannels_Required_ToBeReleased_List, + false); + AssertFatal(ie == NULL, "handling of BH RLC Channel Required to be Released list not implemented\n"); + + /* optional: SL DRB Required to Be Modified List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_SLDRBs_Required_ToBeModified_List, + false); + AssertFatal(ie == NULL, "handling of SL DRB Required to be modified list not implemented\n"); + + /* optional: SL DRB Required to be Released List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_SLDRBs_Required_ToBeReleased_List, + false); + AssertFatal(ie == NULL, "handling of SL DRBs Required to be released list not implemented\n"); + + /* optional: Candidate Cells To Be Cancelled List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_Candidate_SpCell_List, + false); + AssertFatal(ie == NULL, "handling of candidate cells to be cancelled list not implemented\n"); + + itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); return 0; } int CU_send_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, f1ap_ue_context_modif_confirm_t *confirm) { - AssertFatal(false, "%s() not implemented yet\n", __func__); + F1AP_F1AP_PDU_t pdu = {0}; + pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu.choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModificationRequired; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextModificationConfirm; + F1AP_UEContextModificationConfirm_t *out = &tmp->value.choice.UEContextModificationConfirm; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationConfirmIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextModificationConfirmIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = confirm->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationConfirmIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextModificationConfirmIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = confirm->gNB_DU_ue_id; + + /* optional: Resource Coordination Transfer Container */ + /* not implemented*/ + + /* optional: DRB Modified List */ + /* not implemented*/ + + /* optional: RRC Container */ + if (confirm->rrc_container != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationConfirmIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie->criticality = F1AP_Criticality_ignore; + ie->value.present = F1AP_UEContextModificationConfirmIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie->value.choice.RRCContainer, (const char *)confirm->rrc_container, confirm->rrc_container_length); + } + + /* optional: CriticalityDiagnostics */ + /* not implemented*/ + + /* optional: Execute Duplication */ + /* not implemented*/ + + /* optional: Resource Coordination Transfer Information */ + /* not implemented*/ + + /* optional: SL DRB Modified List */ + /* not implemented*/ + + /* encode */ + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 UE Context Modification Confirm\n"); + return -1; + } + f1ap_itti_send_sctp_data_req(true, instance, buffer, len, 0); return 0; } int CU_send_UE_CONTEXT_MODIFICATION_REFUSE(instance_t instance, f1ap_ue_context_modif_refuse_t *refuse) { - AssertFatal(false, "%s() not implemented yet\n", __func__); + F1AP_F1AP_PDU_t pdu = {0}; + pdu.present = F1AP_F1AP_PDU_PR_unsuccessfulOutcome; + asn1cCalloc(pdu.choice.unsuccessfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModificationRequired; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_UnsuccessfulOutcome__value_PR_UEContextModificationRefuse; + F1AP_UEContextModificationRefuse_t *out = &tmp->value.choice.UEContextModificationRefuse; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRefuseIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextModificationRefuseIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = refuse->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRefuseIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextModificationRefuseIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = refuse->gNB_DU_ue_id; + + /* optional: Cause */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRefuseIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Cause; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_UEContextModificationRefuseIEs__value_PR_Cause; + F1AP_Cause_t *cause = &ie3->value.choice.Cause; + switch (refuse->cause) { + case F1AP_CAUSE_RADIO_NETWORK: + cause->present = F1AP_Cause_PR_radioNetwork; + cause->choice.radioNetwork = refuse->cause_value; + break; + case F1AP_CAUSE_TRANSPORT: + cause->present = F1AP_Cause_PR_transport; + cause->choice.transport = refuse->cause_value; + break; + case F1AP_CAUSE_PROTOCOL: + cause->present = F1AP_Cause_PR_protocol; + cause->choice.protocol = refuse->cause_value; + break; + case F1AP_CAUSE_MISC: + cause->present = F1AP_Cause_PR_misc; + cause->choice.misc = refuse->cause_value; + break; + case F1AP_CAUSE_NOTHING: + default: + cause->present = F1AP_Cause_PR_NOTHING; + break; + } // switch + + /* optional: CriticalityDiagnostics */ + /* not implemented*/ + + /* encode */ + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 UE Context Modification Refuse\n"); + return -1; + } + f1ap_itti_send_sctp_data_req(true, instance, buffer, len, 0); return 0; } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 69410f3bc5..352a29bd06 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -1288,18 +1288,249 @@ int DU_send_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance) { int DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, f1ap_ue_context_modif_required_t *required) { - AssertFatal(false, "%s() not implemented yet\n", __func__); + /* 0. Message Type */ + F1AP_F1AP_PDU_t pdu = {0}; + pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu.choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModificationRequired; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextModificationRequired; + F1AP_UEContextModificationRequired_t *out = &tmp->value.choice.UEContextModificationRequired; + + /* mandatory GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequiredIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextModificationRequiredIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = required->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequiredIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextModificationRequiredIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = required->gNB_DU_ue_id; + + /* optional: Resource Coordination Transfer Container */ + /* not implemented!*/ + + /* optional: DU-to-CU RRC Container */ + if (required->du_to_cu_rrc_information) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequiredIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_UEContextModificationRequiredIEs__value_PR_DUtoCURRCInformation; + + const du_to_cu_rrc_information_t *du2cu = required->du_to_cu_rrc_information; + AssertFatal(du2cu->cellGroupConfig != NULL, "du2cu cellGroupConfig is mandatory!\n"); + + /* mandatorycellGroupConfig */ + OCTET_STRING_fromBuf(&ie3->value.choice.DUtoCURRCInformation.cellGroupConfig, + (const char *)du2cu->cellGroupConfig, + du2cu->cellGroupConfig_length); + + /* optional: measGapConfig */ + if (du2cu->measGapConfig != NULL) { + OCTET_STRING_fromBuf(ie3->value.choice.DUtoCURRCInformation.measGapConfig, + (const char *)du2cu->measGapConfig, + du2cu->measGapConfig_length); + } + + /* optional: requestedP_MaxFR1 */ + if (du2cu->requestedP_MaxFR1 != NULL) { + OCTET_STRING_fromBuf(ie3->value.choice.DUtoCURRCInformation.requestedP_MaxFR1, + (const char *)du2cu->requestedP_MaxFR1, + du2cu->requestedP_MaxFR1_length); + } + } + + /* optional: DRB required to be modified */ + /* not implemented */ + + /* optional: SRB required to be released */ + /* not implemented */ + + /* optional: DRB required to be released */ + /* not implemented */ + + /* mandatory: cause */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequiredIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_Cause; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_UEContextModificationRequiredIEs__value_PR_Cause; + F1AP_Cause_t *cause = &ie4->value.choice.Cause; + switch (required->cause) { + case F1AP_CAUSE_RADIO_NETWORK: + cause->present = F1AP_Cause_PR_radioNetwork; + cause->choice.radioNetwork = required->cause_value; + break; + case F1AP_CAUSE_TRANSPORT: + cause->present = F1AP_Cause_PR_transport; + cause->choice.transport = required->cause_value; + break; + case F1AP_CAUSE_PROTOCOL: + cause->present = F1AP_Cause_PR_protocol; + cause->choice.protocol = required->cause_value; + break; + case F1AP_CAUSE_MISC: + cause->present = F1AP_Cause_PR_misc; + cause->choice.misc = required->cause_value; + break; + case F1AP_CAUSE_NOTHING: + default: + cause->present = F1AP_Cause_PR_NOTHING; + break; + } // switch + + /* optional: BH RLC Channel Required to be Released List */ + /* not implemented */ + + /* optional: SL DRB Required to Be Modified List */ + /* not implemented */ + + /* optional: SL DRB Required to be Released List */ + /* not implemented */ + + /* optional: Candidate Cells To Be Cancelled List */ + /* not implemented */ + + /* encode */ + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 context release request\n"); + return -1; + } + + f1ap_itti_send_sctp_data_req(false, instance, buffer, len, getCxt(false, instance)->default_sctp_stream_id); return 0; } int DU_handle_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - AssertFatal(false, "%s() not implemented yet\n", __func__); + F1AP_UEContextModificationConfirm_t *container = &pdu->choice.successfulOutcome->value.choice.UEContextModificationConfirm; + f1ap_ue_context_modif_confirm_t confirm = {0}; + F1AP_UEContextModificationConfirmIEs_t *ie = NULL; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + confirm.gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + confirm.gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + + /* optional: Resource Coordination Transfer Container */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer, + false); + AssertFatal(ie == NULL, "handling of Resource Coordination Transfer Container not implemented\n"); + + /* optional: DRBS Modified List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_DRBs_Modified_List, + false); + AssertFatal(ie == NULL, "handling of DRBs Modified List not implemented\n"); + + /* optional: RRC Container */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t, ie, container, F1AP_ProtocolIE_ID_id_RRCContainer, false); + if (ie != NULL) { + F1AP_RRCContainer_t *rrc_container = &ie->value.choice.RRCContainer; + confirm.rrc_container = malloc(rrc_container->size); + AssertFatal(confirm.rrc_container != NULL, "memory allocation failed\n"); + memcpy(confirm.rrc_container, rrc_container->buf, rrc_container->size); + confirm.rrc_container_length = rrc_container->size; + } + + /* optional: Criticality Diagnostics */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_CriticalityDiagnostics, + false); + AssertFatal(ie == NULL, "handling of DRBs Modified List not implemented\n"); + + /* optional: Execute Duplication */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_ExecuteDuplication, + false); + AssertFatal(ie == NULL, "handling of DRBs Modified List not implemented\n"); + + /* optional: Resource Coordination Transfer Information */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferInformation, + false); + AssertFatal(ie == NULL, "handling of DRBs Modified List not implemented\n"); + + /* optional: SL DRB Modified List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_SLDRBs_Modified_List, + false); + AssertFatal(ie == NULL, "handling of DRBs Modified List not implemented\n"); + + ue_context_modification_confirm(&confirm); return 0; } int DU_handle_UE_CONTEXT_MODIFICATION_REFUSE(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - AssertFatal(false, "%s() not implemented yet\n", __func__); + F1AP_UEContextModificationRefuse_t *container = &pdu->choice.unsuccessfulOutcome->value.choice.UEContextModificationRefuse; + f1ap_ue_context_modif_refuse_t refuse = {0}; + F1AP_UEContextModificationRefuseIEs_t *ie = NULL; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRefuseIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + refuse.gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRefuseIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + refuse.gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + + /* mandatory: Cause */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRefuseIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Cause, true); + switch (ie->value.choice.Cause.present) { + case F1AP_Cause_PR_radioNetwork: + refuse.cause = F1AP_CAUSE_RADIO_NETWORK; + refuse.cause_value = ie->value.choice.Cause.choice.radioNetwork; + break; + case F1AP_Cause_PR_transport: + refuse.cause = F1AP_CAUSE_TRANSPORT; + refuse.cause_value = ie->value.choice.Cause.choice.transport; + break; + case F1AP_Cause_PR_protocol: + refuse.cause = F1AP_CAUSE_PROTOCOL; + refuse.cause_value = ie->value.choice.Cause.choice.protocol; + break; + case F1AP_Cause_PR_misc: + refuse.cause = F1AP_CAUSE_MISC; + refuse.cause_value = ie->value.choice.Cause.choice.misc; + break; + default: + LOG_W(F1AP, "Unknown cause for UE Context Modification Refuse message\n"); + /* fall through */ + case F1AP_Cause_PR_NOTHING: + refuse.cause = F1AP_CAUSE_NOTHING; + break; + } + + /* optional: Criticality Diagnostics */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRefuseIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_CriticalityDiagnostics, + false); + AssertFatal(ie == NULL, "handling of DRBs Modified List not implemented\n"); + + ue_context_modification_refuse(&refuse); return 0; }