diff --git a/CMakeLists.txt b/CMakeLists.txt index 948f623f2b..2d916eba89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1403,9 +1403,6 @@ if(E2_AGENT) endif() -add_library(MAC_NR ${MAC_NR_SRC}) -target_link_libraries(MAC_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) - add_library(MAC_UE_NR ${MAC_NR_SRC_UE}) target_link_libraries(MAC_UE_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) @@ -2233,7 +2230,7 @@ add_executable(nr_dlsim ${PHY_INTERFACE_DIR}/queue_t.c ) target_link_libraries(nr_dlsim PRIVATE - -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group + -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2277,7 +2274,7 @@ if (ENABLE_LDPC_T1) endif() target_link_libraries(nr_ulsim PRIVATE - -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group + -Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group m pthread ${T_LIB} ITTI dl shlib_loader ) target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -2339,7 +2336,7 @@ if (${T_TRACER}) NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB MISC_NFAPI_NR_LIB PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX - L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_NR MAC_UE_NR ngap + L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_UE_NR ngap CN_UTILS GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE NB_IoT SIMU SIMU_ETH OPENAIR0_LIB ldpc_orig ldpc_optim ldpc_optim8seg ldpc dfts) if (TARGET ${i}) diff --git a/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml index 5b6e03db16..8e353b945e 100644 --- a/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml @@ -43,7 +43,7 @@ services: container_name: sa-du-b200-gnb environment: USE_B2XX: 'yes' - USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx -E --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 --RUs.[0].att_rx 14 --RUs.[0].att_tx 14 + USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx -E --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 --RUs.[0].att_rx 18 --RUs.[0].att_tx 18 volumes: - ../../conf_files/gnb-du.sa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf - /dev:/dev diff --git a/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml index 2be92cdb38..2ad0818a47 100644 --- a/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml @@ -26,7 +26,7 @@ services: container_name: sa-du-b200-gnb environment: USE_B2XX: 'yes' - USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx -E --telnetsrv --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 --RUs.[0].att_rx 14 --RUs.[0].att_tx 14 + USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx -E --telnetsrv --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 --RUs.[0].att_rx 18 --RUs.[0].att_tx 18 volumes: - ../../conf_files/gnb-du.sa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf - /dev:/dev diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index 7c67b22756..08f552d9d3 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -40,6 +40,7 @@ MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_r MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_req_t, f1ap_ue_context_release_req) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_cmd) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_complete_t, f1ap_ue_context_release_complete) +MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_required_t, f1ap_ue_context_modification_required) /* RRC -> F1AP messages */ MESSAGE_DEF(F1AP_DL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t , f1ap_dl_rrc_message ) @@ -48,6 +49,8 @@ MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_se MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_resp) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_req_t, f1ap_ue_context_modification_req) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_resp_t, f1ap_ue_context_modification_resp) +MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_CONFIRM, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_confirm_t, f1ap_ue_context_modification_confirm) +MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REFUSE, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_refuse_t, f1ap_ue_context_modification_refuse) /* CU -> DU*/ MESSAGE_DEF(F1AP_PAGING_IND, MESSAGE_PRIORITY_MED, f1ap_paging_ind_t, f1ap_paging_ind) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 3d594a695e..2f95ee8cdc 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -44,6 +44,9 @@ #define F1AP_UE_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_req #define F1AP_UE_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_resp #define F1AP_UE_CONTEXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_fail +#define F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_required +#define F1AP_UE_CONTEXT_MODIFICATION_CONFIRM(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_confirm +#define F1AP_UE_CONTEXT_MODIFICATION_REFUSE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_refuse #define F1AP_DL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_dl_rrc_message #define F1AP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_req @@ -417,6 +420,28 @@ typedef enum F1ap_Cause_e { F1AP_CAUSE_MISC, } f1ap_Cause_t; +typedef struct f1ap_ue_context_modif_required_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + du_to_cu_rrc_information_t *du_to_cu_rrc_information; + f1ap_Cause_t cause; + long cause_value; +} f1ap_ue_context_modif_required_t; + +typedef struct f1ap_ue_context_modif_confirm_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + uint8_t *rrc_container; + int rrc_container_length; +} f1ap_ue_context_modif_confirm_t; + +typedef struct f1ap_ue_context_modif_refuse_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + f1ap_Cause_t cause; + long cause_value; +} f1ap_ue_context_modif_refuse_t; + typedef struct f1ap_ue_context_release_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index 7cc23e88fa..617366563c 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -184,6 +184,16 @@ void *F1AP_CU_task(void *arg) { &F1AP_PAGING_IND(received_msg)); break; + case F1AP_UE_CONTEXT_MODIFICATION_CONFIRM: + CU_send_UE_CONTEXT_MODIFICATION_CONFIRM(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &F1AP_UE_CONTEXT_MODIFICATION_CONFIRM(received_msg)); + break; + + case F1AP_UE_CONTEXT_MODIFICATION_REFUSE: + CU_send_UE_CONTEXT_MODIFICATION_REFUSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &F1AP_UE_CONTEXT_MODIFICATION_REFUSE(received_msg)); + break; + // case F1AP_SETUP_RESPONSE: // This is from RRC // CU_send_F1_SETUP_RESPONSE(instance, *f1ap_setup_ind, &(F1AP_SETUP_RESP) f1ap_setup_resp) // break; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index a72a359c5b..4b91903d5f 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -1701,14 +1701,264 @@ int CU_handle_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance, AssertFatal(1==0,"Not implemented yet\n"); } -int CU_handle_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu) { - AssertFatal(1==0,"Not implemented yet\n"); +int CU_handle_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) +{ + 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_UEContextModificationConfirm_t UEContextModificationConfirm_t) { - AssertFatal(1==0,"Not implemented yet\n"); +int CU_send_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, f1ap_ue_context_modif_confirm_t *confirm) +{ + 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) +{ + 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_cu_ue_context_management.h b/openair2/F1AP/f1ap_cu_ue_context_management.h index 32a54bc6cc..76bbecb2b8 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.h +++ b/openair2/F1AP/f1ap_cu_ue_context_management.h @@ -85,12 +85,11 @@ int CU_handle_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance, /* * UE Context Modification Required (gNB-DU initiated) */ -int CU_handle_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu); -int CU_send_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, - F1AP_UEContextModificationConfirm_t UEContextModificationConfirm_t); +int CU_handle_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); + +int CU_send_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, f1ap_ue_context_modif_confirm_t *confirm); + +int CU_send_UE_CONTEXT_MODIFICATION_REFUSE(instance_t instance, f1ap_ue_context_modif_refuse_t *refuse); /* * UE Inactivity Notification diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c index a7af049c2a..8f8258a1f8 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -169,6 +169,10 @@ void *F1AP_DU_task(void *arg) { DU_send_UE_CONTEXT_RELEASE_COMPLETE(myInstance, &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg)); break; + case F1AP_UE_CONTEXT_MODIFICATION_REQUIRED: + DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(myInstance, &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg)); + break; + case TERMINATE_MESSAGE: LOG_W(F1AP, " *** Exiting F1AP thread\n"); itti_exit_task(); diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 2430b2f870..352a29bd06 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -1285,12 +1285,252 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, f1ap_ue_contex int DU_send_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance) { AssertFatal(1==0,"Not implemented yet\n"); } -int DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance) { - AssertFatal(1==0,"Not implemented yet\n"); + +int DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, f1ap_ue_context_modif_required_t *required) +{ + /* 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(1==0,"Not implemented yet\n"); + +int DU_handle_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) +{ + 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) +{ + 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; } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.h b/openair2/F1AP/f1ap_du_ue_context_management.h index 51b8fa6dce..cd8565f328 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.h +++ b/openair2/F1AP/f1ap_du_ue_context_management.h @@ -79,13 +79,11 @@ int DU_send_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance); /* * UE Context Modification Required (gNB-DU initiated) */ -int DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance); -int DU_handle_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu); +int DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, f1ap_ue_context_modif_required_t *required); -int DU_send_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, f1ap_ue_context_setup_t *req); +int DU_handle_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); + +int DU_handle_UE_CONTEXT_MODIFICATION_REFUSE(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); /* * UE Inactivity Notification diff --git a/openair2/F1AP/f1ap_handlers.c b/openair2/F1AP/f1ap_handlers.c index 3eb4b1d86d..cf2530c850 100644 --- a/openair2/F1AP/f1ap_handlers.c +++ b/openair2/F1AP/f1ap_handlers.c @@ -52,7 +52,7 @@ static const f1ap_message_processing_t f1ap_messages_processing[][3] = { {DU_handle_UE_CONTEXT_SETUP_REQUEST, CU_handle_UE_CONTEXT_SETUP_RESPONSE, 0}, /* UEContextSetup */ {DU_handle_UE_CONTEXT_RELEASE_COMMAND, CU_handle_UE_CONTEXT_RELEASE_COMPLETE, 0}, /* UEContextRelease */ {DU_handle_UE_CONTEXT_MODIFICATION_REQUEST, CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE, 0}, /* UEContextModification */ - {0, 0, 0}, /* UEContextModificationRequired */ + {CU_handle_UE_CONTEXT_MODIFICATION_REQUIRED, DU_handle_UE_CONTEXT_MODIFICATION_CONFIRM, DU_handle_UE_CONTEXT_MODIFICATION_REFUSE}, /* UEContextModificationRequired */ {0, 0, 0}, /* UEMobilityCommand */ {CU_handle_UE_CONTEXT_RELEASE_REQUEST, 0, 0}, /* UEContextReleaseRequest */ {CU_handle_INITIAL_UL_RRC_MESSAGE_TRANSFER, 0, 0}, /* InitialULRRCMessageTransfer */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 165251e9f4..bdf84ddc8e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1615,192 +1615,6 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, LOG_D(NR_MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci); } -static void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req) -{ - gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; - - // proceed only if it is a DL slot - if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) - return; - - // UE is known by the network, C-RNTI to be used instead of TC-RNTI - int rnti = ra->crnti; - - NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, rnti); - if (!UE) { - LOG_E(NR_MAC, "Received Msg3 with C-RNTI but rnti %04x not in the table\n", rnti); - return; - } - - NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_SearchSpace_t *ss = ra->ra_ss; - - NR_ControlResourceSet_t *coreset = ra->coreset; - AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg4\n"); - - // Only need to schedule DCI with and empty DL - NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP; - long BWPStart = 0; - long BWPSize = 0; - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL; - if(*ss->controlResourceSetId!=0) { - BWPStart = dl_bwp->BWPStart; - BWPSize = dl_bwp->BWPSize; - } else { - type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[ra->beam_id]; - BWPStart = type0_PDCCH_CSS_config->cset_start_rb; - BWPSize = type0_PDCCH_CSS_config->num_rbs; - } - - // get CCEindex, needed also for PUCCH and then later for PDCCH - uint8_t aggregation_level; - int CCEIndex = get_cce_index(nr_mac, - CC_id, slotP, 0, - &aggregation_level, - ss, - coreset, - &ra->sched_pdcch, - true); - - if (CCEIndex < 0) { - LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, rnti); - return; - } - - // Checking if the DCI allocation is feasible in current subframe - nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; - if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { - LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, rnti); - return; - } - - uint8_t time_domain_assignment = get_dl_tda(nr_mac, scc, slotP); - int mux_pattern = type0_PDCCH_CSS_config ? type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern : 1; - NR_tda_info_t tda = get_dl_tda_info(dl_bwp, ss->searchSpaceType->present, time_domain_assignment, - scc->dmrs_TypeA_Position, mux_pattern, NR_RNTI_C, coreset->controlResourceSetId, false); - - NR_pdsch_dmrs_t dmrs_info = get_dl_dmrs_params(scc, - dl_bwp, - &tda, - 1); - - int subheader_len = sizeof(NR_MAC_SUBHEADER_SHORT); - int pdu_length = subheader_len + 7; // 7 is contetion resolution length - - int mcsTableIdx = dl_bwp->mcsTableIdx; - int mcsIndex = 0; - int rbStart = 0; - int rbSize = 0; - int tb_scaling = 0; - uint32_t tb_size = 0; - - // increase PRBs until we get to BWPSize or TBS is bigger than MAC PDU size - do { - if(rbSize < BWPSize) - rbSize++; - else - mcsIndex++; - LOG_D(NR_MAC,"Calling nr_compute_tbs with N_PRB_DMRS %d, N_DMRS_SLOT %d\n",dmrs_info.N_PRB_DMRS,dmrs_info.N_DMRS_SLOT); - tb_size = nr_compute_tbs(nr_get_Qm_dl(mcsIndex, mcsTableIdx), - nr_get_code_rate_dl(mcsIndex, mcsTableIdx), - rbSize, tda.nrOfSymbols, dmrs_info.N_PRB_DMRS * dmrs_info.N_DMRS_SLOT, 0, tb_scaling,1) >> 3; - } while (tb_size < pdu_length && mcsIndex<=28); - - AssertFatal(tb_size >= pdu_length,"Cannot allocate response to MSG3 with DCCH\n"); - - int i = 0; - uint16_t *vrb_map = cc[CC_id].vrb_map; - while ((i < rbSize) && (rbStart + rbSize <= BWPSize)) { - if (vrb_map[BWPStart + rbStart + i]&SL_to_bitmap(tda.startSymbolIndex, tda.nrOfSymbols)) { - rbStart += i+1; - i = 0; - } else { - i++; - } - } - - if (rbStart > (BWPSize - rbSize)) { - LOG_E(NR_MAC, "%s(): cannot find free vrb_map for RNTI %04x!\n", __func__, rnti); - return; - } - - // Remove UE associated to TC-RNTI - mac_remove_nr_ue(nr_mac, ra->rnti); - - - // If the UE used MSG3 to transfer a DCCH or DTCH message, then contention resolution is successful if the UE receives a PDCCH transmission which has its CRC bits scrambled by the C-RNTI - // Just send padding LCID - uint8_t buf[tb_size]; - NR_MAC_SUBHEADER_FIXED *padding = (NR_MAC_SUBHEADER_FIXED *) &buf[0]; - padding->R = 0; - padding->LCID = DL_SCH_LCID_PADDING; - for(int k = 1; k < tb_size; k++) - buf[k] = 0; - - T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(ra->rnti), - T_INT(frameP), T_INT(slotP), T_INT(0), T_BUFFER(buf, tb_size)); - - // SCF222: PDU index incremented for each PDSCH PDU sent in TX control message. This is used to associate control - // information to data and is reset every slot. - const int pduindex = nr_mac->pdu_index[CC_id]++; - - prepare_dl_pdus(nr_mac, ra, dl_bwp, dl_req, NULL, dmrs_info, tda, aggregation_level, CCEIndex, tb_size, 0, 0, 0, - 0, time_domain_assignment, CC_id, rnti, 0, mcsIndex, tb_scaling, pduindex, rbStart, rbSize); - - // DL TX request - nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; - memcpy(tx_req->TLVs[0].value.direct, buf, sizeof(uint8_t) * tb_size); - tx_req->PDU_length = tb_size; - tx_req->PDU_index = pduindex; - tx_req->num_TLV = 1; - tx_req->TLVs[0].length = tb_size + 2; - TX_req->SFN = frameP; - TX_req->Number_of_PDUs++; - TX_req->Slot = slotP; - - // Mark the corresponding symbols and RBs as used - fill_pdcch_vrb_map(nr_mac, - CC_id, - &ra->sched_pdcch, - CCEIndex, - aggregation_level); - for (int rb = 0; rb < rbSize; rb++) - vrb_map[BWPStart + rb + rbStart] |= SL_to_bitmap(tda.startSymbolIndex, tda.nrOfSymbols); - - - // If the UE used MSG3 to transfer a DCCH or DTCH message, then contention resolution is successful upon transmission of PDCCH - LOG_A(NR_MAC, "(ue rnti 0x%04x) CBRA procedure succeeded!\n", ra->rnti); - nr_clear_ra_proc(module_idP, CC_id, frameP, ra); - UE->Msg4_ACKed = true; - UE->ra_timer = 0; - - if(!UE->CellGroup) { - // In the specific scenario where UE correctly received MSG4 (assuming it decoded RRCsetup with CellGroup) and gNB didn't correctly received an ACK, - // the UE would already have CG but the UE-dedicated gNB structure wouldn't (because RA didn't complete on gNB side). - uper_decode(NULL, - &asn_DEF_NR_CellGroupConfig, //might be added prefix later - (void **)&UE->CellGroup, - (uint8_t *)UE->cg_buf, - (UE->enc_rval.encoded+7)/8, 0, 0); - } - - process_CellGroup(UE->CellGroup, UE); - - // switching to initial BWP - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - configure_UE_BWP(nr_mac, scc, sched_ctrl, NULL, UE, 0, 0); - - // Reset uplink failure flags/counters/timers at MAC so gNB will resume again scheduling resources for this UE - nr_mac_reset_ul_failure(sched_ctrl); -} - static void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, @@ -1814,8 +1628,7 @@ static void nr_generate_Msg4(module_id_t module_idP, NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP; // if it is a DL slot, if the RA is in MSG4 state - if (is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP) && - ra->state == Msg4) { + if (is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) { NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_SearchSpace_t *ss = ra->ra_ss; @@ -1842,7 +1655,7 @@ static void nr_generate_Msg4(module_id_t module_idP, if (srb_status.bytes_in_buffer == 0) { lcid = DL_SCH_LCID_DCCH; - // Check for data on SRB1 (RRCReestablishment) + // Check for data on SRB1 (RRCReestablishment, RRCReconfiguration) srb_status = mac_rlc_status_ind(module_idP, ra->rnti, module_idP, frameP, slotP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, 0, 0); } @@ -1955,8 +1768,6 @@ static void nr_generate_Msg4(module_id_t module_idP, return; } - LOG_I(NR_MAC,"Generate msg4, rnti: %04x\n", ra->rnti); - // HARQ management if (current_harq_pid < 0) { AssertFatal(sched_ctrl->available_dl_harq.head >= 0, @@ -2011,7 +1822,6 @@ static void nr_generate_Msg4(module_id_t module_idP, ((NR_MAC_SUBHEADER_LONG *)&buf[mac_pdu_length])->L = htons(mac_sdu_length); ra->mac_pdu_length = mac_pdu_length + mac_sdu_length + sizeof(NR_MAC_SUBHEADER_LONG); } - LOG_I(NR_MAC,"Encoded RRCSetup Piggyback (%d + %d bytes), mac_pdu_length %d\n", mac_sdu_length, mac_subheader_len, ra->mac_pdu_length); memcpy(&buf[mac_pdu_length + mac_subheader_len], buffer, mac_sdu_length); } @@ -2054,7 +1864,7 @@ static void nr_generate_Msg4(module_id_t module_idP, } ra->state = WAIT_Msg4_ACK; - LOG_D(NR_MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state); + LOG_I(NR_MAC,"UE %04x Generate msg4: feedback at %4d.%2d, payload %d bytes, next state WAIT_Msg4_ACK\n", ra->rnti, pucch->frame, pucch->ul_slot, harq->tb_size); } } @@ -2113,7 +1923,6 @@ void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t ra->timing_offset = 0; ra->RRC_timer = 20; ra->msg3_round = 0; - ra->crnti = 0; if(ra->cfra == false) { ra->rnti = 0; } @@ -2271,7 +2080,7 @@ void nr_schedule_RA(module_id_t module_idP, nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req); break; case Msg3_dcch_dtch: - nr_generate_Msg3_dcch_dtch_response(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); + /* fallthrough */ case Msg4: nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); break; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 3983773c56..f475ed385a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -43,11 +43,13 @@ #include "UTIL/OPT/opt.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h" +#include "F1AP_CauseRadioNetwork.h" #include "RRC/NR/MESSAGES/asn1_msg.h" #include "intertask_interface.h" #include "openair2/F1AP/f1ap_ids.h" +#include "F1AP_CauseRadioNetwork.h" #include "T.h" @@ -2945,12 +2947,33 @@ void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ct * stop at 0 and we wait for a UE release command from upper layers */ if (sched_ctrl->ul_failure_timer == 1) { f1_ue_data_t ue_data = du_get_f1_ue_data(rnti); - f1ap_ue_context_release_complete_t complete = { + f1ap_ue_context_release_req_t request = { .gNB_CU_ue_id = ue_data.secondary_ue, .gNB_DU_ue_id = rnti, .cause = F1AP_CAUSE_RADIO_NETWORK, - .cause_value = 12, // F1AP_CauseRadioNetwork_rl_failure_others + .cause_value = F1AP_CauseRadioNetwork_rl_failure_others, }; - nrmac->mac_rrc.ue_context_release_request(&complete); + nrmac->mac_rrc.ue_context_release_request(&request); } } + +void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE) +{ + DevAssert(UE->CellGroup != NULL); + uint8_t buf[2048]; + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, UE->CellGroup, buf, sizeof(buf)); + AssertFatal(enc_rval.encoded > 0, "ASN1 encoding of CellGroupConfig failed, failed type %s\n", enc_rval.failed_type->name); + du_to_cu_rrc_information_t du2cu = { + .cellGroupConfig = buf, + .cellGroupConfig_length = (enc_rval.encoded + 7) >> 3, + }; + f1_ue_data_t ue_data = du_get_f1_ue_data(UE->rnti); + f1ap_ue_context_modif_required_t required = { + .gNB_CU_ue_id = ue_data.secondary_ue, + .gNB_DU_ue_id = UE->rnti, + .du_to_cu_rrc_information = &du2cu, + .cause = F1AP_CAUSE_RADIO_NETWORK, + .cause_value = F1AP_CauseRadioNetwork_action_desirable_for_radio_reasons, + }; + nrmac->mac_rrc.ue_context_modification_required(&required); +} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 1f04596fa7..2ff175f34c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -952,7 +952,8 @@ static NR_UE_harq_t *find_harq(frame_t frame, sub_frame_t slot, NR_UE_info_t * U while (harq->feedback_frame != frame || (harq->feedback_frame == frame && harq->feedback_slot < slot)) { LOG_W(NR_MAC, - "expected HARQ pid %d feedback at %4d.%2d, but is at %4d.%2d instead (HARQ feedback is in the past)\n", + "UE %04x expected HARQ pid %d feedback at %4d.%2d, but is at %4d.%2d instead (HARQ feedback is in the past)\n", + UE->rnti, pid, harq->feedback_frame, harq->feedback_slot, @@ -968,7 +969,8 @@ static NR_UE_harq_t *find_harq(frame_t frame, sub_frame_t slot, NR_UE_info_t * U /* feedbacks that we wait for in the future: don't do anything */ if (harq->feedback_slot > slot) { LOG_W(NR_MAC, - "expected HARQ pid %d feedback at %4d.%2d, but is at %4d.%2d instead (HARQ feedback is in the future)\n", + "UE %04x expected HARQ pid %d feedback at %4d.%2d, but is at %4d.%2d instead (HARQ feedback is in the future)\n", + UE->rnti, pid, harq->feedback_frame, harq->feedback_slot, @@ -1001,7 +1003,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; NR_UE_harq_t *harq = find_harq(frame, slot, UE, nrmac->dl_bler.harq_round_max); if (!harq) { - LOG_E(NR_MAC, "Oh no! Could not find a harq in %s!\n", __FUNCTION__); + LOG_E(NR_MAC, "UE %04x: Could not find a HARQ process at %4d.%2d!\n", UE->rnti, frame, slot); break; } DevAssert(harq->is_waiting); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 78d3397e60..cb42680ae9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -223,9 +223,14 @@ static int nr_process_mac_pdu(instance_t module_idP, for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i]; if (ra->state >= WAIT_Msg3 && ra->rnti == UE->rnti) { - ra->crnti = ((pduP[1]&0xFF)<<8)|(pduP[2]&0xFF); + // remove UE context just created after Msg.3 in some milliseconds + // as the UE is one already known (not now, as the UE context is + // still needed for the moment) + nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); + //mac_remove_nr_ue(RC.nrmac[module_idP], ra->rnti); + // this UE is the one identified by the RNTI in pduP + ra->rnti = ((pduP[1]&0xFF)<<8)|(pduP[2]&0xFF); ra->state = Msg3_dcch_dtch; - LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x\n", ra->crnti); break; } } @@ -780,12 +785,13 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, if (ra->state == Msg3_dcch_dtch) { // Check if the UE identified by C-RNTI still exists at the gNB - NR_UE_info_t * UE_C = find_nr_UE(&gNB_mac->UE_info, ra->crnti); + NR_UE_info_t * UE_C = find_nr_UE(&gNB_mac->UE_info, ra->rnti); if (!UE_C) { // The UE identified by C-RNTI no longer exists at the gNB // Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better solution may be implemented mac_remove_nr_ue(gNB_mac, ra->rnti); nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); + LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg.3 to have UE come back with new RA attempt\n", ra->rnti); return; } else { // The UE identified by C-RNTI still exists at the gNB @@ -794,9 +800,11 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, // Reset HARQ processes reset_dl_harq_list(&UE_C->UE_sched_ctrl); reset_ul_harq_list(&UE_C->UE_sched_ctrl); + + // Trigger RRC Reconfiguration + LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", UE_C->rnti); + nr_mac_trigger_reconfiguration(RC.nrmac[gnb_mod_idP], UE_C); } - LOG_I(NR_MAC, "Activating scheduling response to MSG3 with DCCH/DTCCH and RNTI 0x%04x (state %d)\n", - ra->crnti, ra->state); } else { LOG_I(NR_MAC, "Activating scheduling RA-Msg4 for TC_RNTI 0x%04x (state %d)\n", diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 073da246f1..15d823aaf2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -449,4 +449,6 @@ void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpac void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl); void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl); +void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE); + #endif /*__LAYER2_NR_MAC_PROTO_H__*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 0a450a1198..e78b66fded 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -25,6 +25,7 @@ #include "openair2/F1AP/f1ap_ids.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "openair2/RRC/NR/MESSAGES/asn1_msg.h" +#include "F1AP_CauseRadioNetwork.h" #include "uper_decoder.h" #include "uper_encoder.h" @@ -243,6 +244,63 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) } } +void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm) +{ + LOG_I(MAC, "Received UE Context Modification Confirm for UE %04x\n", confirm->gNB_DU_ue_id); + + gNB_MAC_INST *mac = RC.nrmac[0]; + NR_SCHED_LOCK(&mac->sched_lock); + /* check first that the scheduler knows such UE */ + NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, confirm->gNB_DU_ue_id); + if (UE == NULL) { + LOG_E(MAC, "ERROR: unknown UE with RNTI %04x, ignoring UE Context Modification Confirm\n", confirm->gNB_DU_ue_id); + NR_SCHED_UNLOCK(&mac->sched_lock); + return; + } + NR_SCHED_UNLOCK(&mac->sched_lock); + + if (confirm->rrc_container_length > 0) + nr_rlc_srb_recv_sdu(confirm->gNB_DU_ue_id, DCCH, confirm->rrc_container, confirm->rrc_container_length); + + /* nothing else to be done? */ +} + +void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse) +{ + /* Currently, we only use the UE Context Modification Required procedure to + * trigger a RRC reconfigurtion after Msg.3 with C-RNTI MAC CE. If the CU + * refuses, it cannot do this reconfiguration, leaving the UE in an + * unconfigured state. Therefore, we just free all RA-related info, and + * request the release of the UE. */ + LOG_W(MAC, "Received UE Context Modification Refuse for %04x, requesting release\n", refuse->gNB_DU_ue_id); + + gNB_MAC_INST *mac = RC.nrmac[0]; + NR_SCHED_LOCK(&mac->sched_lock); + NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, refuse->gNB_DU_ue_id); + if (UE == NULL) { + LOG_E(MAC, "ERROR: unknown UE with RNTI %04x, ignoring UE Context Modification Refuse\n", refuse->gNB_DU_ue_id); + NR_SCHED_UNLOCK(&mac->sched_lock); + return; + } + + const int CC_id = 0; + NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + NR_RA_t *ra = &cc->ra[i]; + if (ra->rnti == UE->rnti) + nr_clear_ra_proc(0, CC_id, 0 /* frame */, ra); + } + NR_SCHED_UNLOCK(&mac->sched_lock); + + f1ap_ue_context_release_req_t request = { + .gNB_CU_ue_id = refuse->gNB_CU_ue_id, + .gNB_DU_ue_id = refuse->gNB_DU_ue_id, + .cause = F1AP_CAUSE_RADIO_NETWORK, + .cause_value = F1AP_CauseRadioNetwork_procedure_cancelled, + }; + mac->mac_rrc.ue_context_release_request(&request); +} + void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd) { /* mark UE as to be deleted after PUSCH failure */ diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h index 859e128b4a..ebe6ba5adc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h @@ -27,6 +27,8 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req); void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req); +void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm); +void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse); void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd); void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index 5d7a7cd644..43a4818e93 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -28,6 +28,7 @@ typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t* req, const f1ap_ue_context_setup_t *resp); typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_req_t *req, const f1ap_ue_context_modif_resp_t *resp); +typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t); typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_release_req_t* req); typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_release_complete_t *complete); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index a024abe6af..dab70b5e82 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -111,6 +111,31 @@ static void ue_context_modification_response_direct(const f1ap_ue_context_modif_ itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } +static void ue_context_modification_required_direct(const f1ap_ue_context_modif_required_t *required) +{ + MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQUIRED); + f1ap_ue_context_modif_required_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg); + f1ap_msg->gNB_CU_ue_id = required->gNB_CU_ue_id; + f1ap_msg->gNB_DU_ue_id = required->gNB_DU_ue_id; + f1ap_msg->du_to_cu_rrc_information = NULL; + if (required->du_to_cu_rrc_information != NULL) { + f1ap_msg->du_to_cu_rrc_information = calloc(1, sizeof(*f1ap_msg->du_to_cu_rrc_information)); + AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); + du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; + AssertFatal(required->du_to_cu_rrc_information->cellGroupConfig != NULL && required->du_to_cu_rrc_information->cellGroupConfig_length > 0, + "cellGroupConfig is mandatory\n"); + du2cu->cellGroupConfig_length = required->du_to_cu_rrc_information->cellGroupConfig_length; + du2cu->cellGroupConfig = malloc(du2cu->cellGroupConfig_length * sizeof(*du2cu->cellGroupConfig)); + AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); + memcpy(du2cu->cellGroupConfig, required->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); + AssertFatal(required->du_to_cu_rrc_information->measGapConfig == NULL && required->du_to_cu_rrc_information->measGapConfig_length == 0, "not handled yet\n"); + AssertFatal(required->du_to_cu_rrc_information->requestedP_MaxFR1 == NULL && required->du_to_cu_rrc_information->requestedP_MaxFR1_length == 0, "not handled yet\n"); + } + f1ap_msg->cause = required->cause; + f1ap_msg->cause_value = required->cause_value; + itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); +} + static void ue_context_release_request_direct(const f1ap_ue_context_release_req_t* req) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_REQ); @@ -151,6 +176,7 @@ void mac_rrc_ul_direct_init(struct nr_mac_rrc_ul_if_s *mac_rrc) { mac_rrc->ue_context_setup_response = ue_context_setup_response_direct; mac_rrc->ue_context_modification_response = ue_context_modification_response_direct; + mac_rrc->ue_context_modification_required = ue_context_modification_required_direct; mac_rrc->ue_context_release_request = ue_context_release_request_direct; mac_rrc->ue_context_release_complete = ue_context_release_complete_direct; mac_rrc->initial_ul_rrc_message_transfer = initial_ul_rrc_message_transfer_direct; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 644decc21c..c873c569e5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -96,6 +96,31 @@ static void ue_context_modification_response_f1ap(const f1ap_ue_context_modif_re itti_send_msg_to_task(TASK_DU_F1, 0, msg); } +static void ue_context_modification_required_f1ap(const f1ap_ue_context_modif_required_t *required) +{ + MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQUIRED); + f1ap_ue_context_modif_required_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg); + f1ap_msg->gNB_CU_ue_id = required->gNB_CU_ue_id; + f1ap_msg->gNB_DU_ue_id = required->gNB_DU_ue_id; + f1ap_msg->du_to_cu_rrc_information = NULL; + if (required->du_to_cu_rrc_information != NULL) { + f1ap_msg->du_to_cu_rrc_information = calloc(1, sizeof(*f1ap_msg->du_to_cu_rrc_information)); + AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); + du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; + AssertFatal(required->du_to_cu_rrc_information->cellGroupConfig != NULL && required->du_to_cu_rrc_information->cellGroupConfig_length > 0, + "cellGroupConfig is mandatory\n"); + du2cu->cellGroupConfig_length = required->du_to_cu_rrc_information->cellGroupConfig_length; + du2cu->cellGroupConfig = malloc(du2cu->cellGroupConfig_length * sizeof(*du2cu->cellGroupConfig)); + AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); + memcpy(du2cu->cellGroupConfig, required->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); + AssertFatal(required->du_to_cu_rrc_information->measGapConfig == NULL && required->du_to_cu_rrc_information->measGapConfig_length == 0, "not handled yet\n"); + AssertFatal(required->du_to_cu_rrc_information->requestedP_MaxFR1 == NULL && required->du_to_cu_rrc_information->requestedP_MaxFR1_length == 0, "not handled yet\n"); + } + f1ap_msg->cause = required->cause; + f1ap_msg->cause_value = required->cause_value; + itti_send_msg_to_task(TASK_DU_F1, 0, msg); +} + static void ue_context_release_request_f1ap(const f1ap_ue_context_release_req_t* req) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_REQ); @@ -138,6 +163,7 @@ void mac_rrc_ul_f1ap_init(struct nr_mac_rrc_ul_if_s *mac_rrc) { mac_rrc->ue_context_setup_response = ue_context_setup_response_f1ap; mac_rrc->ue_context_modification_response = ue_context_modification_response_f1ap; + mac_rrc->ue_context_modification_required = ue_context_modification_required_f1ap; mac_rrc->ue_context_release_request = ue_context_release_request_f1ap; mac_rrc->ue_context_release_complete = ue_context_release_complete_f1ap; mac_rrc->initial_ul_rrc_message_transfer = initial_ul_rrc_message_transfer_f1ap; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 457497679a..4bec3664c8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -204,8 +204,6 @@ typedef struct { NR_CellGroupConfig_t *CellGroup; /// Preambles for contention-free access NR_preamble_ue_t preambles; - /// NSA: the UEs C-RNTI to use - rnti_t crnti; /// CFRA flag bool cfra; // BWP for RA @@ -660,6 +658,7 @@ typedef struct NR_bler_options { typedef struct nr_mac_rrc_ul_if_s { ue_context_setup_response_func_t ue_context_setup_response; ue_context_modification_response_func_t ue_context_modification_response; + ue_context_modification_required_func_t ue_context_modification_required; ue_context_release_request_func_t ue_context_release_request; ue_context_release_complete_func_t ue_context_release_complete; initial_ul_rrc_message_transfer_func_t initial_ul_rrc_message_transfer; diff --git a/openair2/RRC/NR/mac_rrc_dl.h b/openair2/RRC/NR/mac_rrc_dl.h index 94920f6f64..0180f972fe 100644 --- a/openair2/RRC/NR/mac_rrc_dl.h +++ b/openair2/RRC/NR/mac_rrc_dl.h @@ -27,6 +27,8 @@ typedef void (*ue_context_setup_request_func_t)(const f1ap_ue_context_setup_t *req); typedef void (*ue_context_modification_request_func_t)(const f1ap_ue_context_modif_req_t *req); +typedef void (*ue_context_modification_confirm_func_t)(const f1ap_ue_context_modif_confirm_t *confirm); +typedef void (*ue_context_modification_refuse_func_t)(const f1ap_ue_context_modif_refuse_t *refuse); typedef void (*ue_context_release_command_func_t)(const f1ap_ue_context_release_cmd_t *cmd); typedef void (*dl_rrc_message_transfer_func_t)(const f1ap_dl_rrc_message_t *dl_rrc); diff --git a/openair2/RRC/NR/mac_rrc_dl_direct.c b/openair2/RRC/NR/mac_rrc_dl_direct.c index eeec72e132..423eac2462 100644 --- a/openair2/RRC/NR/mac_rrc_dl_direct.c +++ b/openair2/RRC/NR/mac_rrc_dl_direct.c @@ -28,6 +28,8 @@ void mac_rrc_dl_direct_init(nr_mac_rrc_dl_if_t *mac_rrc) { mac_rrc->ue_context_setup_request = ue_context_setup_request; mac_rrc->ue_context_modification_request = ue_context_modification_request; + mac_rrc->ue_context_modification_confirm = ue_context_modification_confirm; + mac_rrc->ue_context_modification_refuse = ue_context_modification_refuse; mac_rrc->ue_context_release_command = ue_context_release_command; mac_rrc->dl_rrc_message_transfer = dl_rrc_message_transfer; } diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 3f3b0f800f..40eea4861c 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -71,6 +71,31 @@ static void ue_context_modification_request_f1ap(const f1ap_ue_context_modif_req itti_send_msg_to_task(TASK_CU_F1, 0, msg); } +static void ue_context_modification_confirm_f1ap(const f1ap_ue_context_modif_confirm_t *confirm) +{ + MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_CONFIRM); + f1ap_ue_context_modif_confirm_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_CONFIRM(msg); + f1ap_msg->gNB_CU_ue_id = confirm->gNB_CU_ue_id; + f1ap_msg->gNB_DU_ue_id = confirm->gNB_DU_ue_id; + f1ap_msg->rrc_container = NULL; + f1ap_msg->rrc_container_length = 0; + if (confirm->rrc_container != NULL) { + f1ap_msg->rrc_container = calloc(1, sizeof(*f1ap_msg->rrc_container)); + AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n"); + memcpy(f1ap_msg->rrc_container, confirm->rrc_container, confirm->rrc_container_length); + f1ap_msg->rrc_container_length = confirm->rrc_container_length; + } + itti_send_msg_to_task(TASK_CU_F1, 0, msg); +} + +static void ue_context_modification_refuse_f1ap(const f1ap_ue_context_modif_refuse_t *refuse) +{ + MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REFUSE); + f1ap_ue_context_modif_refuse_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REFUSE(msg); + *f1ap_msg = *refuse; + itti_send_msg_to_task(TASK_CU_F1, 0, msg); +} + static void ue_context_release_command_f1ap(const f1ap_ue_context_release_cmd_t *cmd) { MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_CMD); @@ -110,6 +135,8 @@ void mac_rrc_dl_f1ap_init(nr_mac_rrc_dl_if_t *mac_rrc) { mac_rrc->ue_context_setup_request = ue_context_setup_request_f1ap; mac_rrc->ue_context_modification_request = ue_context_modification_request_f1ap; + mac_rrc->ue_context_modification_confirm = ue_context_modification_confirm_f1ap; + mac_rrc->ue_context_modification_refuse = ue_context_modification_refuse_f1ap; mac_rrc->ue_context_release_command = ue_context_release_command_f1ap; mac_rrc->dl_rrc_message_transfer = dl_rrc_message_transfer_f1ap; } diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index f9c821736c..35ff709378 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -365,6 +365,8 @@ typedef struct { typedef struct nr_mac_rrc_dl_if_s { ue_context_setup_request_func_t ue_context_setup_request; ue_context_modification_request_func_t ue_context_modification_request; + ue_context_modification_confirm_func_t ue_context_modification_confirm; + ue_context_modification_refuse_func_t ue_context_modification_refuse; ue_context_release_command_func_t ue_context_release_command; dl_rrc_message_transfer_func_t dl_rrc_message_transfer; } nr_mac_rrc_dl_if_t; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 1fa458a309..3df2b36142 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -43,7 +43,6 @@ #include "rrc_gNB_radio_bearers.h" #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" -#include "LAYER2/RLC/rlc.h" #include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "common/utils/LOG/log.h" #include "COMMON/mac_rrc_primitives.h" @@ -68,7 +67,6 @@ #include "uper_encoder.h" #include "uper_decoder.h" -#include "rlc.h" #include "platform_types.h" #include "common/utils/LOG/vcd_signal_dumper.h" @@ -188,26 +186,6 @@ static void freeDRBlist(NR_DRB_ToAddModList_t *list) return; } -static void nr_rrc_addmod_drbs(int rnti, - const NR_DRB_ToAddModList_t *drb_list, - const struct NR_CellGroupConfig__rlc_BearerToAddModList *bearer_list) -{ - if (drb_list == NULL || bearer_list == NULL) - return; - - for (int i = 0; i < drb_list->list.count; i++) { - const NR_DRB_ToAddMod_t *drb = drb_list->list.array[i]; - for (int j = 0; j < bearer_list->list.count; j++) { - const NR_RLC_BearerConfig_t *bearer = bearer_list->list.array[j]; - if (bearer->servedRadioBearer != NULL - && bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity - && drb->drb_Identity == bearer->servedRadioBearer->choice.drb_Identity) { - nr_rlc_add_drb(rnti, drb->drb_Identity, bearer); - } - } - } -} - typedef struct deliver_dl_rrc_message_data_s { const gNB_RRC_INST *rrc; f1ap_dl_rrc_message_t *dl_rrc; @@ -994,14 +972,6 @@ static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *co kUPint, get_softmodem_params()->sa ? ue_p->masterCellGroup->rlc_BearerToAddModList : NULL); - /* Refresh DRBs */ - if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) { - LOG_D(NR_RRC,"Configuring RLC DRBs/SRBs for UE %04x\n",ue_context_pP->ue_context.rnti); - const struct NR_CellGroupConfig__rlc_BearerToAddModList *bearer_list = - ue_context_pP->ue_context.masterCellGroup->rlc_BearerToAddModList; - nr_rrc_addmod_drbs(ctxt_pP->rntiMaybeUEid, DRB_configList, bearer_list); - } - /* Loop through DRBs and establish if necessary */ if (DRB_configList != NULL) { for (int i = 0; i < DRB_configList->list.count; i++) { @@ -1219,6 +1189,7 @@ int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + ue_p->xids[xid] = RRC_DEDICATED_RECONF; NR_CellGroupConfig_t *masterCellGroup = ue_p->masterCellGroup; if (dl_bwp_id > 0) { @@ -1247,18 +1218,22 @@ int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP NULL, masterCellGroup); - nr_rrc_mac_update_cellgroup(ue_context_pP->ue_context.rnti, masterCellGroup); - gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DCCH, buffer, size); if (NODE_IS_DU(rrc->node_type) || NODE_IS_MONOLITHIC(rrc->node_type)) { - uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated + nr_rrc_mac_update_cellgroup(ue_context_pP->ue_context.rnti, masterCellGroup); + + uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig + && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList ? NR_RRC_RECONFIGURATION_DELAY_MS + NR_RRC_BWP_SWITCHING_DELAY_MS : NR_RRC_RECONFIGURATION_DELAY_MS; - nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, ue_p->rnti, *rrc->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, delay_ms); + nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, + ue_p->rnti, + *rrc->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, + delay_ms); } return 0; @@ -1711,6 +1686,7 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_ rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); break; case RRC_REESTABLISH_COMPLETE: + case RRC_DEDICATED_RECONF: /* do nothing */ break; default: @@ -2131,6 +2107,69 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i } } +static void rrc_CU_process_ue_modification_required(MessageDef *msg_p) +{ + f1ap_ue_context_modif_required_t *required = &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg_p); + protocol_ctxt_t ctxt = {.rntiMaybeUEid = required->gNB_CU_ue_id, .module_id = 0, .instance = 0, .enb_flag = 1, .eNB_index = 0}; + gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, required->gNB_CU_ue_id); + if (ue_context_p == NULL) { + LOG_E(RRC, "Could not find UE context for CU UE ID %d, cannot handle UE context modification request\n", required->gNB_CU_ue_id); + f1ap_ue_context_modif_refuse_t refuse = { + .gNB_CU_ue_id = required->gNB_CU_ue_id, + .gNB_DU_ue_id = required->gNB_DU_ue_id, + .cause = F1AP_CAUSE_RADIO_NETWORK, + .cause_value = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_cu_ue_f1ap_id, + }; + rrc->mac_rrc.ue_context_modification_refuse(&refuse); + return; + } + + if (required->du_to_cu_rrc_information && required->du_to_cu_rrc_information->cellGroupConfig) { + gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + LOG_I(RRC, + "UE Context Modification Required: new CellGroupConfig for UE ID %d/RNTI %04x, triggering reconfiguration\n", + UE->rrc_ue_id, + UE->rnti); + + NR_CellGroupConfig_t *cellGroupConfig = NULL; + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, + &asn_DEF_NR_CellGroupConfig, + (void **)&cellGroupConfig, + (uint8_t *)required->du_to_cu_rrc_information->cellGroupConfig, + required->du_to_cu_rrc_information->cellGroupConfig_length); + if (dec_rval.code != RC_OK && dec_rval.consumed == 0) { + LOG_E(RRC, "Cell group config decode error, refusing reconfiguration\n"); + f1ap_ue_context_modif_refuse_t refuse = { + .gNB_CU_ue_id = required->gNB_CU_ue_id, + .gNB_DU_ue_id = required->gNB_DU_ue_id, + .cause = F1AP_CAUSE_PROTOCOL, + .cause_value = F1AP_CauseProtocol_transfer_syntax_error, + }; + rrc->mac_rrc.ue_context_modification_refuse(&refuse); + return; + } + + if (UE->masterCellGroup) { + ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); + LOG_I(RRC, "UE %d/RNTI %04x replacing existing CellGroupConfig with new one received from DU\n", UE->rrc_ue_id, UE->rnti); + } + UE->masterCellGroup = cellGroupConfig; + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); + + /* trigger reconfiguration */ + nr_rrc_reconfiguration_req(ue_context_p, &ctxt, 0, 0); + //rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p); + //rrc_gNB_generate_defaultRRCReconfiguration(&ctxt, ue_context_p); + return; + } + LOG_W(RRC, + "nothing to be done after UE Context Modification Required for UE ID %d/RNTI %04x\n", + required->gNB_CU_ue_id, + required->gNB_DU_ue_id); +} + unsigned int mask_flip(unsigned int x) { return((((x>>8) + (x<<8))&0xffff)>>6); } @@ -2598,6 +2637,10 @@ void *rrc_gnb_task(void *args_p) { rrc_CU_process_ue_context_modification_response(msg_p, instance); break; + case F1AP_UE_CONTEXT_MODIFICATION_REQUIRED: + rrc_CU_process_ue_modification_required(msg_p); + break; + case F1AP_UE_CONTEXT_RELEASE_REQ: rrc_CU_process_ue_context_release_request(msg_p); break;