From 1c778ef38204703eb5fb41fb95661a8cfd3f1b79 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 19 Oct 2022 10:46:24 +0200 Subject: [PATCH 1/4] Refactor and enable logging in nrRRC_stats.log --- openair2/RRC/NR/rrc_gNB.c | 95 ++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index b5941a5b0c..a279ab8b02 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -3606,9 +3606,8 @@ unsigned int mask_flip(unsigned int x) { return((((x>>8) + (x<<8))&0xffff)>>6); } -unsigned int get_dl_bw_mask(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { - - +static unsigned int get_dl_bw_mask(const gNB_RRC_INST *rrc, const NR_UE_NR_Capability_t *cap) +{ int common_band = *rrc->carrier.servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; int common_scs = rrc->carrier.servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; for (int i=0;irf_Parameters.supportedBandListNR.list.count;i++) { @@ -3657,9 +3656,8 @@ unsigned int get_dl_bw_mask(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { return(0); } -unsigned int get_ul_bw_mask(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { - - +static unsigned int get_ul_bw_mask(const gNB_RRC_INST *rrc, const NR_UE_NR_Capability_t *cap) +{ int common_band = *rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0]; int common_scs = rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; for (int i=0;irf_Parameters.supportedBandListNR.list.count;i++) { @@ -3708,7 +3706,8 @@ unsigned int get_ul_bw_mask(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { return(0); } -int get_ul_mimo_layersCB(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { +static int get_ul_mimo_layersCB(const gNB_RRC_INST *rrc, const NR_UE_NR_Capability_t *cap) +{ int common_scs = rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; // check featureSet @@ -3725,7 +3724,8 @@ int get_ul_mimo_layersCB(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { return(1); } -int get_ul_mimo_layers(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { +static int get_ul_mimo_layers(const gNB_RRC_INST *rrc, const NR_UE_NR_Capability_t *cap) +{ int common_scs = rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; // check featureSet @@ -3741,7 +3741,8 @@ int get_ul_mimo_layers(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { return(1); } -int get_dl_mimo_layers(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { +static int get_dl_mimo_layers(const gNB_RRC_INST *rrc, const NR_UE_NR_Capability_t *cap) +{ int common_scs = rrc->carrier.servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; // check featureSet @@ -3756,36 +3757,15 @@ int get_dl_mimo_layers(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { } return(1); } + void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { MessageDef *msg; rrc_gNB_ue_context_t *ue_context_p = NULL; - FILE *fd=NULL;//fopen("nrRRCstats.log","w"); RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &(RC.nrrrc[ctxt_pP->module_id]->rrc_ue_head)) { ctxt_pP->rnti = ue_context_p->ue_id_rnti; gNB_MAC_INST *nrmac=RC.nrmac[ctxt_pP->module_id]; //WHAT A BEAUTIFULL RACE CONDITION !!! - if (fd) { - if (ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.presence == true) { - fprintf(fd,"NR RRC UE rnti %x: S-TMSI %x failure timer %d/8\n", - ue_context_p->ue_id_rnti, - ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.fiveg_tmsi, - ue_context_p->ue_context.ul_failure_timer); - } else { - fprintf(fd,"NR RRC UE rnti %x failure timer %d/8\n", - ue_context_p->ue_id_rnti, - ue_context_p->ue_context.ul_failure_timer); - } - - if (ue_context_p->ue_context.UE_Capability_nr) { - fprintf(fd,"NR RRC UE cap: BW DL %x. BW UL %x, DL MIMO Layers %d UL MIMO Layers (CB) %d UL MIMO Layers (nonCB) %d\n", - get_dl_bw_mask(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr), - get_ul_bw_mask(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr), - get_dl_mimo_layers(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr), - get_ul_mimo_layersCB(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr), - get_ul_mimo_layers(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr)); - } - } if (ue_context_p->ue_context.ul_failure_timer > 0) { ue_context_p->ue_context.ul_failure_timer++; @@ -3856,8 +3836,6 @@ void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { } } - if (fd) fclose(fd); - /* send a tick to x2ap */ if (is_x2ap_enabled()){ msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_SUBFRAME_PROCESS); @@ -3865,6 +3843,42 @@ void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { } } +static void write_rrc_stats(const gNB_RRC_INST *rrc) +{ + const char *filename = "nrRRC_stats.log"; + FILE *f = fopen(filename, "w"); + if (f == NULL) { + LOG_E(NR_RRC, "cannot open %s for writing\n", filename); + return; + } + + rrc_gNB_ue_context_t *ue_context_p = NULL; + /* cast is necessary to eliminate warning "discards ‘const’ qualifier" */ + RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &((gNB_RRC_INST *)rrc)->rrc_ue_head) { + const rnti_t rnti = ue_context_p->ue_id_rnti; + const gNB_RRC_UE_t *ue_ctxt = &ue_context_p->ue_context; + + fprintf(f, "NR RRC UE rnti %04x:", rnti); + + if (ue_ctxt->Initialue_identity_5g_s_TMSI.presence) + fprintf(f, " S-TMSI %x\n", ue_ctxt->Initialue_identity_5g_s_TMSI.fiveg_tmsi); + + fprintf(f, " failure timer %d/8\n", ue_ctxt->ul_failure_timer); + + if (ue_ctxt->UE_Capability_nr) { + fprintf(f, + " UE cap: BW DL %x. BW UL %x, DL MIMO Layers %d UL MIMO Layers (CB) %d UL MIMO Layers (nonCB) %d\n", + get_dl_bw_mask(rrc, ue_ctxt->UE_Capability_nr), + get_ul_bw_mask(rrc, ue_ctxt->UE_Capability_nr), + get_dl_mimo_layers(rrc, ue_ctxt->UE_Capability_nr), + get_ul_mimo_layersCB(rrc, ue_ctxt->UE_Capability_nr), + get_ul_mimo_layers(rrc, ue_ctxt->UE_Capability_nr)); + } + } + + fclose(f); +} + ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// void *rrc_gnb_task(void *args_p) { @@ -3883,6 +3897,11 @@ void *rrc_gnb_task(void *args_p) { .eNB_index=0, .brOption=false }; + + /* timer to write stats to file */ + long stats_timer_id = 1; + timer_setup(1, 0, TASK_RRC_GNB, 0, TIMER_PERIODIC, NULL, &stats_timer_id); + itti_mark_task_ready(TASK_RRC_GNB); LOG_I(NR_RRC,"Entering main loop of NR_RRC message task\n"); @@ -3892,10 +3911,6 @@ void *rrc_gnb_task(void *args_p) { msg_name_p = ITTI_MSG_NAME(msg_p); instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p); - /* RRC_SUBFRAME_PROCESS is sent every subframe, do not log it */ - if (ITTI_MSG_ID(msg_p) != RRC_SUBFRAME_PROCESS) - LOG_I(NR_RRC,"Received message %s\n",msg_name_p); - switch (ITTI_MSG_ID(msg_p)) { case TERMINATE_MESSAGE: LOG_W(NR_RRC, " *** Exiting NR_RRC thread\n"); @@ -3906,6 +3921,12 @@ void *rrc_gnb_task(void *args_p) { LOG_I(NR_RRC, "[gNB %ld] Received %s\n", instance, msg_name_p); break; + case TIMER_HAS_EXPIRED: + /* only this one handled for now */ + DevAssert(TIMER_HAS_EXPIRED(msg_p).timer_id == stats_timer_id); + write_rrc_stats(RC.nrrrc[0]); + break; + case RRC_SUBFRAME_PROCESS: nr_rrc_subframe_process(&RRC_SUBFRAME_PROCESS(msg_p).ctxt, RRC_SUBFRAME_PROCESS(msg_p).CC_id); break; From 6762342d25c204c469af64de670876fdd024d84e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 21 May 2022 16:14:08 +0200 Subject: [PATCH 2/4] Add periodic RRC measurements --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 105 ++++++++++++++++++++++++---- openair2/RRC/NR/MESSAGES/asn1_msg.h | 2 + openair2/RRC/NR/rrc_gNB.c | 44 +++++++++++- 3 files changed, 136 insertions(+), 15 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 82ecf18812..98d21ca452 100755 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -2096,19 +2096,6 @@ int16_t do_RRCReconfiguration( return -1; } - LOG_D(NR_RRC,"[gNB %d] RRCReconfiguration for UE %x Encoded %zd bits (%zd bytes)\n", - ctxt_pP->module_id, - ctxt_pP->rnti, - enc_rval.encoded, - (enc_rval.encoded+7)/8); - - if (enc_rval.encoded == -1) { - LOG_E(NR_RRC,"[gNB %d] ASN1 : RRCReconfiguration encoding failed for UE %x\n", - ctxt_pP->module_id, - ctxt_pP->rnti); - return(-1); - } - return((enc_rval.encoded+7)/8); } @@ -2550,3 +2537,95 @@ do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_T return((enc_rval.encoded+7)/8); } +NR_MeasConfig_t *get_defaultMeasConfig(const gNB_RrcConfigurationReq *conf) +{ + const NR_FrequencyInfoDL_t *freqInfoDL = conf->scc->downlinkConfigCommon->frequencyInfoDL; + const NR_ARFCN_ValueNR_t absFreqSSB = *freqInfoDL->absoluteFrequencySSB; + DevAssert(freqInfoDL->scs_SpecificCarrierList.list.count == 1); + const NR_SubcarrierSpacing_t scs = freqInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + DevAssert(freqInfoDL->frequencyBandList.list.count == 1); + const NR_FreqBandIndicatorNR_t band = *freqInfoDL->frequencyBandList.list.array[0]; + + NR_MeasConfig_t *mc = calloc(1, sizeof(*mc)); + mc->measObjectToAddModList = calloc(1, sizeof(*mc->measObjectToAddModList)); + mc->reportConfigToAddModList = calloc(1, sizeof(*mc->reportConfigToAddModList)); + + // Measurement Objects: Specifies what is to be measured. For NR and inter-RAT E-UTRA measurements, this may include + // cell-specific offsets, blacklisted cells to be ignored and whitelisted cells to consider for measurements. + NR_MeasObjectToAddMod_t *mo1 = calloc(1, sizeof(*mo1)); + mo1->measObjectId = 1; + mo1->measObject.present = NR_MeasObjectToAddMod__measObject_PR_measObjectNR; + NR_MeasObjectNR_t *monr1 = calloc(1, sizeof(*monr1)); + asn1cCallocOne(monr1->ssbFrequency, absFreqSSB); + asn1cCallocOne(monr1->ssbSubcarrierSpacing, scs); + monr1->referenceSignalConfig.ssb_ConfigMobility = calloc(1, sizeof(*monr1->referenceSignalConfig.ssb_ConfigMobility)); + monr1->referenceSignalConfig.ssb_ConfigMobility->deriveSSB_IndexFromCell = true; + monr1->absThreshSS_BlocksConsolidation = calloc(1, sizeof(*monr1->absThreshSS_BlocksConsolidation)); + asn1cCallocOne(monr1->absThreshSS_BlocksConsolidation->thresholdRSRP, 36); + asn1cCallocOne(monr1->nrofSS_BlocksToAverage, 8); + monr1->smtc1 = calloc(1, sizeof(*monr1->smtc1)); + monr1->smtc1->periodicityAndOffset.present = NR_SSB_MTC__periodicityAndOffset_PR_sf20; + monr1->smtc1->periodicityAndOffset.choice.sf20 = 2; + monr1->smtc1->duration = NR_SSB_MTC__duration_sf2; + monr1->quantityConfigIndex = 1; + monr1->ext1 = calloc(1, sizeof(*monr1->ext1)); + asn1cCallocOne(monr1->ext1->freqBandIndicatorNR, band); + mo1->measObject.choice.measObjectNR = monr1; + int ret = ASN_SEQUENCE_ADD(&mc->measObjectToAddModList->list, mo1); + AssertFatal(ret == 0, "ASN_SEQUENCE_ADD() returned %d\n", ret); + + // Reporting Configuration: Specifies how reporting should be done. This could be periodic or event-triggered. + NR_ReportConfigToAddMod_t *rc = calloc(1, sizeof(*rc)); + rc->reportConfigId = 1; + rc->reportConfig.present = NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR; + + NR_PeriodicalReportConfig_t *prc = calloc(1, sizeof(*prc)); + prc->rsType = NR_NR_RS_Type_ssb; + prc->reportInterval = NR_ReportInterval_ms1024; + prc->reportAmount = NR_PeriodicalReportConfig__reportAmount_infinity; + prc->reportQuantityCell.rsrp = true; + prc->reportQuantityCell.rsrq = true; + prc->reportQuantityCell.sinr = true; + prc->reportQuantityRS_Indexes = calloc(1, sizeof(*prc->reportQuantityRS_Indexes)); + prc->reportQuantityRS_Indexes->rsrp = true; + prc->reportQuantityRS_Indexes->rsrq = true; + prc->reportQuantityRS_Indexes->sinr = true; + asn1cCallocOne(prc->maxNrofRS_IndexesToReport, 4); + prc->maxReportCells = 4; + prc->includeBeamMeasurements = true; + + NR_ReportConfigNR_t *rcnr = calloc(1, sizeof(*rcnr)); + rcnr->reportType.present = NR_ReportConfigNR__reportType_PR_periodical; + rcnr->reportType.choice.periodical = prc; + + + rc->reportConfig.choice.reportConfigNR = rcnr; + ret = ASN_SEQUENCE_ADD(&mc->reportConfigToAddModList->list, rc); + AssertFatal(ret == 0, "ASN_SEQUENCE_ADD() returned %d\n", ret); + //prc->reportQuantityRS_Indexes->rsrp = 1; + + // Measurement ID: Identifies how to report measurements of a specific object. This is a many-to-many mapping: a + // measurement object could have multiple reporting configurations, a reporting configuration could apply to multiple + // objects. A unique ID is used for each object-to-report-config association. When UE sends a MeasurementReport + // message, a single ID and related measurements are included in the message. + mc->measIdToAddModList = calloc(1, sizeof(*mc->measIdToAddModList)); + NR_MeasIdToAddMod_t *measid = calloc(1, sizeof(*measid)); + measid->measId = 1; + measid->measObjectId = 1; + measid->reportConfigId = 1; + ret = ASN_SEQUENCE_ADD(&mc->measIdToAddModList->list, measid); + AssertFatal(ret == 0, "ASN_SEQUENCE_ADD() returned %d\n", ret); + + // Quantity Configuration: Specifies parameters for layer 3 filtering of measurements. Only after filtering, reporting + // criteria are evaluated. The formula used is F_n = (1-a)F_(n-1) + a*M_n, where M is the latest measurement, F is the + // filtered measurement, and ais based on configured filter coefficient. + mc->quantityConfig = calloc(1, sizeof(*mc->quantityConfig)); + mc->quantityConfig->quantityConfigNR_List = calloc(1, sizeof(*mc->quantityConfig->quantityConfigNR_List)); + NR_QuantityConfigNR_t *qcnr3 = calloc(1, sizeof(*qcnr3)); + asn1cCallocOne(qcnr3->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRP, NR_FilterCoefficient_fc6); + asn1cCallocOne(qcnr3->quantityConfigCell.csi_RS_FilterConfig.filterCoefficientRSRP, NR_FilterCoefficient_fc6); + ret = ASN_SEQUENCE_ADD(&mc->quantityConfig->quantityConfigNR_List->list, qcnr3); + AssertFatal(ret == 0, "ASN_SEQUENCE_ADD() returned %d\n", ret); + + return mc; +} diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 770399b382..1e1b59de82 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -207,4 +207,6 @@ do_RRCReestablishmentComplete( uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier); +NR_MeasConfig_t *get_defaultMeasConfig(const gNB_RrcConfigurationReq *conf); + #endif /* __RRC_NR_MESSAGES_ASN1_MSG__H__ */ diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index a279ab8b02..a1e8e860c3 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -541,7 +541,7 @@ rrc_gNB_generate_defaultRRCReconfiguration( //----------------------------------------------------------------------------- { uint8_t buffer[RRC_BUF_SIZE]; - uint16_t size; + int16_t size; /*NR_SRB_ToAddModList_t **SRB_configList2 = NULL; NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; NR_DRB_ToAddModList_t **DRB_configList = NULL; @@ -651,6 +651,8 @@ rrc_gNB_generate_defaultRRCReconfiguration( } gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + NR_MeasConfig_t *measconfig = get_defaultMeasConfig(&rrc->configuration); + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; memset(buffer, 0, sizeof(buffer)); size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer), @@ -660,13 +662,17 @@ rrc_gNB_generate_defaultRRCReconfiguration( NULL, NULL, NULL, - NULL, + measconfig, dedicatedNAS_MessageList, ue_context_pP, &rrc->carrier, &rrc->configuration, NULL, ue_p->masterCellGroup); + AssertFatal(size > 0, "cannot encode RRCReconfiguration in %s()\n", __func__); + LOG_W(RRC, "do_RRCReconfiguration(): size %d\n", size); + + xer_fprint(stdout,&asn_DEF_NR_CellGroupConfig, ue_p->masterCellGroup); free(ue_context_pP->ue_context.nas_pdu.buffer); @@ -2234,6 +2240,32 @@ static inline uint64_t bitStr_to_uint64(BIT_STRING_t *asn) { return result; } +static void rrc_gNB_process_MeasurementReport(rrc_gNB_ue_context_t *ue_context, const NR_MeasurementReport_t *measurementReport) +{ + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_MeasurementReport, (void *)measurementReport); + + DevAssert(measurementReport->criticalExtensions.present == NR_MeasurementReport__criticalExtensions_PR_measurementReport + && measurementReport->criticalExtensions.choice.measurementReport != NULL); + + const NR_MeasResults_t *measresults = &measurementReport->criticalExtensions.choice.measurementReport->measResults; + + AssertFatal(measresults->measId == 1, "unexpected MeasResult for MeasurementId %ld received\n", measresults->measId); + DevAssert(measresults->measResultServingMOList.list.count >= 1); + if (measresults->measResultServingMOList.list.count > 1) + LOG_W(RRC, "Received %d MeasResultServMO, but handling only 1!\n", measresults->measResultServingMOList.list.count); + + NR_MeasResultServMO_t *measresultservmo = measresults->measResultServingMOList.list.array[0]; + NR_MeasResultNR_t *measresultnr = &measresultservmo->measResultServingCell; + NR_MeasQuantityResults_t *mqr = measresultnr->measResult.cellResults.resultsSSB_Cell; + + LOG_I(RRC, "RNTI %04x servingCellId %ld MeasResultNR for phyCellId %ld:\n", ue_context->ue_context.rnti, measresultservmo->servCellId, *measresultnr->physCellId); + if (mqr != NULL) + LOG_I(RRC, " resultSSB: RSRP %ld dBm RSRQ %.1f dB SINR %.1f dB\n", *mqr->rsrp - 156, (float) (*mqr->rsrq - 87) / 2.0f, (float) (*mqr->sinr - 46) / 2.0f); + else + LOG_I(RRC, " resultSSB: NOT PROVIDED\n"); +} + //----------------------------------------------------------------------------- int rrc_gNB_decode_dcch( @@ -2453,6 +2485,14 @@ rrc_gNB_decode_dcch( ue_context_p->ue_context.ue_release_timer = 0; break; + case NR_UL_DCCH_MessageType__c1_PR_measurementReport: + DevAssert(ul_dcch_msg != NULL + && ul_dcch_msg->message.present == NR_UL_DCCH_MessageType_PR_c1 + && ul_dcch_msg->message.choice.c1 + && ul_dcch_msg->message.choice.c1->present == NR_UL_DCCH_MessageType__c1_PR_measurementReport); + rrc_gNB_process_MeasurementReport(ue_context_p, ul_dcch_msg->message.choice.c1->choice.measurementReport); + break; + case NR_UL_DCCH_MessageType__c1_PR_ulInformationTransfer: LOG_I(NR_RRC,"Recived RRC GNB UL Information Transfer \n"); if(!ue_context_p) { From 1ae1b0aa9f8d2ebe7a12e445ea1ebf33214c4663 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 19 Oct 2022 14:11:49 +0200 Subject: [PATCH 3/4] Print RRC meas periodically --- openair2/RRC/NR/rrc_gNB.c | 47 ++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index a1e8e860c3..fdd6fb9544 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2248,22 +2248,15 @@ static void rrc_gNB_process_MeasurementReport(rrc_gNB_ue_context_t *ue_context, DevAssert(measurementReport->criticalExtensions.present == NR_MeasurementReport__criticalExtensions_PR_measurementReport && measurementReport->criticalExtensions.choice.measurementReport != NULL); - const NR_MeasResults_t *measresults = &measurementReport->criticalExtensions.choice.measurementReport->measResults; + gNB_RRC_UE_t *ue_ctxt = &ue_context->ue_context; + if (ue_ctxt->measResults != NULL) { + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_MeasResults, ue_ctxt->measResults); + ue_ctxt->measResults = NULL; + } - AssertFatal(measresults->measId == 1, "unexpected MeasResult for MeasurementId %ld received\n", measresults->measId); - DevAssert(measresults->measResultServingMOList.list.count >= 1); - if (measresults->measResultServingMOList.list.count > 1) - LOG_W(RRC, "Received %d MeasResultServMO, but handling only 1!\n", measresults->measResultServingMOList.list.count); - - NR_MeasResultServMO_t *measresultservmo = measresults->measResultServingMOList.list.array[0]; - NR_MeasResultNR_t *measresultnr = &measresultservmo->measResultServingCell; - NR_MeasQuantityResults_t *mqr = measresultnr->measResult.cellResults.resultsSSB_Cell; - - LOG_I(RRC, "RNTI %04x servingCellId %ld MeasResultNR for phyCellId %ld:\n", ue_context->ue_context.rnti, measresultservmo->servCellId, *measresultnr->physCellId); - if (mqr != NULL) - LOG_I(RRC, " resultSSB: RSRP %ld dBm RSRQ %.1f dB SINR %.1f dB\n", *mqr->rsrp - 156, (float) (*mqr->rsrq - 87) / 2.0f, (float) (*mqr->sinr - 46) / 2.0f); - else - LOG_I(RRC, " resultSSB: NOT PROVIDED\n"); + const NR_MeasId_t id = measurementReport->criticalExtensions.choice.measurementReport->measResults.measId; + AssertFatal(id, "unexpected MeasResult for MeasurementId %ld received\n", id); + asn1cCallocOne(ue_ctxt->measResults, measurementReport->criticalExtensions.choice.measurementReport->measResults); } //----------------------------------------------------------------------------- @@ -3883,6 +3876,27 @@ void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { } } +static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults) +{ + DevAssert(measresults->measResultServingMOList.list.count >= 1); + if (measresults->measResultServingMOList.list.count > 1) + LOG_W(RRC, "Received %d MeasResultServMO, but handling only 1!\n", measresults->measResultServingMOList.list.count); + + NR_MeasResultServMO_t *measresultservmo = measresults->measResultServingMOList.list.array[0]; + NR_MeasResultNR_t *measresultnr = &measresultservmo->measResultServingCell; + NR_MeasQuantityResults_t *mqr = measresultnr->measResult.cellResults.resultsSSB_Cell; + + fprintf(f, " servingCellId %ld MeasResultNR for phyCellId %ld:\n resultSSB:", measresultservmo->servCellId, *measresultnr->physCellId); + if (mqr != NULL) { + const long rrsrp = *mqr->rsrp - 156; + const float rrsrq = (float) (*mqr->rsrq - 87) / 2.0f; + const float rsinr = (float) (*mqr->sinr - 46) / 2.0f; + fprintf(f, "RSRP %ld dBm RSRQ %.1f dB SINR %.1f dB\n", rrsrp, rrsrq, rsinr); + } else { + fprintf(f, "NOT PROVIDED\n"); + } +} + static void write_rrc_stats(const gNB_RRC_INST *rrc) { const char *filename = "nrRRC_stats.log"; @@ -3914,6 +3928,9 @@ static void write_rrc_stats(const gNB_RRC_INST *rrc) get_ul_mimo_layersCB(rrc, ue_ctxt->UE_Capability_nr), get_ul_mimo_layers(rrc, ue_ctxt->UE_Capability_nr)); } + + if (ue_ctxt->measResults) + print_rrc_meas(f, ue_ctxt->measResults); } fclose(f); From 1c73dec53fc7c5dd693c3247f2b5164b6221aa71 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 3 Nov 2022 17:18:48 +0100 Subject: [PATCH 4/4] Update FEATURE_SET.md --- doc/FEATURE_SET.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index d08c1e9b2a..cd543412d1 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -359,6 +359,7 @@ The following features are valid for the gNB and the 5G-NR UE. - Support for master cell group configuration - Interface with NGAP for the interactions with the AMF - Interface with F1AP for CU/DU split deployment option + - Periodic RRC measurements of serving cell (no A/B events) **gNB X2AP** - Integration of X2AP messages and procedures for the exchanges with the eNB over X2 interface supporting the NSA setup according to 36.423 Rel. 15