From 6762342d25c204c469af64de670876fdd024d84e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 21 May 2022 16:14:08 +0200 Subject: [PATCH] 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) {