From cd8cfab768251222d3cdd771d9fb517087d4a35c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 11 Jul 2023 12:57:53 +0200 Subject: [PATCH 01/14] Remove MAC_NR target: it is not needed The MAC_NR target is not needed; every dependent target also links L2_NR. Therefore, this target just creates double compilation. We can remove it without problems. --- CMakeLists.txt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) 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}) From 7746897f0e11e94ccc061901d1dca73167c843d6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 15 Jun 2023 09:42:50 +0200 Subject: [PATCH 02/14] Fix: use correct type for F1 UE Context Release Req --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 81ea2edcb7..19a2641b58 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -48,6 +48,7 @@ #include "intertask_interface.h" #include "openair2/F1AP/f1ap_ids.h" +#include "F1AP_CauseRadioNetwork.h" #include "T.h" @@ -2985,12 +2986,12 @@ 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); } } From 7fbccc709ad42005ae396a4d40c493259fc44bce Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 14 Aug 2023 15:48:59 +0200 Subject: [PATCH 03/14] Do not trigger RLC bearer establishment from RRC The RRC should not trigger RLC bearer establishment: this should be done only via F1, and in the remaining code (removed here), this principle was violated. Further, this code was doubly wrong, as it used the CU UE ID for the RLC, setting up bearers with IDs 1,2,3 etc instead of the RNTI. --- openair2/RRC/NR/rrc_gNB.c | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 1fa458a309..32930a4256 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++) { From 57be09efafce09599610f113f1d4983ce58507b8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 4 Jun 2023 02:10:48 +0200 Subject: [PATCH 04/14] Stubs for F1 UE Context Modification Required/Confirm/Refuse --- openair2/COMMON/f1ap_messages_def.h | 3 +++ openair2/COMMON/f1ap_messages_types.h | 25 +++++++++++++++++++ openair2/F1AP/f1ap_cu_task.c | 10 ++++++++ openair2/F1AP/f1ap_cu_ue_context_management.c | 22 ++++++++++------ openair2/F1AP/f1ap_cu_ue_context_management.h | 11 ++++---- openair2/F1AP/f1ap_du_task.c | 4 +++ openair2/F1AP/f1ap_du_ue_context_management.c | 23 +++++++++++------ openair2/F1AP/f1ap_du_ue_context_management.h | 10 +++----- openair2/F1AP/f1ap_handlers.c | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 12 +++++++++ .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h | 2 ++ openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 1 + .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 6 +++++ openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 6 +++++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + openair2/RRC/NR/mac_rrc_dl.h | 2 ++ openair2/RRC/NR/mac_rrc_dl_direct.c | 2 ++ openair2/RRC/NR/mac_rrc_dl_f1ap.c | 14 +++++++++++ openair2/RRC/NR/nr_rrc_defs.h | 2 ++ 19 files changed, 130 insertions(+), 28 deletions(-) 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..b5d3ea0ec8 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -1701,14 +1701,20 @@ 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) +{ + AssertFatal(false, "%s() not implemented yet\n", __func__); + 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) +{ + AssertFatal(false, "%s() not implemented yet\n", __func__); + 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__); + 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..69410f3bc5 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -1285,12 +1285,21 @@ 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) +{ + AssertFatal(false, "%s() not implemented yet\n", __func__); + 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) +{ + AssertFatal(false, "%s() not implemented yet\n", __func__); + 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__); + 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 8b6cc38fec..259de1f9d5 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/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 0a450a1198..7e6df48e38 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -243,6 +243,18 @@ 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) confirm; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + +void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse) +{ + (void) refuse; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + 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..bb7cec2e87 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,11 @@ 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) +{ + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + 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 +156,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..c3138c4a5c 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,11 @@ 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) +{ + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + 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 +143,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..2197871845 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -660,6 +660,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..3d554f80cc 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -71,6 +71,18 @@ 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) +{ + (void)confirm; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + +static void ue_context_modification_refuse_f1ap(const f1ap_ue_context_modif_refuse_t *refuse) +{ + (void)refuse; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + 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 +122,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; From bb63aa79b23ccd402387482e5389866f04e778ac Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 5 Jun 2023 14:08:00 +0200 Subject: [PATCH 05/14] 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; } From e72fa6aa39234a95c0f6ef68735109dd04984d6d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 15 Jun 2023 11:43:08 +0200 Subject: [PATCH 06/14] Implement F1 handlers --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 22 +++++++++++++++++++- openair2/RRC/NR/mac_rrc_dl_f1ap.c | 21 +++++++++++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) 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 c3138c4a5c..c873c569e5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -98,7 +98,27 @@ static void ue_context_modification_response_f1ap(const f1ap_ue_context_modif_re static void ue_context_modification_required_f1ap(const f1ap_ue_context_modif_required_t *required) { - AssertFatal(false, "%s() not implemented yet\n", __func__); + 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) diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 3d554f80cc..40eea4861c 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -73,14 +73,27 @@ static void ue_context_modification_request_f1ap(const f1ap_ue_context_modif_req static void ue_context_modification_confirm_f1ap(const f1ap_ue_context_modif_confirm_t *confirm) { - (void)confirm; - AssertFatal(false, "%s() not implemented yet\n", __func__); + 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) { - (void)refuse; - AssertFatal(false, "%s() not implemented yet\n", __func__); + 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) From 633795118299fc5a568a21c1c28896a436419c6e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 5 Jun 2023 14:27:14 +0200 Subject: [PATCH 07/14] UE Context Modification Required: add RRC handler --- openair2/RRC/NR/rrc_gNB.c | 69 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 32930a4256..7349e871c7 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1189,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) { @@ -1681,6 +1682,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: @@ -2101,6 +2103,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); } @@ -2568,6 +2633,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; From d40db13e2a7a5eee22277a8c8a5821ddd3aba610 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 3 Jul 2023 10:56:24 +0200 Subject: [PATCH 08/14] Make reconfiguration work --- openair2/RRC/NR/rrc_gNB.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 7349e871c7..3df2b36142 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1218,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; From 3b87dd30a0e8b3e36fe42c623cfff0d38b5dee6e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 15 Jun 2023 09:43:37 +0200 Subject: [PATCH 09/14] Implement ue_context_modification_required_direct() --- .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) 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 bb7cec2e87..dab70b5e82 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -113,7 +113,27 @@ static void ue_context_modification_response_direct(const f1ap_ue_context_modif_ static void ue_context_modification_required_direct(const f1ap_ue_context_modif_required_t *required) { - AssertFatal(false, "%s() not implemented yet\n", __func__); + 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) From 7b7f045f1c0639f5d08929f372dcd417efbc9e18 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 15 Jun 2023 09:44:11 +0200 Subject: [PATCH 10/14] DU: trigger UE Context Modification Required and handle --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 22 ++++++++ .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 8 +-- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 + .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 54 +++++++++++++++++-- 4 files changed, 79 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 19a2641b58..fc161e1e30 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -43,6 +43,7 @@ #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" @@ -2995,3 +2996,24 @@ void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ct 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_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 0bc137f910..18693ac20e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -225,7 +225,6 @@ static int nr_process_mac_pdu(instance_t module_idP, if (ra->state >= WAIT_Msg3 && ra->rnti == UE->rnti) { ra->crnti = ((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; } } @@ -786,6 +785,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, // 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->crnti); return; } else { // The UE identified by C-RNTI still exists at the gNB @@ -794,9 +794,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 10ba95928d..4d49dc51db 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -447,4 +447,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 7e6df48e38..404eebc3b5 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" @@ -245,14 +246,59 @@ 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) confirm; - AssertFatal(false, "%s() not implemented yet\n", __func__); + 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) { - (void) refuse; - AssertFatal(false, "%s() not implemented yet\n", __func__); + /* 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->crnti == 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) From 93f59a3c6e56fef265156c57bdc28f0b43c63d48 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 14 Aug 2023 15:34:18 +0200 Subject: [PATCH 11/14] Remove RA.crnti: it is not needed anymore The RA.crnti field is marked as being used by NSA mode, but it is not. OTOH, it is used in the case of RA with Msg.3 with C-RNTI MAC CE. The latter does not necessarily need it, though, as we can change the RNTI of the RA process when we receive C-RNTI MAC CE. This introduces a slight complication, though, as we cannot remove the MAC UE Context (generated when receiving Msg.3) directly when parsing the C-RNTI MAC CE. Previously, we had both rnti and crnti in the RA struct, and when sending Msg.4 after Msg.3 with C-RNTI MAC CE, we would remove the UE context (this is changed in the next commit). Therefore, we employ nr_mac_trigger_release_timer() which releases the UE after 60ms, circumventing this complication. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 7 +------ openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 12 +++++++++--- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 -- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 165251e9f4..b1081ee631 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1630,7 +1630,7 @@ static void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, return; // UE is known by the network, C-RNTI to be used instead of TC-RNTI - int rnti = ra->crnti; + int rnti = ra->rnti; NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, rnti); if (!UE) { @@ -1731,10 +1731,6 @@ static void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, 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]; @@ -2113,7 +2109,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; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 18693ac20e..1f612e0ecd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -223,7 +223,13 @@ 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; break; } @@ -779,13 +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->crnti); + 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 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 404eebc3b5..e78b66fded 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -287,7 +287,7 @@ void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse 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->crnti == UE->rnti) + if (ra->rnti == UE->rnti) nr_clear_ra_proc(0, CC_id, 0 /* frame */, ra); } NR_SCHED_UNLOCK(&mac->sched_lock); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 2197871845..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 From 27f9d6f7432fd026605ba4c7d26c746726397517 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 14 Aug 2023 14:56:13 +0200 Subject: [PATCH 12/14] Use nr_generate_Msg4() in the case of Msg.3 with C-RNTI After removing RA.crnti, there is no need to use a separate function nr_generate_Msg3_dcch_dtch_response() to generate Msg.4 (yes, the function mentions Msg3 but it does Msg3 response == Msg.4). Also, using nr_generate_Msg4() has the advantage that it waits until we have the reconfiguration available in RLC to be sent to the UE. Finally, we can delete the old nr_generate_Msg3_dcch_dtch_response() as we don't need it anymore. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 189 +----------------- 1 file changed, 3 insertions(+), 186 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index b1081ee631..92db11c24d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1615,188 +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->rnti; - - 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; - } - - // 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, @@ -1810,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; @@ -1838,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); } @@ -2266,7 +2083,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; From 35b5782968745891fbc3fbe6674b3b2d08ec05ca Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 17 Aug 2023 18:42:38 +0200 Subject: [PATCH 13/14] CI F1 and F1+E1 tests: increase attenuation to stabilize connection --- ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml | 2 +- ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 From 31af346ebcce608662ca884e9c6b9c51645e6c63 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 18 Aug 2023 12:34:25 +0200 Subject: [PATCH 14/14] Improve log messages for debugging --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 5 +---- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 8 +++++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 92db11c24d..bdf84ddc8e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1768,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, @@ -1824,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); } @@ -1867,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); } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index cf6001626d..893274de64 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -894,7 +894,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, @@ -910,7 +911,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, @@ -943,7 +945,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);