diff --git a/ci-scripts/conf_files/neighbour-config.conf b/ci-scripts/conf_files/neighbour-config.conf index 12b023de7a..875129365e 100644 --- a/ci-scripts/conf_files/neighbour-config.conf +++ b/ci-scripts/conf_files/neighbour-config.conf @@ -62,12 +62,12 @@ nr_measurement_configuration = { }; A3 = ({ - cell_id = -1; #Default + physCellId = -1; #Default offset = 10; hysteresis = 0; timeToTrigger = 1 }, { - cell_id = 2; + physCellId = 2; offset = 5; hysteresis = 1; timeToTrigger = 2 diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index c1ed6c7546..f851c26eee 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1161,9 +1161,9 @@ void nr_timer_stop(NR_timer_t *timer) timer->counter = 0; } -bool is_nr_timer_active(NR_timer_t timer) +bool nr_timer_is_active(const NR_timer_t *timer) { - return timer.active; + return timer->active; } bool nr_timer_tick(NR_timer_t *timer) @@ -1173,23 +1173,23 @@ bool nr_timer_tick(NR_timer_t *timer) timer->counter += timer->step; if (timer->target == UINT_MAX) // infinite target, never expires return false; - expired = nr_timer_expired(*timer); + expired = nr_timer_expired(timer); if (expired) timer->active = false; } return expired; } -bool nr_timer_expired(NR_timer_t timer) +bool nr_timer_expired(const NR_timer_t *timer) { - if (timer.target == UINT_MAX) // infinite target, never expires + if (timer->target == UINT_MAX) // infinite target, never expires return false; - return (timer.counter >= timer.target); + return timer->counter >= timer->target; } -uint32_t nr_timer_elapsed_time(NR_timer_t timer) +uint32_t nr_timer_elapsed_time(const NR_timer_t *timer) { - return timer.counter; + return timer->counter; } void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t step) diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index cafeebb632..3c04bca581 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -163,19 +163,19 @@ void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t ste * @param timer Timer to be checked * @return Indication if the timer is expired or not */ -bool nr_timer_expired(NR_timer_t timer); +bool nr_timer_expired(const NR_timer_t *timer); /** * @brief To check if a timer is active * @param timer Timer to be checked * @return Indication if the timer is active or not */ -bool is_nr_timer_active(NR_timer_t timer); +bool nr_timer_is_active(const NR_timer_t *timer); /** * @brief To return how much time has passed since start of timer * @param timer Timer to be checked * @return Time passed since start of timer */ -uint32_t nr_timer_elapsed_time(NR_timer_t timer); +uint32_t nr_timer_elapsed_time(const NR_timer_t *timer); extern const nr_bandentry_t nr_bandtable[]; diff --git a/common/utils/nr/tests/test_nr_common.cpp b/common/utils/nr/tests/test_nr_common.cpp index fede91b8ee..c780736a51 100644 --- a/common/utils/nr/tests/test_nr_common.cpp +++ b/common/utils/nr/tests/test_nr_common.cpp @@ -29,13 +29,13 @@ TEST(nr_common, nr_timer) { NR_timer_t timer; nr_timer_setup(&timer, 10, 1); nr_timer_start(&timer); - EXPECT_TRUE(is_nr_timer_active(timer)); - EXPECT_FALSE(nr_timer_expired(timer)); + EXPECT_TRUE(nr_timer_is_active(&timer)); + EXPECT_FALSE(nr_timer_expired(&timer)); for (auto i = 0; i < 10; i++) { nr_timer_tick(&timer); } - EXPECT_FALSE(is_nr_timer_active(timer)); - EXPECT_TRUE(nr_timer_expired(timer)); + EXPECT_FALSE(nr_timer_is_active(&timer)); + EXPECT_TRUE(nr_timer_expired(&timer)); } diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index 9d22e06d7d..b59de2e0fc 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -320,7 +320,7 @@ typedef struct timer_elm_s { (char *)itti_get_task_name(task_id), -1, OAI_PRIORITY_RT); - LOG_I(ITTI,"Created Posix thread %s\n", itti_get_task_name(task_id) ); + LOG_D(ITTI,"Created Posix thread %s\n", itti_get_task_name(task_id) ); return 0; } diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index faeb11d377..861f5e6d2c 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -278,8 +278,6 @@ typedef struct pdusession_s { transport_layer_addr_t upf_addr; /* Outgoing (UL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */ uint32_t gtp_teid; - /* Stores the DRB ID of the DRBs used by this PDU Session */ - uint8_t used_drbs[MAX_DRBS_PER_UE]; /* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */ uint32_t gNB_teid_N3; transport_layer_addr_t gNB_addr_N3; diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index a320b92935..72e3d86ea2 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -64,27 +64,17 @@ static void cu_task_handle_sctp_association_ind(instance_t instance, static void cu_task_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) { DevAssert(sctp_new_association_resp != NULL); - if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN) { + enum sctp_state_e state = sctp_new_association_resp->sctp_state; + if (state != SCTP_STATE_ESTABLISHED) { f1ap_cudu_inst_t *f1ap_cu_data = getCxt(instance); AssertFatal(f1ap_cu_data != NULL, "illegal state: SCTP shutdown for non-existing F1AP endpoint\n"); - LOG_I(F1AP, "Received SCTP shutdown for assoc_id %d, removing endpoint\n", sctp_new_association_resp->assoc_id); + LOG_I(F1AP, "Received SCTP state %d for assoc_id %d, removing endpoint\n", state, sctp_new_association_resp->assoc_id); /* inform RRC that the DU is gone */ MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_LOST_CONNECTION); message_p->ittiMsgHeader.originInstance = sctp_new_association_resp->assoc_id; itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p); return; } - - if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - LOG_W(F1AP, "Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", - sctp_new_association_resp->sctp_state, - instance, - sctp_new_association_resp->ulp_cnx_id); - //if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN) - //proto_agent_stop(instance); - //f1ap_handle_setup_message(instance, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); - return; // exit -1 for debugging - } } static void cu_task_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) { diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 8c32e7bea6..6d9771f1f4 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -281,12 +281,9 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i memcpy(f1ap_ue_context_setup_req->rrc_container, ieRRC->value.choice.RRCContainer.buf, ieRRC->value.choice.RRCContainer.size); f1ap_ue_context_setup_req->rrc_container_length = ieRRC->value.choice.RRCContainer.size; - // AssertFatal(0, "check configuration, send to appropriate handler\n"); } else { LOG_E(F1AP, " RRCContainer in UEContextSetupRequestIEs size id 0\n"); } - } else { - LOG_W(F1AP, "can't find RRCContainer in UEContextSetupRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer); } ue_context_setup_request(f1ap_ue_context_setup_req); @@ -596,6 +593,7 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set F1AP_SRBs_Setup_Item_t *srbs_setup_item=&srbs_setup_item_ies->value.choice.SRBs_Setup_Item; /* sRBID */ srbs_setup_item->sRBID = resp->srbs_to_be_setup[i].srb_id; + srbs_setup_item->lCID = resp->srbs_to_be_setup[i].lcid; } } diff --git a/openair2/F1AP/f1ap_encoder.c b/openair2/F1AP/f1ap_encoder.c index 870dfd73fc..5de4ba43db 100644 --- a/openair2/F1AP/f1ap_encoder.c +++ b/openair2/F1AP/f1ap_encoder.c @@ -40,13 +40,13 @@ int f1ap_encode_pdu(F1AP_F1AP_PDU_t *pdu, uint8_t **buffer, uint32_t *length) { LOG_E(F1AP, "----------------- ASN1 ENCODER PRINT END----------------- \n"); } - char errbuf[128]; /* Buffer for error message */ + char errbuf[4096]; /* Buffer for error message */ size_t errlen = sizeof(errbuf); /* Size of the buffer */ int ret = asn_check_constraints(&asn_DEF_F1AP_F1AP_PDU, pdu, errbuf, &errlen); - /* assert(errlen < sizeof(errbuf)); // Guaranteed: you may rely on that */ if(ret) { - fprintf(stderr, "Constraint validation failed: %s\n", errbuf); + xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, pdu); + LOG_E(F1AP, "Constraint validation failed: %s\n", errbuf); } encoded = aper_encode_to_new_buffer(&asn_DEF_F1AP_F1AP_PDU, 0, pdu, (void **)buffer); diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 0dfe99e3cb..0cbe75bbeb 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1598,7 +1598,7 @@ static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc paramdef_t NeighbourCellParams[] = GNBNEIGHBOURCELLPARAMS_DESC; paramlist_def_t NeighbourCellParamList = {GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST, NULL, 0}; config_getlist(config_get_if(), &NeighbourCellParamList, NeighbourCellParams, sizeofArray(NeighbourCellParams), neighbourpath); - LOG_D(GNB_APP, "HO LOG: For the Cell: %d Neighbour Cell ELM NUM: %d\n", cell->nr_cell_id, NeighbourCellParamList.numelt); + LOG_D(GNB_APP, "HO LOG: For the Cell: %ld Neighbour Cell ELM NUM: %d\n", cell->nr_cell_id, NeighbourCellParamList.numelt); if (NeighbourCellParamList.numelt < 1) continue; @@ -1696,12 +1696,17 @@ static void fill_measurement_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc) for (int i = 0; i < A3_EventList.numelt; i++) { nr_a3_event_t *a3_event = (nr_a3_event_t *)calloc(1, sizeof(nr_a3_event_t)); AssertFatal(a3_event != NULL, "out of memory\n"); - a3_event->cell_id = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_CELL_ID_IDX].i64ptr; + a3_event->pci = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_PCI_ID_IDX].i64ptr; + AssertFatal(a3_event->pci >= -1 && a3_event->pci < 1024, + "entry %s.%s must be -1<=PCI<1024, but is %d\n", + measurement_path, + MEASUREMENT_EVENTS_PCI_ID, + a3_event->pci); a3_event->timeToTrigger = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_TIMETOTRIGGER_IDX].i64ptr; a3_event->a3_offset = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_OFFSET_IDX].i64ptr; a3_event->hysteresis = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_HYSTERESIS_IDX].i64ptr; - if (a3_event->cell_id == -1) + if (a3_event->pci == -1) measurementConfig->is_default_a3_configuration_exists = true; seq_arr_push_back(measurementConfig->a3_event_list, a3_event, sizeof(nr_a3_event_t)); diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index a5d8cc5b42..253d94b44a 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -324,12 +324,12 @@ typedef enum { #define MEASUREMENT_EVENTS_THRESHOLD "threshold" #define MEASUREMENT_EVENTS_PERIODICAL_BEAM_MEASUREMENT "includeBeamMeasurements" #define MEASUREMENT_EVENTS_PERIODICAL_NR_OF_RS_INDEXES "maxNrofRS_IndexesToReport" -#define MEASUREMENT_EVENTS_CELL_ID "cell_id" +#define MEASUREMENT_EVENTS_PCI_ID "physCellId" #define MEASUREMENT_EVENT_ENABLE "enable" // clang-format off #define MEASUREMENT_A3_GLOBALPARAMS_DESC \ { \ - {MEASUREMENT_EVENTS_CELL_ID, "neighbour cellId for A3Report", 0, .i64ptr = NULL, .defint64val = -1, TYPE_INT64, 0}, \ + {MEASUREMENT_EVENTS_PCI_ID, "neighbour PCI for A3Report", 0, .i64ptr = NULL, .defint64val = -1, TYPE_INT64, 0}, \ {MEASUREMENT_EVENTS_TIME_TO_TRIGGER, "a3 time to trigger", 0, .i64ptr = NULL, .defint64val = 1, TYPE_INT64, 0}, \ {MEASUREMENT_EVENTS_OFFSET, "a3 offset", 0, .i64ptr = NULL, .defint64val = 60, TYPE_INT64, 0}, \ {MEASUREMENT_EVENTS_HYSTERESIS, "a3 hysteresis", 0, .i64ptr = NULL, .defint64val = 0, TYPE_INT64, 0}, \ @@ -350,7 +350,7 @@ typedef enum { } // clang-format on -#define MEASUREMENT_EVENTS_CELL_ID_IDX 0 +#define MEASUREMENT_EVENTS_PCI_ID_IDX 0 #define MEASUREMENT_EVENTS_ENABLE_IDX 0 #define MEASUREMENT_EVENTS_TIMETOTRIGGER_IDX 1 #define MEASUREMENT_EVENTS_A2_THRESHOLD_IDX 2 diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index c26e8a5629..c52a67c5a2 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -790,7 +790,7 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB } } - if (is_nr_timer_active(ra->contention_resolution_timer)) { + if (nr_timer_is_active(&ra->contention_resolution_timer)) { nr_ue_contention_resolution(mac, CC_id, frame, nr_slot_tx, prach_resources); } } @@ -851,7 +851,7 @@ void nr_ue_contention_resolution(NR_UE_MAC_INST_t *mac, int cc_id, frame_t frame { RA_config_t *ra = &mac->ra; - if (nr_timer_expired(ra->contention_resolution_timer)) { + if (nr_timer_expired(&ra->contention_resolution_timer)) { ra->t_crnti = 0; nr_timer_stop(&ra->contention_resolution_timer); // Signal PHY to quit RA procedure diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index ac743c0f60..ccfa861587 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2543,7 +2543,7 @@ int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_Schedu sr_id); // todo // TODO check if the PUCCH resource for the SR transmission occasion does not overlap with a UL-SCH resource - if (!sr_info->pending || is_nr_timer_active(sr_info->prohibitTimer)) + if (!sr_info->pending || nr_timer_is_active(&sr_info->prohibitTimer)) return 0; if (sr_info->counter < sr_info->maxTransmissions) { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 557a393ce2..b66ff3203c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1297,7 +1297,7 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac) // if a Regular BSR has been triggered and logicalChannelSR-DelayTimer is not running if (((sched_info->BSR_reporting_active & NR_BSR_TRIGGER_REGULAR) == 0) - || is_nr_timer_active(sched_info->sr_DelayTimer)) + || nr_timer_is_active(&sched_info->sr_DelayTimer)) return; nr_lcordered_info_t *lc_info = get_lc_info_from_lcid(mac, sched_info->regularBSR_trigger_lcid); @@ -1527,7 +1527,7 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid); int32_t bj = sched_info->Bj; if (lc_info->pbr < UINT_MAX) { - uint32_t slots_elapsed = nr_timer_elapsed_time(sched_info->Bj_timer); // slots elapsed since Bj was last incremented + uint32_t slots_elapsed = nr_timer_elapsed_time(&sched_info->Bj_timer); // slots elapsed since Bj was last incremented // it is safe to divide by 1k since pbr in lc_info is computed multiplying by 1000 the RRC value to convert kB/s to B/s uint32_t pbr_ms = lc_info->pbr / 1000; bj += ((pbr_ms * slots_elapsed) >> mac->current_UL_BWP->scs); // each slot length is 1/scs ms diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index d8f6690818..160cde63f5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -560,7 +560,7 @@ static void start_ra_contention_resolution_timer(NR_RA_t *ra, const long ra_Cont // Value sf8 corresponds to 8 subframes, value sf16 corresponds to 16 subframes, and so on. // We add 2 * K2 because the timer runs from Msg2 transmission till Msg4 ACK reception ra->contention_resolution_timer = ((((int)ra_ContentionResolutionTimer + 1) * 8) << scs) + 2 * K2; - LOG_I(NR_MAC, + LOG_D(NR_MAC, "Starting RA Contention Resolution timer with %d ms + 2 * %d K2 (%d slots) duration\n", ((int)ra_ContentionResolutionTimer + 1) * 8, K2, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index d0b36a4603..d091d486ff 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -860,12 +860,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, // re-initialize ta update variables after RA procedure completion UE->UE_sched_ctrl.ta_frame = frameP; - LOG_I(NR_MAC, - "[gNB %d][RAPROC] PUSCH with TC_RNTI 0x%04x received correctly, " - "adding UE MAC Context RNTI 0x%04x\n", - gnb_mod_idP, - current_rnti, - ra->rnti); + LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frameP, slotP, current_rnti); NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl; if (ul_cqi != 0xff) { @@ -884,7 +879,6 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, ra->CellGroup->rlc_BearerToAddModList); nr_clear_ra_proc(ra); } else { - LOG_A(NR_MAC, "[RAPROC] RA-Msg3 received (sdu_lenP %d)\n", sdu_lenP); LOG_D(NR_MAC, "[RAPROC] Received Msg3:\n"); for (uint32_t k = 0; k < sdu_lenP; k++) { LOG_D(NR_MAC, "(%i): 0x%x\n", k, sduP[k]); 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 2435ed629a..bb84a4793c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -233,7 +233,8 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .priority = priority}; nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); - (*resp_srbs)[i] = *srb; + (*resp_srbs)[i].srb_id = srb->srb_id; + (*resp_srbs)[i].lcid = c.lcid; int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig); DevAssert(ret == 0); @@ -669,8 +670,12 @@ void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd) NR_SCHED_LOCK(&mac->sched_lock); NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, cmd->gNB_DU_ue_id); if (UE == NULL) { - LOG_E(MAC, "ERROR: unknown UE with RNTI %04x, ignoring UE Context Release Command\n", cmd->gNB_DU_ue_id); NR_SCHED_UNLOCK(&mac->sched_lock); + f1ap_ue_context_release_complete_t complete = { + .gNB_CU_ue_id = cmd->gNB_CU_ue_id, + .gNB_DU_ue_id = cmd->gNB_DU_ue_id, + }; + mac->mac_rrc.ue_context_release_complete(&complete); return; } @@ -743,7 +748,7 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) * the new UE context (with new C-RNTI), but set up everything to reuse the * old config. */ NR_UE_info_t *oldUE = find_nr_UE(&mac->UE_info, *dl_rrc->old_gNB_DU_ue_id); - DevAssert(oldUE); + AssertFatal(oldUE, "CU claims we should know UE %04x, but we don't\n", *dl_rrc->old_gNB_DU_ue_id); pthread_mutex_lock(&mac->sched_lock); /* 38.331 5.3.7.2 says that the UE releases the spCellConfig, so we drop it * from the current configuration. Also, expect the reconfiguration from diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 3849e157c9..25baed610a 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -1165,10 +1165,9 @@ static NR_ReportConfigToAddMod_t *prepare_a2_event_report(const nr_a2_event_t *a static NR_ReportConfigToAddMod_t *prepare_a3_event_report(const nr_a3_event_t *a3_event) { NR_ReportConfigToAddMod_t *rc_A3 = calloc(1, sizeof(*rc_A3)); - rc_A3->reportConfigId = - a3_event->cell_id == -1 - ? 3 - : a3_event->cell_id + 4; // 3 is default A3 Report Config ID. So cellId(0) specific Report Config ID starts from 4 + // 3 is default A3 Report Config ID. So cellId(0) specific Report Config ID + // starts from 4 + rc_A3->reportConfigId = a3_event->pci == -1 ? 3 : a3_event->pci + 4; rc_A3->reportConfig.present = NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR; NR_EventTriggerConfig_t *etrc_A3 = calloc(1, sizeof(*etrc_A3)); etrc_A3->eventId.present = NR_EventTriggerConfig__eventId_PR_eventA3; @@ -1194,7 +1193,7 @@ static NR_ReportConfigToAddMod_t *prepare_a3_event_report(const nr_a3_event_t *a return rc_A3; } -const nr_a3_event_t *get_a3_configuration(int nr_cellid) +const nr_a3_event_t *get_a3_configuration(int pci) { gNB_RRC_INST *rrc = RC.nrrrc[0]; nr_measurement_configuration_t *measurementConfiguration = &rrc->measurementConfiguration; @@ -1203,7 +1202,7 @@ const nr_a3_event_t *get_a3_configuration(int nr_cellid) for (uint8_t i = 0; i < measurementConfiguration->a3_event_list->size; i++) { nr_a3_event_t *a3_event = (nr_a3_event_t *)seq_arr_at(measurementConfiguration->a3_event_list, i); - if (a3_event->cell_id == nr_cellid) + if (a3_event->pci == pci) return a3_event; } @@ -1262,11 +1261,11 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, if (!neighbourCell->isIntraFrequencyNeighbour) continue; - const nr_a3_event_t *a3Event = get_a3_configuration(neighbourCell->nrcell_id); + const nr_a3_event_t *a3Event = get_a3_configuration(neighbourCell->physicalCellId); if (!a3Event || is_default_a3_added) continue; - if (a3Event->cell_id == -1) + if (a3Event->pci == -1) is_default_a3_added = true; NR_ReportConfigToAddMod_t *rc_A3 = prepare_a3_event_report(a3Event); @@ -1368,7 +1367,7 @@ int do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi) LOG_D(NR_RRC, "[gNB %d] do_Paging paging_record: PagingRecordList.count %d\n", Mod_id, c1->choice.paging->pagingRecordList->list.count); asn_enc_rval_t enc_rval = uper_encode_to_buffer( - &asn_DEF_NR_PCCH_Message, NULL, (void *)&pcch_msg, buffer, RRC_BUF_SIZE); + &asn_DEF_NR_PCCH_Message, NULL, (void *)&pcch_msg, buffer, NR_RRC_BUF_SIZE); if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_PCCH_Message, (void *)&pcch_msg); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 0d8b4c547f..623573d24f 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -143,7 +143,7 @@ int do_RRCReestablishment(rrc_gNB_ue_context_t *const ue_context_pP, int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier); -const nr_a3_event_t *get_a3_configuration(int nr_cellid); +const nr_a3_event_t *get_a3_configuration(int pci); NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, int band, int scs, diff --git a/openair2/RRC/NR/nr_rrc_common.h b/openair2/RRC/NR/nr_rrc_common.h index e1ff2e703e..305013ecf4 100644 --- a/openair2/RRC/NR/nr_rrc_common.h +++ b/openair2/RRC/NR/nr_rrc_common.h @@ -26,17 +26,9 @@ #include #include -#define NR_RRC_HEADER_SIZE_MAX 64 -#define NR_RRC_BUFFER_SIZE_MAX 1024 #define NR_NUM_SRB 4 /* Number of Signalling Radio Bearers according to clause 4.2.2 of 3GPP TS 38.331 */ #define NR_K_KEY_SIZE 16 /* K keys have 128 bits length */ -typedef struct { - char Payload[NR_RRC_BUFFER_SIZE_MAX]; - char Header[NR_RRC_HEADER_SIZE_MAX]; - uint16_t payload_size; -} NR_RRC_BUFFER; - typedef enum UE_STATE_NR_e { NR_RRC_INACTIVE=0, NR_RRC_IDLE, diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index e5f0c295b5..5631da4c0e 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -2805,6 +2805,8 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, && servingcellconfigdedicated->downlinkBWP_ToAddModList->list.count > 0) { n_dl_bwp = servingcellconfigdedicated->downlinkBWP_ToAddModList->list.count; } + int default_dl_bwp = 0; + int first_active_dl_bwp = 0; if (n_dl_bwp > 0) { SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList)); @@ -2813,15 +2815,13 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, config_downlinkBWP(bwp, scc, servingcellconfigdedicated, NULL, 0, false, bwp_loop, true); asn1cSeqAdd(&SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list, bwp); } - SpCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id = - calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id)); - *SpCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id = - servingcellconfigdedicated->firstActiveDownlinkBWP_Id ? *servingcellconfigdedicated->firstActiveDownlinkBWP_Id : 1; - SpCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = - calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id)); - *SpCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = - servingcellconfigdedicated->defaultDownlinkBWP_Id ? *servingcellconfigdedicated->defaultDownlinkBWP_Id : 1; + const NR_BWP_Id_t *firstActiveDownlinkBWP_Id = servingcellconfigdedicated->firstActiveDownlinkBWP_Id; + first_active_dl_bwp = firstActiveDownlinkBWP_Id ? *firstActiveDownlinkBWP_Id : 1; + const NR_BWP_Id_t *defaultDownlinkBWP_Id = servingcellconfigdedicated->defaultDownlinkBWP_Id; + default_dl_bwp = defaultDownlinkBWP_Id ? *defaultDownlinkBWP_Id : 1; } + asn1cCallocOne(SpCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id, first_active_dl_bwp); + asn1cCallocOne(SpCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id, default_dl_bwp); // Uplink BWPs int n_ul_bwp = 0; @@ -2830,6 +2830,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, && servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count > 0) { n_ul_bwp = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; } + int first_active_ul_bwp = 0; if (n_ul_bwp > 0) { uplinkConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList)); for (int bwp_loop = 0; bwp_loop < n_ul_bwp; bwp_loop++) { @@ -2837,11 +2838,10 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, config_uplinkBWP(ubwp, bwp_loop, true, uid, configuration, servingcellconfigdedicated, scc, NULL); asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ubwp); } - uplinkConfig->firstActiveUplinkBWP_Id = calloc(1, sizeof(*uplinkConfig->firstActiveUplinkBWP_Id)); - *uplinkConfig->firstActiveUplinkBWP_Id = servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id - ? *servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id - : 1; + const NR_BWP_Id_t *firstActiveUplinkBWP_Id = servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id; + first_active_ul_bwp = firstActiveUplinkBWP_Id ? *firstActiveUplinkBWP_Id : 1; } + asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_ul_bwp); SpCellConfig->spCellConfigDedicated->csi_MeasConfig = calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->csi_MeasConfig)); SpCellConfig->spCellConfigDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup; diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index a9234ed5bd..b5b27a6f4d 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -88,15 +88,6 @@ #define NR_RRC_RECONFIGURATION_DELAY_MS 10 #define NR_RRC_BWP_SWITCHING_DELAY_MS 6 -// 3GPP TS 38.133 - Section 8 - Table 8.2.1.2.7-2: Parameters which cause interruption other than SCS -// This table was recently added to 3GPP. It shows that changing the parameters locationAndBandwidth, nrofSRS-Ports or -// maxMIMO-Layers-r16 causes an interruption. This parameter is not yet being used in code, but has been placed here -// for future reference. -#define NR_OF_SRS_PORTS_SWITCHING_DELAY_MS 30 - -#define NR_UE_MODULE_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!! -#define NR_UE_INDEX_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!! used to be -1 - typedef enum { NR_RRC_OK=0, NR_RRC_ConnSetup_failed, @@ -105,17 +96,11 @@ typedef enum { NR_RRC_HO_STARTED } NR_RRC_status_t; -#define RRM_FREE(p) if ( (p) != NULL) { free(p) ; p=NULL ; } -#define RRM_MALLOC(t,n) (t *) malloc16( sizeof(t) * n ) -#define RRM_CALLOC(t,n) (t *) malloc16( sizeof(t) * n) -#define RRM_CALLOC2(t,s) (t *) malloc16( s ) - #define MAX_MEAS_OBJ 7 #define MAX_MEAS_CONFIG 7 #define MAX_MEAS_ID 7 -#define PAYLOAD_SIZE_MAX 1024 -#define RRC_BUF_SIZE 1024 +#define NR_RRC_BUF_SIZE 4096 #define UNDEF_SECURITY_MODE 0xff #define NO_SECURITY_MODE 0x20 @@ -129,14 +114,6 @@ typedef struct UE_S_TMSI_NR_s { uint32_t fiveg_tmsi; } __attribute__ ((__packed__)) NR_UE_S_TMSI; - -typedef enum nr_e_rab_satus_e { - NR_E_RAB_STATUS_NEW, - NR_E_RAB_STATUS_DONE, // from the gNB perspective - NR_E_RAB_STATUS_ESTABLISHED, // get the reconfigurationcomplete form UE - NR_E_RAB_STATUS_FAILED, -} nr_e_rab_status_t; - typedef struct nr_e_rab_param_s { e_rab_t param; uint8_t status; @@ -156,12 +133,10 @@ typedef struct HANDOVER_INFO_NR_s { //AS_Config_t as_config; /* these two parameters are taken from 36.331 section 10.2.2: HandoverPreparationInformation-r8-IEs */ //AS_Context_t as_context; /* They are mandatory for HO */ - uint8_t buf[RRC_BUF_SIZE]; /* ASN.1 encoded handoverCommandMessage */ + uint8_t buf[NR_RRC_BUF_SIZE]; /* ASN.1 encoded handoverCommandMessage */ int size; /* size of above message in bytes */ } NR_HANDOVER_INFO; -#define NR_RRC_BUFFER_SIZE sizeof(RRC_BUFFER_NR) - typedef struct nr_rrc_guami_s { uint16_t mcc; uint16_t mnc; @@ -194,19 +169,15 @@ typedef struct pdu_session_param_s { * @brief F1-U tunnel configuration */ typedef struct f1u_tunnel_s { - /* Downlink F1-U Tunnel Endpoint Identifier (CU-UP/DU) */ - uint32_t cuup_teid_f1u; - /* DL F1-U Transport Layer */ - transport_layer_addr_t cuup_addr_f1u; + /* F1-U Tunnel Endpoint Identifier (on DU side) */ + uint32_t teid; + /* Downlink F1-U Transport Layer (on DU side) */ + transport_layer_addr_t addr; } f1u_tunnel_t; typedef struct drb_s { int status; - int defaultDRBid; int drb_id; - int reestablishPDCP; - int recoverPDCP; - int daps_Config_r16; struct cnAssociation_s { int present; int eps_BearerIdentity; @@ -232,8 +203,10 @@ typedef struct drb_s { int cipheringDisabled; } ext1; } pdcp_config; - // F1-U - f1u_tunnel_t f1u_tunnel_config; + // F1-U Downlink Tunnel Config (on DU side) + f1u_tunnel_t du_tunnel_config; + // F1-U Uplink Tunnel Config (on CU-UP side) + f1u_tunnel_t cuup_tunnel_config; } drb_t; typedef enum { @@ -284,7 +257,6 @@ typedef struct gNB_RRC_UE_s { NR_CipheringAlgorithm_t ciphering_algorithm; e_NR_IntegrityProtAlgorithm integrity_algorithm; - NR_UE_STATE_t StatusRrc; rnti_t rnti; uint64_t random_ue_identity; @@ -317,6 +289,8 @@ typedef struct gNB_RRC_UE_s { uint32_t ue_reestablishment_counter; uint32_t ue_reconfiguration_counter; + bool an_release; // flag if core requested UE release + /* NGUEContextSetup might come with PDU sessions, but setup needs to be * delayed after security (and capability); PDU sessions are stored here */ int n_initial_pdu; @@ -368,7 +342,7 @@ typedef struct { } nr_a2_event_t; typedef struct { - int cell_id; + int pci; long a3_offset; long hysteresis; long timeToTrigger; @@ -393,7 +367,7 @@ typedef struct { } nr_neighbour_gnb_configuration_t; typedef struct neighbour_cell_configuration_s { - int nr_cell_id; + uint64_t nr_cell_id; seq_arr_t *neighbour_cells; } neighbour_cell_configuration_t; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index f9646468e0..f7992d9757 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -113,9 +113,9 @@ mui_t rrc_gNB_mui = 0; // the assoc_id might be 0 (if the DU goes offline). Below helper macro to // print an error and return from the function in that case -#define RETURN_IF_INVALID_ASSOC_ID(ue_data) \ +#define RETURN_IF_INVALID_ASSOC_ID(assoc_id) \ { \ - if (ue_data.du_assoc_id == 0) { \ + if (assoc_id == 0) { \ LOG_E(NR_RRC, "cannot send data: invalid assoc_id 0, DU offline\n"); \ return; \ } \ @@ -197,7 +197,7 @@ void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, { DevAssert(size > 0); f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); - RETURN_IF_INVALID_ASSOC_ID(ue_data); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); f1ap_dl_rrc_message_t dl_rrc = {.gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .srb_id = srb_id}; deliver_dl_rrc_message_data_t data = {.rrc = rrc, .dl_rrc = &dl_rrc, .assoc_id = ue_data.du_assoc_id}; nr_pdcp_data_req_srb(ue_p->rrc_ue_id, @@ -345,7 +345,6 @@ static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) if (ue->established_drbs[i].status != DRB_INACTIVE) { DRB_config = generateDRB_ASN1(&ue->established_drbs[i]); if (reestablish) { - ue->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); } asn1cSeqAdd(&DRB_configList->list, DRB_config); @@ -424,7 +423,7 @@ static void rrc_gNB_generate_RRCSetup(instance_t instance, LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buf, size, "[MSG] RRC Setup\n"); freeSRBlist(SRBs); f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); - RETURN_IF_INVALID_ASSOC_ID(ue_data); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); f1ap_dl_rrc_message_t dl_rrc = { .gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, @@ -454,7 +453,7 @@ static void rrc_gNB_generate_RRCReject(module_id_t module_id, rrc_gNB_ue_context LOG_I(NR_RRC, " [RAPROC] ue %04x Logical Channel DL-CCCH, Generating NR_RRCReject (bytes %d)\n", ue_p->rnti, size); f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); - RETURN_IF_INVALID_ASSOC_ID(ue_data); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); f1ap_dl_rrc_message_t dl_rrc = { .gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, @@ -477,7 +476,6 @@ static void rrc_gNB_process_RRCSetupComplete(const protocol_ctxt_t *const ctxt_p LOG_A(NR_RRC, "UE %d Processing NR_RRCSetupComplete from UE\n", ue_context_pP->ue_context.rrc_ue_id); ue_context_pP->ue_context.Srb[1].Active = 1; ue_context_pP->ue_context.Srb[2].Active = 0; - ue_context_pP->ue_context.StatusRrc = NR_RRC_CONNECTED; AssertFatal(ctxt_pP->rntiMaybeUEid == ue_context_pP->ue_context.rrc_ue_id, "logic bug: inconsistent IDs, must use CU UE ID!\n"); rrc_gNB_send_NGAP_NAS_FIRST_REQ(ctxt_pP, ue_context_pP, rrcSetupComplete); @@ -549,13 +547,13 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c ue_p->measConfig = measconfig; - uint8_t buffer[RRC_BUF_SIZE] = {0}; + uint8_t buffer[NR_RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); int size = do_RRCReconfiguration(ue_p, buffer, - RRC_BUF_SIZE, + NR_RRC_BUF_SIZE, xid, SRBs, DRBs, @@ -676,10 +674,10 @@ rrc_gNB_modify_dedicatedRRCReconfiguration( } NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); - uint8_t buffer[RRC_BUF_SIZE]; + uint8_t buffer[NR_RRC_BUF_SIZE]; int size = do_RRCReconfiguration(ue_p, buffer, - RRC_BUF_SIZE, + NR_RRC_BUF_SIZE, xid, NULL, DRBs, @@ -742,10 +740,10 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release( LOG_W(NR_RRC,"dedlicated NAS list is empty\n"); } - uint8_t buffer[RRC_BUF_SIZE] = {0}; + uint8_t buffer[NR_RRC_BUF_SIZE] = {0}; int size = do_RRCReconfiguration(ue_p, buffer, - RRC_BUF_SIZE, + NR_RRC_BUF_SIZE, xid, NULL, NULL, @@ -808,7 +806,8 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) return; /* loop through active DRBs */ for (int drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) { - if (ue_p->established_drbs[drb_id - 1].status == DRB_INACTIVE) + drb_t *drb = get_drb(ue_p, drb_id); + if (drb->status == DRB_INACTIVE) continue; /* fetch an existing PDU session for this DRB */ rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue_p, drb_id); @@ -829,13 +828,11 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) DRB_nGRAN_to_mod_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify]; drb_e1->id = drb_id; drb_e1->numDlUpParam = 1; - drb_t *drbs = &ue_p->established_drbs[drb_id]; - memcpy(&drb_e1->DlUpParamList[0].tlAddress, &drbs->f1u_tunnel_config.cuup_addr_f1u.buffer, sizeof(uint8_t) * 4); - drb_e1->DlUpParamList[0].teId = drbs->f1u_tunnel_config.cuup_teid_f1u; + memcpy(&drb_e1->DlUpParamList[0].tlAddress, &drb->du_tunnel_config.addr.buffer, sizeof(uint8_t) * 4); + drb_e1->DlUpParamList[0].teId = drb->du_tunnel_config.teid; /* PDCP configuration */ bearer_context_pdcp_config_t *pdcp_config = &drb_e1->pdcp_config; - drb_t *rrc_drb = get_drb(ue_p, drb_id); - set_bearer_context_pdcp_config(pdcp_config, rrc_drb, rrc->configuration.um_on_default_drb); + set_bearer_context_pdcp_config(pdcp_config, drb, rrc->configuration.um_on_default_drb); pdcp_config->pDCP_Reestablishment = true; /* increase DRB to modify counter */ pdu_e1->numDRB2Modify += 1; @@ -863,12 +860,12 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context module_id_t module_id = 0; gNB_RRC_INST *rrc = RC.nrrrc[module_id]; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - uint8_t buffer[RRC_BUF_SIZE] = {0}; + uint8_t buffer[NR_RRC_BUF_SIZE] = {0}; uint8_t xid = rrc_gNB_get_next_transaction_identifier(module_id); ue_p->xids[xid] = RRC_REESTABLISH; const f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; uint32_t ssb_arfcn = get_ssb_arfcn(du); - int size = do_RRCReestablishment(ue_context_pP, buffer, RRC_BUF_SIZE, xid, cell_info->nr_pci, ssb_arfcn); + int size = do_RRCReestablishment(ue_context_pP, buffer, NR_RRC_BUF_SIZE, xid, cell_info->nr_pci, ssb_arfcn); LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel DL-DCCH, Generating NR_RRCReestablishment (bytes %d)\n", ue_p->rnti, size); @@ -902,7 +899,7 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context &security_parameters); /* F1AP DL RRC Message Transfer */ f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); - RETURN_IF_INVALID_ASSOC_ID(ue_data); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); uint32_t old_gNB_DU_ue_id = old_rnti; f1ap_dl_rrc_message_t dl_rrc = {.gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, @@ -935,7 +932,6 @@ static void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *co int i = 0; ue_p->xids[xid] = RRC_ACTION_NONE; - ue_p->StatusRrc = NR_RRC_CONNECTED; ue_p->Srb[1].Active = 1; @@ -987,10 +983,10 @@ static void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *co uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); ue_p->xids[new_xid] = RRC_REESTABLISH_COMPLETE; - uint8_t buffer[RRC_BUF_SIZE] = {0}; + uint8_t buffer[NR_RRC_BUF_SIZE] = {0}; int size = do_RRCReconfiguration(ue_p, buffer, - RRC_BUF_SIZE, + NR_RRC_BUF_SIZE, new_xid, SRBs, DRBs, @@ -1031,8 +1027,8 @@ int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP, *masterCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = ul_bwp_id; } - uint8_t buffer[RRC_BUF_SIZE]; - int size = do_RRCReconfiguration(ue_p, buffer, RRC_BUF_SIZE, xid, NULL, NULL, NULL, NULL, NULL, NULL, masterCellGroup); + uint8_t buffer[NR_RRC_BUF_SIZE]; + int size = do_RRCReconfiguration(ue_p, buffer, NR_RRC_BUF_SIZE, xid, NULL, NULL, NULL, NULL, NULL, NULL, masterCellGroup); gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DCCH, buffer, size); @@ -1120,7 +1116,9 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, uint64_t random_value = 0; const char *scause = get_reestab_cause(req->reestablishmentCause); const long physCellId = req->ue_Identity.physCellId; - LOG_D(NR_RRC, "UE %04x physCellId %ld NR_RRCReestablishmentRequest cause %s\n", msg->crnti, physCellId, scause); + long ngap_cause = NGAP_CAUSE_RADIO_NETWORK_UNSPECIFIED; /* cause in case of NGAP release req */ + rrc_gNB_ue_context_t *ue_context_p = NULL; + LOG_I(NR_RRC, "UE %04x physCellId %ld NR_RRCReestablishmentRequest cause %s\n", msg->crnti, physCellId, scause); const nr_rrc_du_container_t *du = get_du_by_assoc_id(rrc, assoc_id); if (du == NULL) { @@ -1128,6 +1126,13 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, return; } + // 3GPP TS 38.321 version 15.13.0 Section 7.1 Table 7.1-1: RNTI values + if (req->ue_Identity.c_RNTI < 0x1 || req->ue_Identity.c_RNTI > 0xffef) { + /* c_RNTI range error should not happen */ + LOG_E(NR_RRC, "NR_RRCReestablishmentRequest c_RNTI %04lx range error, fallback to RRC setup\n", req->ue_Identity.c_RNTI); + goto fallback_rrc_setup; + } + if (du->mib == NULL || du->sib1 == NULL) { /* we don't have MIB/SIB1 of the DU, and therefore cannot generate the * Reestablishment (as we would need the SSB's ARFCN, which we cannot @@ -1136,12 +1141,22 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, goto fallback_rrc_setup; } + if (du->mtc == NULL) { + // some UEs don't send MeasurementTimingConfiguration, so we don't know the + // SSB ARFCN and can't do reestablishment. handle it gracefully by doing + // RRC setup procedure instead + LOG_E(NR_RRC, "no MeasurementTimingConfiguration for this cell, cannot perform reestablishment\n"); + ngap_cause = NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_NGRAN_GENERATED_REASON; + goto fallback_rrc_setup; + } + rnti_t old_rnti = req->ue_Identity.c_RNTI; - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, assoc_id, old_rnti); + ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, assoc_id, old_rnti); if (ue_context_p == NULL) { LOG_E(NR_RRC, "NR_RRCReestablishmentRequest without UE context, fallback to RRC setup\n"); goto fallback_rrc_setup; } + gNB_RRC_UE_t *UE = &ue_context_p->ue_context; const f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; if (physCellId != cell_info->nr_pci) { @@ -1150,6 +1165,7 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, "RRC Reestablishment Request from different physCellId (%ld) than current physCellId (%d), fallback to RRC setup\n", physCellId, cell_info->nr_pci); + ngap_cause = NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_NGRAN_GENERATED_REASON; /* 38.401 8.7: "If the UE accessed from a gNB-DU other than the original * one, the gNB-CU should trigger the UE Context Setup procedure". Let's * assume that the old DU will trigger a release request, also freeing the @@ -1157,25 +1173,10 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, goto fallback_rrc_setup; } - gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - // 3GPP TS 38.321 version 15.13.0 Section 7.1 Table 7.1-1: RNTI values - if (req->ue_Identity.c_RNTI < 0x1 || req->ue_Identity.c_RNTI > 0xffef) { - /* c_RNTI range error should not happen */ - LOG_E(NR_RRC, "NR_RRCReestablishmentRequest c_RNTI %04lx range error, fallback to RRC setup\n", req->ue_Identity.c_RNTI); - goto fallback_rrc_setup; - } - if (!UE->as_security_active) { /* no active security context, need to restart entire connection */ LOG_E(NR_RRC, "UE requested Reestablishment without activated AS security\n"); - goto fallback_rrc_setup; - } - - if (du->mtc == NULL) { - // some UEs don't send MeasurementTimingConfiguration, so we don't know the - // SSB ARFCN and can't do reestablishment. handle it gracefully by doing - // RRC setup procedure instead - LOG_E(NR_RRC, "no MeasurementTimingConfiguration for this cell, cannot perform reestablishment\n"); + ngap_cause = NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_NGRAN_GENERATED_REASON; goto fallback_rrc_setup; } @@ -1188,8 +1189,6 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, cu_remove_f1_ue_data(UE->rrc_ue_id); cu_add_f1_ue_data(UE->rrc_ue_id, &ue_data); - LOG_I(NR_RRC, "Accept Reestablishment Request UE physCellId %ld cause %s\n", physCellId, scause); - rrc_gNB_generate_RRCReestablishment(ue_context_p, msg->du2cu_rrc_container, old_rnti, du); return; @@ -1197,6 +1196,10 @@ fallback_rrc_setup: fill_random(&random_value, sizeof(random_value)); random_value = random_value & 0x7fffffffff; /* random value is 39 bits */ + /* request release of the "old" UE in case it exists */ + if (ue_context_p != NULL) + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(0, ue_context_p, NGAP_CAUSE_RADIO_NETWORK, ngap_cause); + rrc_gNB_ue_context_t *new = rrc_gNB_create_ue_context(assoc_id, msg->crnti, rrc, random_value, msg->gNB_DU_ue_id); activate_srb(&new->ue_context, 1); rrc_gNB_generate_RRCSetup(0, msg->crnti, new, msg->du2cu_rrc_container, msg->du2cu_rrc_container_length); @@ -1228,11 +1231,11 @@ static void process_Event_Based_Measurement_Report(NR_ReportConfigNR_t *report, switch (event_triggered->eventId.present) { case NR_EventTriggerConfig__eventId_PR_eventA2: - LOG_I(NR_RRC, "\nHO LOG: Event A2 (Serving becomes worse than threshold)\n"); + LOG_I(NR_RRC, "HO LOG: Event A2 (Serving becomes worse than threshold)\n"); break; case NR_EventTriggerConfig__eventId_PR_eventA3: { - LOG_I(NR_RRC, "\nHO LOG: Event A3 Report - Neighbour Becomes Better than Serving!\n"); + LOG_I(NR_RRC, "HO LOG: Event A3 Report - Neighbour Becomes Better than Serving!\n"); const NR_MeasResults_t *measResults = &measurementReport->criticalExtensions.choice.measurementReport->measResults; for (int serving_cell_idx = 0; serving_cell_idx < measResults->measResultServingMOList.list.count; serving_cell_idx++) { @@ -1267,7 +1270,7 @@ static void process_Event_Based_Measurement_Report(NR_ReportConfigNR_t *report, } LOG_I(NR_RRC, - "HO LOG: Measurement Report has came for the neighbour: %d with RSRP: %d\n", + "HO LOG: Measurement Report for the neighbour %d with RSRP: %d\n", neighbourCellId, neighbourCellRSRP); @@ -1279,7 +1282,7 @@ static void process_Event_Based_Measurement_Report(NR_ReportConfigNR_t *report, // neighbour. if (!neighbour_cell_du_context && neighbour) { // No F1 connection but static neighbour configuration is available - const nr_a3_event_t *a3_event_configuration = get_a3_configuration(neighbour->nrcell_id); + const nr_a3_event_t *a3_event_configuration = get_a3_configuration(neighbour->physicalCellId); // Additional check - This part can be modified according to additional cell specific Handover Margin if (a3_event_configuration && ((a3_event_configuration->a3_offset + a3_event_configuration->hysteresis) @@ -1864,15 +1867,39 @@ static void fill_e1_bearer_modif(DRB_nGRAN_to_setup_t *drb_e1, const f1ap_drb_to /** * @brief Store F1-U DL TL and TEID in RRC */ -static void f1u_gtp_update(f1u_tunnel_t *f1u, const f1ap_drb_to_be_setup_t *drb_f1) +static void f1u_dl_gtp_update(f1u_tunnel_t *f1u, const f1ap_up_tnl_t *p) { - f1u->cuup_teid_f1u = drb_f1->up_dl_tnl[0].teid; - memcpy(&f1u->cuup_addr_f1u.buffer, &drb_f1->up_dl_tnl[0].tl_address, sizeof(uint8_t) * 4); - f1u->cuup_addr_f1u.length = sizeof(in_addr_t); + f1u->teid = p->teid; + memcpy(&f1u->addr.buffer, &p->tl_address, sizeof(uint8_t) * 4); + f1u->addr.length = sizeof(in_addr_t); +} + +/** + * @brief Update DRB TEID information in RRC storage from received DRB list + */ +static void store_du_f1u_tunnel(const f1ap_drb_to_be_setup_t *drbs, int n, gNB_RRC_UE_t *ue) +{ + for (int i = 0; i < n; i++) { + const f1ap_drb_to_be_setup_t *drb_f1 = &drbs[i]; + AssertFatal(drb_f1->up_dl_tnl_length == 1, "can handle only one UP param\n"); + AssertFatal(drb_f1->drb_id < MAX_DRBS_PER_UE, "illegal DRB ID %ld\n", drb_f1->drb_id); + drb_t *drb = get_drb(ue, drb_f1->drb_id); + f1u_dl_gtp_update(&drb->du_tunnel_config, &drb_f1->up_dl_tnl[0]); + } +} + +/* + * @brief Store F1-U UL TEID and address in RRC + */ +static void f1u_ul_gtp_update(f1u_tunnel_t *f1u, const up_params_t *p) +{ + f1u->teid = p->teId; + memcpy(&f1u->addr.buffer, &p->tlAddress, sizeof(uint8_t) * 4); + f1u->addr.length = sizeof(in_addr_t); } /* \brief use list of DRBs and send the corresponding bearer update message via - * E1 to the CU of this UE */ + * E1 to the CU of this UE. Also updates TEID info internally */ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_to_be_setup_t *drbs) { // we assume the same UE ID in CU-UP and CU-CP @@ -1892,7 +1919,6 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f DevAssert(pdu_e1 != NULL); pdu_e1->sessionId = pdu_ue->param.pdusession_id; DRB_nGRAN_to_setup_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify]; - f1u_gtp_update(&UE->established_drbs[drb_f1->drb_id].f1u_tunnel_config, drb_f1); /* Fill E1 bearer context modification */ fill_e1_bearer_modif(drb_e1, drb_f1); pdu_e1->numDRB2Modify += 1; @@ -1942,6 +1968,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance /* Note: we would ideally check that SRB2 is acked, but at least LiteOn DU * seems buggy and does not ack, so simply check that locally we activated */ AssertFatal(UE->Srb[1].Active && UE->Srb[2].Active, "SRBs 1 and 2 must be active during DRB Establishment"); + store_du_f1u_tunnel(resp->drbs_to_be_setup, resp->drbs_to_be_setup_length, UE); e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup); } @@ -2003,7 +2030,13 @@ static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p) return; } - rrc_remove_ue(RC.nrrrc[0], ue_context_p); + gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + if (UE->an_release) { + /* only trigger release if it has been requested by core + * otherwise, it might be CU that requested release on a DU during normal + * operation (i.e, handover) */ + rrc_remove_ue(RC.nrrrc[0], ue_context_p); + } } static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, instance_t instance) @@ -2019,6 +2052,7 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i gNB_RRC_UE_t *UE = &ue_context_p->ue_context; if (resp->drbs_to_be_setup_length > 0) { + store_du_f1u_tunnel(resp->drbs_to_be_setup, resp->drbs_to_be_setup_length, UE); e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup); } @@ -2118,6 +2152,67 @@ static pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, return NULL; } +/* \bref return F1AP QoS characteristics based on Qos flow parameters */ +static f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param) +{ + f1ap_qos_characteristics_t qos_char = {0}; + if (qos_param->fiveQI_type == dynamic) { + qos_char.qos_type = dynamic; + qos_char.dynamic.fiveqi = qos_param->fiveQI; + qos_char.dynamic.qos_priority_level = qos_param->qos_priority; + } else { + qos_char.qos_type = non_dynamic; + qos_char.non_dynamic.fiveqi = qos_param->fiveQI; + qos_char.non_dynamic.qos_priority_level = qos_param->qos_priority; + } + return qos_char; +} + +/* \brief fills a list of DRBs to be setup from a number of PDU sessions in E1 + * bearer setup response */ +static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, + gNB_RRC_UE_t *UE, + const pdu_session_setup_t *pduSession, + int numPduSession, + f1ap_drb_to_be_setup_t drbs[32]) +{ + int nb_drb = 0; + for (int p = 0; p < numPduSession; ++p) { + rrc_pdu_session_param_t *RRC_pduSession = find_pduSession(UE, pduSession[p].id, false); + DevAssert(RRC_pduSession); + for (int i = 0; i < pduSession[p].numDRBSetup; i++) { + const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i]; + f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb]; + drb->drb_id = pduSession[p].DRBnGRanList[i].id; + drb->rlc_mode = rrc->configuration.um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM; + drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tlAddress; + drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd; + drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].teId; + drb->up_ul_tnl_length = 1; + + /* pass QoS info to MAC */ + int nb_qos_flows = drb_config->numQosFlowSetup; + AssertFatal(nb_qos_flows > 0, "must map at least one flow to a DRB\n"); + drb->drb_info.flows_to_be_setup_length = nb_qos_flows; + drb->drb_info.flows_mapped_to_drb = calloc(nb_qos_flows, sizeof(f1ap_flows_mapped_to_drb_t)); + AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n"); + for (int j = 0; j < nb_qos_flows; j++) { + drb->drb_info.flows_mapped_to_drb[j].qfi = drb_config->qosFlows[j].qfi; + pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(drb_config->qosFlows[j].qfi, RRC_pduSession); + drb->drb_info.flows_mapped_to_drb[j].qos_params.qos_characteristics = get_qos_char_from_qos_flow_param(in_qos_char); + } + /* the DRB QoS parameters: we just reuse the ones from the first flow */ + drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params; + + /* pass NSSAI info to MAC */ + drb->nssai = RRC_pduSession->param.nssai; + + nb_drb++; + } + } + return nb_drb; +} + /** * @brief E1AP Bearer Context Setup Response processing on CU-CP */ @@ -2146,56 +2241,20 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp rrc_pdu->param.gNB_teid_N3 = e1_pdu->teId; memcpy(&rrc_pdu->param.gNB_addr_N3.buffer, &e1_pdu->tlAddress, sizeof(uint8_t) * 4); rrc_pdu->param.gNB_addr_N3.length = sizeof(in_addr_t); + + // save the tunnel address for the DRBs + for (int i = 0; i < e1_pdu->numDRBSetup; i++) { + DRB_nGRAN_setup_t *drb_config = &e1_pdu->DRBnGRanList[i]; + // numUpParam only relevant in F1, but not monolithic + AssertFatal(drb_config->numUpParam <= 1, "can only up to one UP param\n"); + drb_t *drb = get_drb(UE, drb_config->id); + f1u_ul_gtp_update(&drb->cuup_tunnel_config, &drb_config->UpParamList[0]); + } } /* Instruction towards the DU for DRB configuration and tunnel creation */ f1ap_drb_to_be_setup_t drbs[32]; // maximum DRB can be 32 - int nb_drb = 0; - for (int p = 0; p < resp->numPDUSessions; ++p) { - rrc_pdu_session_param_t *RRC_pduSession = find_pduSession(UE, resp->pduSession[p].id, false); - DevAssert(RRC_pduSession); - for (int i = 0; i < resp->pduSession[p].numDRBSetup; i++) { - DRB_nGRAN_setup_t *drb_config = &resp->pduSession[p].DRBnGRanList[i]; - f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb]; - drb->drb_id = resp->pduSession[p].DRBnGRanList[i].id; - drb->rlc_mode = rrc->configuration.um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM; - drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tlAddress; - drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].teId; - drb->up_ul_tnl_length = 1; - - drb->nssai = RRC_pduSession->param.nssai; - - /* pass QoS info to MAC */ - int nb_qos_flows = drb_config->numQosFlowSetup; - AssertFatal(nb_qos_flows > 0, "must map at least one flow to a DRB\n"); - drb->drb_info.flows_to_be_setup_length = nb_qos_flows; - drb->drb_info.flows_mapped_to_drb = calloc(nb_qos_flows, sizeof(f1ap_flows_mapped_to_drb_t)); - AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n"); - for (int j = 0; j < nb_qos_flows; j++) { - drb->drb_info.flows_mapped_to_drb[j].qfi = drb_config->qosFlows[j].qfi; - - pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(drb_config->qosFlows[j].qfi, RRC_pduSession); - f1ap_qos_characteristics_t *qos_char = &drb->drb_info.flows_mapped_to_drb[j].qos_params.qos_characteristics; - if (in_qos_char->fiveQI_type == dynamic) { - qos_char->qos_type = dynamic; - qos_char->dynamic.fiveqi = in_qos_char->fiveQI; - qos_char->dynamic.qos_priority_level = in_qos_char->qos_priority; - } else { - qos_char->qos_type = non_dynamic; - qos_char->non_dynamic.fiveqi = in_qos_char->fiveQI; - qos_char->non_dynamic.qos_priority_level = in_qos_char->qos_priority; - } - } - /* the DRB QoS parameters: we just reuse the ones from the first flow */ - drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params; - - /* pass NSSAI info to MAC */ - drb->nssai = RRC_pduSession->param.nssai; - - nb_drb++; - } - } + int nb_drb = fill_drb_to_be_setup_from_e1_resp(rrc, UE, resp->pduSession, resp->numPDUSessions, drbs); if (!UE->f1_ue_context_active) rrc_gNB_generate_UeContextSetupRequest(rrc, ue_context_p, nb_drb, drbs); @@ -2255,20 +2314,6 @@ static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults) } } -static const char *get_rrc_connection_status_text(NR_UE_STATE_t state) -{ - switch (state) { - case NR_RRC_INACTIVE: return "inactive"; - case NR_RRC_IDLE: return "idle"; - case NR_RRC_SI_RECEIVED: return "SI-received"; - case NR_RRC_CONNECTED: return "connected"; - case NR_RRC_RECONFIGURED: return "reconfigured"; - case NR_RRC_HO_EXECUTION: return "HO-execution"; - default: AssertFatal(false, "illegal RRC state %d\n", state); return "illegal"; - } - return "illegal"; -} - static const char *get_pdusession_status_text(pdu_session_status_t status) { switch (status) { @@ -2316,7 +2361,6 @@ static void write_rrc_stats(const gNB_RRC_INST *rrc) time_t last_seen = now - ue_ctxt->last_seen; fprintf(f, " last RRC activity: %ld seconds ago\n", last_seen); - fprintf(f, " RRC status %s\n", get_rrc_connection_status_text(ue_ctxt->StatusRrc)); if (ue_ctxt->nb_of_pdusessions == 0) fprintf(f, " (no PDU sessions)\n"); @@ -2606,8 +2650,8 @@ rrc_gNB_generate_RRCRelease( ) //----------------------------------------------------------------------------- { - uint8_t buffer[RRC_BUF_SIZE] = {0}; - int size = do_NR_RRCRelease(buffer, RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id)); + uint8_t buffer[NR_RRC_BUF_SIZE] = {0}; + int size = do_NR_RRCRelease(buffer, NR_RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id)); LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate RRCRelease (bytes %d)\n", @@ -2617,7 +2661,7 @@ rrc_gNB_generate_RRCRelease( gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; const gNB_RRC_UE_t *UE = &ue_context_pP->ue_context; f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); - RETURN_IF_INVALID_ASSOC_ID(ue_data); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); f1ap_ue_context_release_cmd_t ue_context_release_cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, @@ -2639,7 +2683,7 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint uint32_t N; /* N: min(T,nB). total count of PF in one DRX cycle */ uint32_t Ns = 0; /* Ns: max(1,nB/T) */ uint32_t T; /* DRX cycle */ - uint8_t buffer[RRC_BUF_SIZE]; + uint8_t buffer[NR_RRC_BUF_SIZE]; /* get default DRX cycle from configuration */ Tc = sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.defaultPagingCycle; @@ -2743,7 +2787,7 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, /* the callback will fill the UE context setup request and forward it */ f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); - RETURN_IF_INVALID_ASSOC_ID(ue_data); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); f1ap_ue_context_setup_t ue_context_setup_req = { .gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, @@ -2787,7 +2831,7 @@ void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, } f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); - RETURN_IF_INVALID_ASSOC_ID(ue_data); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); f1ap_ue_context_modif_req_t ue_context_modif_req = { .gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index a98853af28..1ef1f8c808 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1180,6 +1180,7 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_ } gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + UE->an_release = true; #ifdef E2_AGENT signal_rrc_state_changed_to(UE, RC_SM_RRC_IDLE); #endif diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index b24e6f594c..e20121e8c2 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -40,12 +40,17 @@ int get_ssb_scs(const struct f1ap_served_cell_info_t *cell_info) return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.tbw.scs : cell_info->fdd.dl_tbw.scs; } +static int ssb_arfcn_mtc(const NR_MeasurementTimingConfiguration_t *mtc) +{ + /* format has been verified when accepting MeasurementTimingConfiguration */ + NR_MeasTimingList_t *mtlist = mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming; + return mtlist->list.array[0]->frequencyAndTiming->carrierFreq; +} + int get_ssb_arfcn(const struct nr_rrc_du_container_t *du) { DevAssert(du != NULL && du->mtc != NULL); - /* format has been verified when accepting MeasurementTimingConfiguration */ - NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming; - return mtlist->list.array[0]->frequencyAndTiming->carrierFreq; + return ssb_arfcn_mtc(du->mtc); } static int du_compare(const nr_rrc_du_container_t *a, const nr_rrc_du_container_t *b) @@ -197,6 +202,58 @@ static void label_intra_frequency_neighbours(gNB_RRC_INST *rrc, for_each(cell_neighbour_list, (void *)&ssb_arfcn, is_intra_frequency_neighbour); } +static bool valid_du_in_neighbour_configs(const seq_arr_t *neighbour_cell_configuration, const f1ap_served_cell_info_t *cell, int ssb_arfcn) +{ + for (int c = 0; c < neighbour_cell_configuration->size; c++) { + const neighbour_cell_configuration_t *neighbour_config = seq_arr_at(neighbour_cell_configuration, c); + for (int ni = 0; ni < neighbour_config->neighbour_cells->size; ni++) { + const nr_neighbour_gnb_configuration_t *nc = seq_arr_at(neighbour_config->neighbour_cells, ni); + if (nc->nrcell_id != cell->nr_cellid) + continue; + // current cell is in the nc config, check that config matches + if (nc->physicalCellId != cell->nr_pci) { + LOG_W(NR_RRC, "Cell %ld in neighbour config: PCI mismatch (%d vs %d)\n", cell->nr_cellid, cell->nr_pci, nc->physicalCellId); + return false; + } + if (cell->tac && nc->tac != *cell->tac) { + LOG_W(NR_RRC, "Cell %ld in neighbour config: TAC mismatch (%d vs %d)\n", cell->nr_cellid, *cell->tac, nc->tac); + return false; + } + if (ssb_arfcn != nc->absoluteFrequencySSB) { + LOG_W(NR_RRC, + "Cell %ld in neighbour config: SSB ARFCN mismatch (%d vs %d)\n", + cell->nr_cellid, + ssb_arfcn, + nc->absoluteFrequencySSB); + return false; + } + if (get_ssb_scs(cell) != nc->subcarrierSpacing) { + LOG_W(NR_RRC, + "Cell %ld in neighbour config: SCS mismatch (%d vs %d)\n", + cell->nr_cellid, + get_ssb_scs(cell), + nc->subcarrierSpacing); + return false; + } + if (cell->plmn.mcc != nc->plmn.mcc || cell->plmn.mnc != nc->plmn.mnc + || cell->plmn.mnc_digit_length != nc->plmn.mnc_digit_length) { + LOG_W(NR_RRC, + "Cell %ld in neighbour config: PLMN mismatch (%03d.%0*d vs %03d.%0*d)\n", + cell->nr_cellid, + cell->plmn.mcc, + cell->plmn.mnc_digit_length, + cell->plmn.mnc, + nc->plmn.mcc, + nc->plmn.mnc_digit_length, + nc->plmn.mnc); + return false; + } + LOG_D(NR_RRC, "Cell %ld is neighbor of cell %ld\n", cell->nr_cellid, neighbour_config->nr_cell_id); + } + } + return true; +} + void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) { AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n"); @@ -219,10 +276,12 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) f1ap_served_cell_info_t *cell_info = &req->cell[0].info; if (!rrc_gNB_plmn_matches(rrc, cell_info)) { LOG_E(NR_RRC, - "PLMN mismatch: CU %d%d, DU %d%d\n", + "PLMN mismatch: CU %03d.%0*d, DU %03d%0*d\n", rrc->configuration.mcc[0], + rrc->configuration.mnc_digit_length[0], rrc->configuration.mnc[0], cell_info->plmn.mcc, + cell_info->plmn.mnc_digit_length, cell_info->plmn.mnc); f1ap_setup_failure_t fail = {.cause = F1AP_CauseRadioNetwork_plmn_not_served_by_the_gNB_CU}; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); @@ -264,6 +323,15 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) NR_MeasurementTimingConfiguration_t *mtc = extract_mtc(cell_info->measurement_timing_config, cell_info->measurement_timing_config_len); + if (rrc->neighbour_cell_configuration + && !valid_du_in_neighbour_configs(rrc->neighbour_cell_configuration, cell_info, ssb_arfcn_mtc(mtc))) { + LOG_E(NR_RRC, "problem with DU %ld in neighbor configuration, rejecting DU\n", req->gNB_DU_id); + f1ap_setup_failure_t fail = {.cause = F1AP_CauseMisc_unspecified}; + rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); + ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc); + return; + } + const f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info; NR_MIB_t *mib = NULL; NR_SIB1_t *sib1 = NULL; @@ -501,7 +569,7 @@ void dump_du_info(const gNB_RRC_INST *rrc, FILE *f) fprintf(f, "assoc_id %d", du->assoc_id); } const f1ap_served_cell_info_t *info = &sr->cell[0].info; - fprintf(f, ": nrCellID %ld, PCI %d\n", info->nr_cellid, info->nr_pci); + fprintf(f, ": nrCellID %ld, PCI %d, SSB ARFCN %d\n", info->nr_cellid, info->nr_pci, get_ssb_arfcn(du)); if (info->mode == F1AP_MODE_TDD) { const f1ap_nr_frequency_info_t *fi = &info->tdd.freqinfo; diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 205a58fc36..ab2bf13071 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -51,7 +51,7 @@ rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id) { - DevAssert(drb_id > 0 && drb_id < 32); + DevAssert(drb_id > 0 && drb_id <= 32); DevAssert(ue != NULL); return &ue->established_drbs[drb_id - 1]; @@ -96,10 +96,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, est_drb->status = DRB_ACTIVE; est_drb->drb_id = drb_id; - est_drb->reestablishPDCP = -1; - est_drb->recoverPDCP = -1; est_drb->cnAssociation.sdap_config.defaultDRB = true; - est_drb->defaultDRBid = drb_id; /* SDAP Configuration */ est_drb->cnAssociation.present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index eb5113ccee..477df28703 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -479,7 +479,7 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, // Actions following cell selection while T311 is running NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; - if (is_nr_timer_active(timers->T311)) { + if (nr_timer_is_active(&timers->T311)) { nr_timer_stop(&timers->T311); rrc->ra_trigger = RRC_CONNECTION_REESTABLISHMENT; @@ -1695,7 +1695,7 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded) { NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; - if (ra_succeeded && is_nr_timer_active(timers->T304)) { + if (ra_succeeded && nr_timer_is_active(&timers->T304)) { // successful Random Access procedure triggered by reconfigurationWithSync nr_timer_stop(&timers->T304); // TODO handle the rest of procedures as described in 5.3.5.3 for when @@ -2130,7 +2130,7 @@ static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_l process_nsa_message(NR_UE_rrc_inst, nr_SecondaryCellGroupConfig_r15, nr_SecondaryCellGroup_buffer, nr_SecondaryCellGroup_size); process_nsa_message(NR_UE_rrc_inst, nr_RadioBearerConfigX_r15, nr_RadioBearer_buffer, nr_RadioBearer_size); LOG_I(NR_RRC, "Calling do_NR_RRCReconfigurationComplete. t_id %ld \n", t_id); - uint8_t buffer[RRC_BUF_SIZE]; + uint8_t buffer[NR_RRC_BUF_SIZE]; size_t size = do_NR_RRCReconfigurationComplete_for_nsa(buffer, sizeof(buffer), t_id); nsa_sendmsg_to_lte_ue(buffer, size, NR_RRC_CONFIG_COMPLETE_REQ); break; @@ -2138,7 +2138,7 @@ static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_l case OAI_TUN_IFACE_NSA: { LOG_I(NR_RRC, "We got an OAI_TUN_IFACE_NSA!!\n"); - char cmd_line[RRC_BUF_SIZE]; + char cmd_line[NR_RRC_BUF_SIZE]; memcpy(cmd_line, msg_buffer, sizeof(cmd_line)); LOG_D(NR_RRC, "Command line: %s\n", cmd_line); if (background_system(cmd_line) != 0) @@ -2218,14 +2218,14 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, } } if (!waitTime) { - if (is_nr_timer_active(tac->T302)) { + if (nr_timer_is_active(&tac->T302)) { nr_timer_stop(&tac->T302); // TODO barring alleviation as in 5.3.14.4 // not implemented LOG_E(NR_RRC,"Go to IDLE. Barring alleviation not implemented\n"); } } - if (is_nr_timer_active(tac->T390)) { + if (nr_timer_is_active(&tac->T390)) { nr_timer_stop(&tac->T390); // TODO barring alleviation as in 5.3.14.4 // not implemented diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index 70a467691b..9e734a3188 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -560,7 +560,7 @@ void handle_rlf_sync(NR_UE_Timers_Constants_t *tac, { if (sync_msg == IN_SYNC) { tac->N310_cnt = 0; - if (is_nr_timer_active(tac->T310)) { + if (nr_timer_is_active(&tac->T310)) { tac->N311_cnt++; // Upon receiving N311 consecutive "in-sync" indications if (tac->N311_cnt >= tac->N311_k) { @@ -573,12 +573,12 @@ void handle_rlf_sync(NR_UE_Timers_Constants_t *tac, else { // OUT_OF_SYNC tac->N311_cnt = 0; - if(is_nr_timer_active(tac->T300) || - is_nr_timer_active(tac->T301) || - is_nr_timer_active(tac->T304) || - is_nr_timer_active(tac->T310) || - is_nr_timer_active(tac->T311) || - is_nr_timer_active(tac->T319)) + if(nr_timer_is_active(&tac->T300) || + nr_timer_is_active(&tac->T301) || + nr_timer_is_active(&tac->T304) || + nr_timer_is_active(&tac->T310) || + nr_timer_is_active(&tac->T311) || + nr_timer_is_active(&tac->T319)) return; tac->N310_cnt++; // upon receiving N310 consecutive "out-of-sync" indications diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index ffd4bba3f5..a6d3a11a39 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -787,7 +787,7 @@ sctp_eNB_read_from_socket( SCTP_ERROR("sctp_recvmsg (fd %d, len %d ): %s:%d\n", sctp_cnx->sd, n, strerror(errno), errno); sctp_itti_send_association_resp( - sctp_cnx->task_id, sctp_cnx->instance, -1, + sctp_cnx->task_id, sctp_cnx->instance, sctp_cnx->assoc_id, sctp_cnx->cnx_id, SCTP_STATE_UNREACHABLE, 0, 0); close(sctp_cnx->sd);