Commit 2f81f190 authored by Giulio Carota's avatar Giulio Carota Committed by Robert Schmidt

Generate TimingMeasurementConfig at DU, store at CU

parent a771d584
......@@ -140,7 +140,8 @@ typedef struct f1ap_served_cell_info_t {
f1ap_tdd_info_t tdd;
};
char *measurement_timing_information;
uint8_t *measurement_timing_config;
int measurement_timing_config_len;
} f1ap_served_cell_info_t;
typedef struct f1ap_gnb_du_system_info_t {
......
......@@ -67,6 +67,14 @@ int CU_send_ERROR_INDICATION(sctp_assoc_t assoc_id, F1AP_ErrorIndication_t *Erro
AssertFatal(1==0,"Not implemented yet\n");
}
static uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len)
{
uint8_t *buf = calloc(os->size, sizeof(*buf));
AssertFatal(buf != NULL, "out of memory\n");
memcpy(buf, os->buf, os->size);
*len = os->size;
return buf;
}
/*
F1 Setup
......@@ -187,6 +195,11 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint3
AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present);
}
/* MeasurementConfig */
if (servedCellInformation->measurementTimingConfiguration.size > 0)
req->cell[i].info.measurement_timing_config =
cp_octet_string(&servedCellInformation->measurementTimingConfiguration, &req->cell[i].info.measurement_timing_config_len);
struct F1AP_GNB_DU_System_Information * DUsi=served_cells_item->gNB_DU_System_Information;
if (DUsi != NULL) {
// System Information
......@@ -537,6 +550,12 @@ int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t asso
AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present);
}
/* MeasurementConfig */
if (servedCellInformation->measurementTimingConfiguration.size > 0)
req->cell_to_add[i].info.measurement_timing_config =
cp_octet_string(&servedCellInformation->measurementTimingConfiguration,
&req->cell_to_add[i].info.measurement_timing_config_len);
struct F1AP_GNB_DU_System_Information *DUsi = served_cells_item->gNB_DU_System_Information;
// System Information
req->cell_to_add[i].sys_info = calloc(1, sizeof(*req->cell_to_add[i].sys_info));
......@@ -648,7 +667,12 @@ int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t asso
} else {
AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present);
}
// TODO: Measurement Config
/* MeasurementConfig */
if (servedCellInformation->measurementTimingConfiguration.size > 0)
req->cell_to_modify[i].info.measurement_timing_config =
cp_octet_string(&servedCellInformation->measurementTimingConfiguration,
&req->cell_to_modify[i].info.measurement_timing_config_len);
/*gNB DU SYSTEM INFORMATION */
struct F1AP_GNB_DU_System_Information *DUsi = served_cells_item->gNB_DU_System_Information;
......
......@@ -196,10 +196,9 @@ static F1AP_Served_Cell_Information_t encode_served_cell_info(const f1ap_served_
}
/* - measurementTimingConfiguration */
char *measurementTimingConfiguration = c->measurement_timing_information;
OCTET_STRING_fromBuf(&scell_info.measurementTimingConfiguration,
measurementTimingConfiguration,
strlen(measurementTimingConfiguration));
(const char *)c->measurement_timing_config,
c->measurement_timing_config_len);
return scell_info;
}
......
......@@ -82,6 +82,7 @@
#include "NR_RateMatchPatternLTE-CRS.h"
#include "NR_SearchSpace.h"
#include "NR_ControlResourceSet.h"
#include "NR_MeasurementTimingConfiguration.h"
#include "NR_EUTRA-MBSFN-SubframeConfig.h"
#include "uper_decoder.h"
#include "uper_encoder.h"
......@@ -1168,7 +1169,16 @@ static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
req->cell[0].info.fdd = read_fdd_config(scc);
}
req->cell[0].info.measurement_timing_information = "0";
NR_MeasurementTimingConfiguration_t *mtc = get_new_MeasurementTimingConfiguration(scc);
uint8_t buf[1024];
int len = encode_MeasurementTimingConfiguration(mtc, buf, sizeof(buf));
DevAssert(len <= sizeof(buf));
free_MeasurementTimingConfiguration(mtc);
uint8_t *mtc_buf = calloc(len, sizeof(*mtc_buf));
AssertFatal(mtc_buf != NULL, "out of memory\n");
memcpy(mtc_buf, buf, len);
req->cell[0].info.measurement_timing_config = mtc_buf;
req->cell[0].info.measurement_timing_config_len = len;
if (get_softmodem_params()->sa) {
// in NSA we don't transmit SIB1, so cannot fill DU system information
......
......@@ -39,8 +39,14 @@ static void f1_setup_request_direct(const f1ap_setup_req_t *req)
AssertFatal(f1ap_msg->cell[n].info.tac != NULL, "out of memory\n");
*f1ap_msg->cell[n].info.tac = *req->cell[n].info.tac;
}
if (req->cell[n].info.measurement_timing_information)
f1ap_msg->cell[n].info.measurement_timing_information = strdup(req->cell[n].info.measurement_timing_information);
if (req->cell[n].info.measurement_timing_config_len > 0) {
f1ap_msg->cell[n].info.measurement_timing_config = calloc(req->cell[n].info.measurement_timing_config_len, sizeof(uint8_t));
AssertFatal(f1ap_msg->cell[n].info.measurement_timing_config != NULL, "out of memory\n");
memcpy(f1ap_msg->cell[n].info.measurement_timing_config,
req->cell[n].info.measurement_timing_config,
req->cell[n].info.measurement_timing_config_len);
f1ap_msg->cell[n].info.measurement_timing_config_len = req->cell[n].info.measurement_timing_config_len;
}
if (req->cell[n].sys_info) {
f1ap_gnb_du_system_info_t *orig_sys_info = req->cell[n].sys_info;
......@@ -85,9 +91,15 @@ static void gnb_du_configuration_update_direct(const f1ap_gnb_du_configuration_u
AssertFatal(f1ap_msg->cell_to_modify[n].info.tac != NULL, "out of memory\n");
*f1ap_msg->cell_to_modify[n].info.tac = *upd->cell_to_modify[n].info.tac;
}
if (upd->cell_to_modify[n].info.measurement_timing_information)
f1ap_msg->cell_to_modify[n].info.measurement_timing_information =
strdup(upd->cell_to_modify[n].info.measurement_timing_information);
if (upd->cell_to_modify[n].info.measurement_timing_config_len > 0) {
f1ap_msg->cell_to_modify[n].info.measurement_timing_config =
calloc(upd->cell_to_modify[n].info.measurement_timing_config_len, sizeof(uint8_t));
AssertFatal(f1ap_msg->cell_to_modify[n].info.measurement_timing_config != NULL, "out of memory\n");
memcpy(f1ap_msg->cell_to_modify[n].info.measurement_timing_config,
upd->cell_to_modify[n].info.measurement_timing_config,
upd->cell_to_modify[n].info.measurement_timing_config_len);
f1ap_msg->cell_to_modify[n].info.measurement_timing_config_len = upd->cell_to_modify[n].info.measurement_timing_config_len;
}
if (upd->cell_to_modify[n].sys_info) {
f1ap_gnb_du_system_info_t *orig_sys_info = upd->cell_to_modify[n].sys_info;
......
......@@ -69,8 +69,14 @@ static void f1_setup_request_f1ap(const f1ap_setup_req_t *req)
AssertFatal(f1ap_setup->cell[n].info.tac != NULL, "out of memory\n");
*f1ap_setup->cell[n].info.tac = *req->cell[n].info.tac;
}
if (req->cell[n].info.measurement_timing_information)
f1ap_setup->cell[n].info.measurement_timing_information = strdup(req->cell[n].info.measurement_timing_information);
if (req->cell[n].info.measurement_timing_config_len > 0) {
f1ap_setup->cell[n].info.measurement_timing_config = calloc(req->cell[n].info.measurement_timing_config_len, sizeof(uint8_t));
AssertFatal(f1ap_setup->cell[n].info.measurement_timing_config != NULL, "out of memory\n");
memcpy(f1ap_setup->cell[n].info.measurement_timing_config,
req->cell[n].info.measurement_timing_config,
req->cell[n].info.measurement_timing_config_len);
f1ap_setup->cell[n].info.measurement_timing_config_len = req->cell[n].info.measurement_timing_config_len;
}
if (req->cell[n].sys_info) {
f1ap_gnb_du_system_info_t *orig_sys_info = req->cell[n].sys_info;
......
......@@ -36,6 +36,8 @@
#include "oai_asn1.h"
#include "SIMULATION/TOOLS/sim.h" // for taus();
#include "NR_MeasurementTimingConfiguration.h"
#include "uper_decoder.h"
#include "uper_encoder.h"
......@@ -1887,6 +1889,83 @@ int encode_MIB_NR_setup(NR_MIB_t *mib, int frame, uint8_t *buf, int buf_size)
return (enc_rval.encoded + 7) / 8;
}
static struct NR_SSB_MTC__periodicityAndOffset get_SSB_MTC_periodicityAndOffset(long ssb_periodicityServingCell)
{
struct NR_SSB_MTC__periodicityAndOffset po = {0};
switch (ssb_periodicityServingCell) {
case NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms5:
po.present = NR_SSB_MTC__periodicityAndOffset_PR_sf5;
po.choice.sf5 = 0;
break;
case NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms10:
po.present = NR_SSB_MTC__periodicityAndOffset_PR_sf10;
po.choice.sf10 = 0;
break;
case NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms20:
po.present = NR_SSB_MTC__periodicityAndOffset_PR_sf20;
po.choice.sf20 = 0;
break;
case NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms40:
po.present = NR_SSB_MTC__periodicityAndOffset_PR_sf40;
po.choice.sf40 = 0;
break;
case NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms80:
po.present = NR_SSB_MTC__periodicityAndOffset_PR_sf80;
po.choice.sf80 = 0;
break;
case NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms160:
po.present = NR_SSB_MTC__periodicityAndOffset_PR_sf160;
po.choice.sf160 = 0;
break;
default:
AssertFatal(false, "illegal ssb_periodicityServingCell %ld\n", ssb_periodicityServingCell);
break;
}
return po;
}
NR_MeasurementTimingConfiguration_t *get_new_MeasurementTimingConfiguration(const NR_ServingCellConfigCommon_t *scc)
{
NR_MeasurementTimingConfiguration_t *mtc = calloc(1, sizeof(*mtc));
AssertFatal(mtc != NULL, "out of memory\n");
mtc->criticalExtensions.present = NR_MeasurementTimingConfiguration__criticalExtensions_PR_c1;
mtc->criticalExtensions.choice.c1 = calloc(1, sizeof(*mtc->criticalExtensions.choice.c1));
AssertFatal(mtc->criticalExtensions.choice.c1 != NULL, "out of memory\n");
mtc->criticalExtensions.choice.c1->present = NR_MeasurementTimingConfiguration__criticalExtensions__c1_PR_measTimingConf;
NR_MeasurementTimingConfiguration_IEs_t *mtc_ie = calloc(1, sizeof(*mtc_ie));
AssertFatal(mtc_ie != NULL, "out of memory\n");
mtc->criticalExtensions.choice.c1->choice.measTimingConf = mtc_ie;
mtc_ie->measTiming = calloc(1, sizeof(*mtc_ie->measTiming));
AssertFatal(mtc_ie->measTiming != NULL, "out of memory\n");
asn1cSequenceAdd(mtc_ie->measTiming->list, NR_MeasTiming_t, mt);
AssertFatal(mt != NULL, "out of memory\n");
mt->frequencyAndTiming = calloc(1, sizeof(*mt->frequencyAndTiming));
AssertFatal(mt->frequencyAndTiming != NULL, "out of memory\n");
mt->frequencyAndTiming->carrierFreq = *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB;
mt->frequencyAndTiming->ssbSubcarrierSpacing = *scc->ssbSubcarrierSpacing;
NR_SSB_MTC_t *ssb_mtc = &mt->frequencyAndTiming->ssb_MeasurementTimingConfiguration;
ssb_mtc->duration = NR_SSB_MTC__duration_sf1;
ssb_mtc->periodicityAndOffset = get_SSB_MTC_periodicityAndOffset(*scc->ssb_periodicityServingCell);
return mtc;
}
int encode_MeasurementTimingConfiguration(const struct NR_MeasurementTimingConfiguration *mtc, uint8_t *buf, int buf_len)
{
DevAssert(mtc != NULL);
xer_fprint(stdout, &asn_DEF_NR_MeasurementTimingConfiguration, mtc);
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MeasurementTimingConfiguration, NULL, mtc, buf, buf_len);
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
return (enc_rval.encoded + 7) / 8;
}
void free_MeasurementTimingConfiguration(NR_MeasurementTimingConfiguration_t *mtc)
{
ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc);
}
NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, const f1ap_plmn_t *plmn, uint64_t cellID, int tac)
{
AssertFatal(cellID < (1l << 36), "cellID must fit within 36 bits, but is %lu\n", cellID);
......
......@@ -57,6 +57,10 @@ void free_MIB_NR(NR_BCCH_BCH_Message_t *mib);
int encode_MIB_NR(NR_BCCH_BCH_Message_t *mib, int frame, uint8_t *buf, int buf_size);
int encode_MIB_NR_setup(NR_MIB_t *mib, int frame, uint8_t *buf, int buf_size);
struct NR_MeasurementTimingConfiguration;
struct NR_MeasurementTimingConfiguration *get_new_MeasurementTimingConfiguration(const NR_ServingCellConfigCommon_t *scc);
int encode_MeasurementTimingConfiguration(const struct NR_MeasurementTimingConfiguration *mtc, uint8_t *buf, int buf_len);
void free_MeasurementTimingConfiguration(struct NR_MeasurementTimingConfiguration *mtc);
#define NR_MAX_SIB_LENGTH 2976 // 3GPP TS 38.331 section 5.2.1
NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, const f1ap_plmn_t *plmn, uint64_t cellID, int tac);
......
......@@ -62,6 +62,7 @@
#include "NR_CellGroupConfig.h"
#include "NR_ServingCellConfigCommon.h"
#include "NR_EstablishmentCause.h"
#include "NR_MeasurementTimingConfiguration.h"
//-------------------
......@@ -382,6 +383,7 @@ typedef struct nr_rrc_du_container_t {
f1ap_setup_req_t *setup_req;
NR_MIB_t *mib;
NR_SIB1_t *sib1;
NR_MeasurementTimingConfiguration_t *mtc;
} nr_rrc_du_container_t;
typedef struct nr_rrc_cuup_container_t {
......
......@@ -80,6 +80,30 @@ static bool extract_sys_info(const f1ap_gnb_du_system_info_t *sys_info, NR_MIB_t
return true;
}
static NR_MeasurementTimingConfiguration_t *extract_mtc(uint8_t *buf, int buf_len)
{
NR_MeasurementTimingConfiguration_t *mtc = NULL;
asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_MeasurementTimingConfiguration, (void **)&mtc, buf, buf_len);
if (dec_rval.code != RC_OK) {
ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc);
return NULL;
}
/* verify that it has the format we need */
if (mtc->criticalExtensions.present != NR_MeasurementTimingConfiguration__criticalExtensions_PR_c1
|| mtc->criticalExtensions.choice.c1 == NULL
|| mtc->criticalExtensions.choice.c1->present != NR_MeasurementTimingConfiguration__criticalExtensions__c1_PR_measTimingConf
|| mtc->criticalExtensions.choice.c1->choice.measTimingConf == NULL
|| mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming == NULL
|| mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming->list.count == 0) {
LOG_E(RRC, "error: measurementTimingConfiguration does not have expected format (at least one measTiming entry\n");
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_MeasurementTimingConfiguration, mtc);
ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc);
return NULL;
}
return mtc;
}
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");
......@@ -142,6 +166,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 (!mtc) {
LOG_W(RRC, "cannot decode MeasurementTimingConfiguration of DU ID %ld, rejecting\n", req->gNB_DU_id);
f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error};
rrc->mac_rrc.f1_setup_failure(assoc_id, &fail);
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;
......@@ -151,6 +184,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
LOG_W(RRC, "rejecting DU ID %ld\n", req->gNB_DU_id);
f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error};
rrc->mac_rrc.f1_setup_failure(assoc_id, &fail);
ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc);
return;
}
}
......@@ -171,6 +205,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
// MIB can be null and configured later via DU Configuration Update
du->mib = mib;
du->sib1 = sib1;
du->mtc = mtc;
RB_INSERT(rrc_du_tree, &rrc->dus, du);
rrc->num_dus++;
......@@ -234,6 +269,16 @@ static void update_cell_info(nr_rrc_du_container_t *du, const f1ap_served_cell_i
ci->tdd = new_ci->tdd;
else
ci->fdd = new_ci->fdd;
NR_MeasurementTimingConfiguration_t *new_mtc =
extract_mtc(new_ci->measurement_timing_config, new_ci->measurement_timing_config_len);
if (new_mtc != NULL) {
ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, du->mtc);
du->mtc = new_mtc;
} else {
LOG_E(RRC, "error decoding MeasurementTimingConfiguration during cell update, ignoring new config\n");
ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, new_mtc);
}
}
void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update_t *conf_up, sctp_assoc_t assoc_id)
......@@ -321,6 +366,7 @@ void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t
LOG_I(RRC, "releasing DU ID %ld (%s) on assoc_id %d\n", req->gNB_DU_id, req->gNB_DU_name, assoc_id);
ASN_STRUCT_FREE(asn_DEF_NR_MIB, du->mib);
ASN_STRUCT_FREE(asn_DEF_NR_SIB1, du->sib1);
ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, du->mtc);
/* TODO: free setup request */
nr_rrc_du_container_t *removed = RB_REMOVE(rrc_du_tree, &rrc->dus, du);
DevAssert(removed != NULL);
......
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