Commit bacce39a authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/rrc-meas' into integration_2022_wk44

parents 3e0efbde 1c73dec5
......@@ -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
......
......@@ -1993,19 +1993,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);
}
......@@ -2447,3 +2434,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;
}
......@@ -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__ */
......@@ -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,25 @@ 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);
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;
}
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);
}
//-----------------------------------------------------------------------------
int
rrc_gNB_decode_dcch(
......@@ -2453,6 +2478,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) {
......@@ -3606,9 +3639,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;i<cap->rf_Parameters.supportedBandListNR.list.count;i++) {
......@@ -3657,9 +3689,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;i<cap->rf_Parameters.supportedBandListNR.list.count;i++) {
......@@ -3708,7 +3739,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 +3757,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 +3774,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 +3790,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 +3869,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 +3876,66 @@ 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";
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));
}
if (ue_ctxt->measResults)
print_rrc_meas(f, ue_ctxt->measResults);
}
fclose(f);
}
///---------------------------------------------------------------------------------------------------------------///
///---------------------------------------------------------------------------------------------------------------///
void *rrc_gnb_task(void *args_p) {
......@@ -3883,6 +3954,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 +3968,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 +3978,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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment