Merge remote-tracking branch 'origin/nr-minor-cleanup-gnb' into integration_2024_w45 (!3048)
The goal of this MR is to improve readability, maintainability and consistency of gNB initialization functions. This MR is: - cleaning up redundant and unused code - refactoring init_gNB, l1_north_init_gNB, RCconfig_NR_L1, NRRCConfig - removing redundant memory allocation for gNB RAN context and L1 instances - cleaning up redundant log lines
This commit is contained in:
@@ -131,7 +131,7 @@ static struct {
|
||||
extern double cpuf;
|
||||
|
||||
|
||||
void init_eNB(int);
|
||||
void init_eNB();
|
||||
void stop_eNB(int nb_inst);
|
||||
|
||||
int wakeup_tx(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, int frame_tx, int subframe_tx, uint64_t timestamp_tx);
|
||||
@@ -1219,7 +1219,8 @@ void init_eNB_afterRU(void) {
|
||||
}
|
||||
|
||||
|
||||
void init_eNB(int wait_for_sync) {
|
||||
void init_eNB()
|
||||
{
|
||||
int CC_id;
|
||||
int inst;
|
||||
PHY_VARS_eNB *eNB;
|
||||
|
||||
@@ -532,8 +532,8 @@ int main ( int argc, char **argv )
|
||||
printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
|
||||
|
||||
if (RC.nb_L1_inst > 0) {
|
||||
printf("Initializing eNB threads wait_for_sync:%d\n", get_softmodem_params()->wait_for_sync);
|
||||
init_eNB(get_softmodem_params()->wait_for_sync);
|
||||
printf("Initializing eNB threads\n");
|
||||
init_eNB();
|
||||
}
|
||||
for (int x=0; x < RC.nb_L1_inst; x++)
|
||||
for (int CC_id=0; CC_id<RC.nb_L1_CC[x]; CC_id++) {
|
||||
|
||||
@@ -138,7 +138,7 @@ extern int usrp_tx_thread;
|
||||
// In lte-enb.c
|
||||
extern void stop_eNB(int);
|
||||
extern void kill_eNB_proc(int inst);
|
||||
extern void init_eNB(int wait_for_sync);
|
||||
extern void init_eNB();
|
||||
|
||||
// In lte-ru.c
|
||||
extern void stop_ru(RU_t *ru);
|
||||
|
||||
+26
-30
@@ -400,13 +400,8 @@ void term_gNB_Tpool(int inst) {
|
||||
void init_eNB_afterRU(void) {
|
||||
int inst,ru_id,i,aa;
|
||||
PHY_VARS_gNB *gNB;
|
||||
LOG_D(PHY, "%s() RC.nb_nr_inst:%d\n", __FUNCTION__, RC.nb_nr_inst);
|
||||
|
||||
if(NFAPI_MODE == NFAPI_MODE_PNF)
|
||||
RC.nb_nr_inst = 1;
|
||||
for (inst=0; inst<RC.nb_nr_inst; inst++) {
|
||||
LOG_D(PHY, "RC.nb_nr_CC[inst:%d]:%p\n", inst, RC.gNB[inst]);
|
||||
|
||||
gNB = RC.gNB[inst];
|
||||
gNB->ldpc_offload_flag = get_softmodem_params()->ldpc_offload_flag;
|
||||
|
||||
@@ -415,7 +410,7 @@ void init_eNB_afterRU(void) {
|
||||
// map antennas and PRACH signals to gNB RX
|
||||
if (0) AssertFatal(gNB->num_RU>0,"Number of RU attached to gNB %d is zero\n",gNB->Mod_id);
|
||||
|
||||
LOG_D(PHY, "Mapping RX ports from %d RUs to gNB %d\n", gNB->num_RU, gNB->Mod_id);
|
||||
LOG_D(NR_PHY, "Mapping RX ports from %d RUs to gNB %d\n", gNB->num_RU, gNB->Mod_id);
|
||||
|
||||
for (ru_id=0,aa=0; ru_id<gNB->num_RU; ru_id++) {
|
||||
AssertFatal(gNB->RU_list[ru_id]->common.rxdataF != NULL, "RU %d : common.rxdataF is NULL\n", gNB->RU_list[ru_id]->idx);
|
||||
@@ -439,39 +434,41 @@ void init_eNB_afterRU(void) {
|
||||
|
||||
}
|
||||
|
||||
void init_gNB(int wait_for_sync) {
|
||||
|
||||
int inst;
|
||||
PHY_VARS_gNB *gNB;
|
||||
|
||||
/**
|
||||
* @brief Initialize gNB struct in RAN context
|
||||
*/
|
||||
void init_gNB()
|
||||
{
|
||||
LOG_I(NR_PHY, "Initializing gNB RAN context: RC.nb_nr_L1_inst = %d \n", RC.nb_nr_L1_inst);
|
||||
if (RC.gNB == NULL) {
|
||||
RC.gNB = (PHY_VARS_gNB **) calloc(1+RC.nb_nr_L1_inst, sizeof(PHY_VARS_gNB *));
|
||||
LOG_D(PHY, "gNB L1 structure RC.gNB allocated @ %p\n", RC.gNB);
|
||||
RC.gNB = (PHY_VARS_gNB **)calloc_or_fail(RC.nb_nr_L1_inst, sizeof(PHY_VARS_gNB *));
|
||||
LOG_D(NR_PHY, "gNB L1 structure RC.gNB allocated @ %p\n", RC.gNB);
|
||||
}
|
||||
|
||||
for (inst=0; inst<RC.nb_nr_L1_inst; inst++) {
|
||||
|
||||
for (int inst = 0; inst < RC.nb_nr_L1_inst; inst++) {
|
||||
// Allocate L1 instance
|
||||
if (RC.gNB[inst] == NULL) {
|
||||
RC.gNB[inst] = (PHY_VARS_gNB *) calloc(1, sizeof(PHY_VARS_gNB));
|
||||
LOG_D(PHY, "[nr-gnb.c] gNB structure RC.gNB[%d] allocated @ %p\n", inst, RC.gNB[inst]);
|
||||
RC.gNB[inst] = (PHY_VARS_gNB *)calloc_or_fail(1, sizeof(PHY_VARS_gNB));
|
||||
LOG_D(NR_PHY, "[nr-gnb.c] gNB structure RC.gNB[%d] allocated @ %p\n", inst, RC.gNB[inst]);
|
||||
}
|
||||
gNB = RC.gNB[inst];
|
||||
/*nr_polar_init(&gNB->nrPolar_params,
|
||||
NR_POLAR_PBCH_MESSAGE_TYPE,
|
||||
NR_POLAR_PBCH_PAYLOAD_BITS,
|
||||
NR_POLAR_PBCH_AGGREGATION_LEVEL);*/
|
||||
PHY_VARS_gNB *gNB = RC.gNB[inst];
|
||||
LOG_D(NR_PHY, "Initializing gNB %d\n", inst);
|
||||
|
||||
// Init module ID
|
||||
gNB->Mod_id = inst;
|
||||
|
||||
// Register MAC interface module
|
||||
AssertFatal((gNB->if_inst = NR_IF_Module_init(inst)) != NULL, "Cannot register interface");
|
||||
gNB->if_inst->NR_Schedule_response = nr_schedule_response;
|
||||
gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
memset(&gNB->UL_INFO, 0, sizeof(gNB->UL_INFO));
|
||||
LOG_I(NR_PHY, "Registered with MAC interface module (%p)\n", gNB->if_inst);
|
||||
|
||||
// Set function pointers in MAC IF module
|
||||
gNB->if_inst->NR_Schedule_response = nr_schedule_response;
|
||||
gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
|
||||
// Clear UL_INFO and set rx/crc indication lists
|
||||
memset((void *)&gNB->UL_INFO, 0, sizeof(gNB->UL_INFO));
|
||||
gNB->UL_INFO.rx_ind.pdu_list = gNB->rx_pdu_list;
|
||||
gNB->UL_INFO.crc_ind.crc_list = gNB->crc_pdu_list;
|
||||
/*gNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = gNB->sr_pdu_list;
|
||||
gNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = gNB->harq_pdu_list;
|
||||
gNB->UL_INFO.cqi_ind.cqi_pdu_list = gNB->cqi_pdu_list;
|
||||
gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;*/
|
||||
|
||||
gNB->prach_energy_counter = 0;
|
||||
gNB->chest_time = get_softmodem_params()->chest_time;
|
||||
@@ -479,7 +476,6 @@ void init_gNB(int wait_for_sync) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void stop_gNB(int nb_inst) {
|
||||
for (int inst=0; inst<nb_inst; inst++) {
|
||||
LOG_I(PHY,"Killing gNB %d processing threads\n",inst);
|
||||
|
||||
+1
-1
@@ -1819,7 +1819,7 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg)
|
||||
|
||||
if (RUParamList.numelt > 0) {
|
||||
RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *));
|
||||
RC.ru_mask = (1 << NB_RU) - 1;
|
||||
RC.ru_mask = (1 << RC.nb_RU) - 1;
|
||||
|
||||
for (int j = 0; j < RC.nb_RU; j++) {
|
||||
RC.ru[j] = calloc(1, sizeof(*RC.ru[j]));
|
||||
|
||||
+16
-111
@@ -92,28 +92,17 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
pthread_cond_t nfapi_sync_cond;
|
||||
pthread_mutex_t nfapi_sync_mutex;
|
||||
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
|
||||
|
||||
extern uint8_t nfapi_mode; // Default to monolithic mode
|
||||
THREAD_STRUCT thread_struct;
|
||||
pthread_cond_t sync_cond;
|
||||
pthread_mutex_t sync_mutex;
|
||||
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
|
||||
int config_sync_var=-1;
|
||||
|
||||
volatile int start_gNB = 0;
|
||||
int oai_exit = 0;
|
||||
|
||||
int NB_UE_INST = 0;
|
||||
|
||||
static int wait_for_sync = 0;
|
||||
|
||||
unsigned int mmapped_dma=0;
|
||||
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
|
||||
//Temp fix for inexistent NR upper layer
|
||||
unsigned char NB_gNB_INST = 1;
|
||||
char *uecap_file;
|
||||
|
||||
runmode_t mode = normal_txrx;
|
||||
@@ -131,26 +120,10 @@ double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
|
||||
double rx_gain_off = 0.0;
|
||||
|
||||
static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/;
|
||||
|
||||
|
||||
int chain_offset=0;
|
||||
|
||||
uint8_t dci_Format = 0;
|
||||
uint8_t nb_antenna_tx = 1;
|
||||
uint8_t nb_antenna_rx = 1;
|
||||
|
||||
int otg_enabled;
|
||||
|
||||
extern void *udp_eNB_task(void *args_p);
|
||||
|
||||
int transmission_mode=1;
|
||||
int emulate_rf = 0;
|
||||
int numerology = 0;
|
||||
|
||||
|
||||
/* struct for ethernet specific parameters given in eNB conf file */
|
||||
eth_params_t *eth_params;
|
||||
|
||||
double cpuf;
|
||||
|
||||
/* hack: pdcp_run() is required by 4G scheduler which is compiled into
|
||||
@@ -160,9 +133,6 @@ void pdcp_run(const protocol_ctxt_t *const ctxt_pP)
|
||||
abort();
|
||||
}
|
||||
|
||||
/* forward declarations */
|
||||
void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs], NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
|
||||
|
||||
/*---------------------BMC: timespec helpers -----------------------------*/
|
||||
|
||||
struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
|
||||
@@ -273,33 +243,20 @@ static int create_gNB_tasks(ngran_node_t node_type, configmodule_interface_t *cf
|
||||
|
||||
RCconfig_verify(cfg, node_type);
|
||||
|
||||
if(NFAPI_MODE != NFAPI_MODE_AERIAL){
|
||||
RCconfig_nr_prs();
|
||||
}
|
||||
|
||||
if (RC.nb_nr_macrlc_inst > 0)
|
||||
RCconfig_nr_macrlc(cfg);
|
||||
|
||||
LOG_D(PHY, "%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst);
|
||||
|
||||
if (RC.nb_nr_L1_inst>0) AssertFatal(l1_north_init_gNB()==0,"could not initialize L1 north interface\n");
|
||||
|
||||
AssertFatal (gnb_nb <= RC.nb_nr_inst,
|
||||
"Number of gNB is greater than gNB defined in configuration file (%d/%d)!",
|
||||
gnb_nb, RC.nb_nr_inst);
|
||||
|
||||
LOG_D(GNB_APP, "Allocating gNB_RRC_INST for %d instances\n", RC.nb_nr_inst);
|
||||
LOG_D(GNB_APP, "Allocating gNB_RRC_INST\n");
|
||||
RC.nrrrc = calloc(1, sizeof(*RC.nrrrc));
|
||||
RC.nrrrc[0] = RCconfig_NRRRC();
|
||||
|
||||
if (RC.nb_nr_inst > 0) {
|
||||
AssertFatal(RC.nb_nr_inst == 1, "multiple RRC instances are not supported\n");
|
||||
RC.nrrrc = calloc(1, sizeof(*RC.nrrrc));
|
||||
RC.nrrrc[0] = calloc(1,sizeof(gNB_RRC_INST));
|
||||
RCconfig_NRRRC(RC.nrrrc[0]);
|
||||
}
|
||||
|
||||
if (RC.nb_nr_inst > 0 &&
|
||||
!get_softmodem_params()->nsa &&
|
||||
!(node_type == ngran_gNB_DU)) {
|
||||
if (!get_softmodem_params()->nsa && !(node_type == ngran_gNB_DU)) {
|
||||
// we start pdcp in both cuup (for drb) and cucp (for srb)
|
||||
init_pdcp();
|
||||
}
|
||||
@@ -401,65 +358,6 @@ static void get_options(configmodule_interface_t *cfg)
|
||||
get_common_options(cfg, SOFTMODEM_GNB_BIT);
|
||||
config_process_cmdline(cfg, cmdline_params, sizeofArray(cmdline_params), NULL);
|
||||
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
|
||||
|
||||
if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
|
||||
memset((void *)&RC,0,sizeof(RC));
|
||||
/* Read RC configuration file */
|
||||
NRRCConfig();
|
||||
NB_gNB_INST = RC.nb_nr_inst;
|
||||
NB_RU = RC.nb_RU;
|
||||
}
|
||||
}
|
||||
|
||||
void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs],
|
||||
NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
|
||||
for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
frame_parms[CC_id] = (NR_DL_FRAME_PARMS *) malloc(sizeof(NR_DL_FRAME_PARMS));
|
||||
config[CC_id] = (nfapi_nr_config_request_scf_t *) malloc(sizeof(nfapi_nr_config_request_scf_t));
|
||||
config[CC_id]->ssb_config.scs_common.value = 1;
|
||||
config[CC_id]->cell_config.frame_duplex_type.value = 1; //FDD
|
||||
//config[CC_id]->subframe_config.dl_cyclic_prefix_type.value = 0; //NORMAL
|
||||
config[CC_id]->carrier_config.dl_grid_size[1].value = 106;
|
||||
config[CC_id]->carrier_config.ul_grid_size[1].value = 106;
|
||||
config[CC_id]->cell_config.phy_cell_id.value = 0;
|
||||
///dl frequency to be filled in
|
||||
/* //Set some default values that may be overwritten while reading options
|
||||
frame_parms[CC_id]->frame_type = FDD;
|
||||
frame_parms[CC_id]->tdd_config = 3;
|
||||
frame_parms[CC_id]->tdd_config_S = 0;
|
||||
frame_parms[CC_id]->N_RB_DL = 100;
|
||||
frame_parms[CC_id]->N_RB_UL = 100;
|
||||
frame_parms[CC_id]->Ncp = NORMAL;
|
||||
frame_parms[CC_id]->Ncp_UL = NORMAL;
|
||||
frame_parms[CC_id]->Nid_cell = 0;
|
||||
frame_parms[CC_id]->num_MBSFN_config = 0;
|
||||
frame_parms[CC_id]->nb_antenna_ports_gNB = 1;
|
||||
frame_parms[CC_id]->nb_antennas_tx = 1;
|
||||
frame_parms[CC_id]->nb_antennas_rx = 1;
|
||||
|
||||
frame_parms[CC_id]->nushift = 0;
|
||||
|
||||
frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth;
|
||||
frame_parms[CC_id]->phich_config_common.phich_duration = normal;
|
||||
// UL RS Config
|
||||
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0
|
||||
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0;
|
||||
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0;
|
||||
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
|
||||
|
||||
frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
|
||||
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
|
||||
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
|
||||
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
|
||||
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;
|
||||
|
||||
// downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31.
|
||||
// downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
|
||||
// downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
|
||||
// downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
|
||||
frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
void wait_RUs(void) {
|
||||
@@ -596,6 +494,7 @@ int main( int argc, char **argv ) {
|
||||
lock_memory_to_ram();
|
||||
get_options(uniqCfg);
|
||||
|
||||
|
||||
EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
|
||||
|
||||
if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
|
||||
@@ -630,9 +529,19 @@ int main( int argc, char **argv ) {
|
||||
|
||||
// don't create if node doesn't connect to RRC/S1/GTP
|
||||
const ngran_node_t node_type = get_node_type();
|
||||
// Init RAN context
|
||||
if (!(CONFIG_ISFLAGSET(CONFIG_ABORT)))
|
||||
NRRCConfig();
|
||||
|
||||
if (RC.nb_nr_L1_inst > 0)
|
||||
if (RC.nb_nr_L1_inst > 0) {
|
||||
// Initialize gNB structure in RAN context
|
||||
init_gNB();
|
||||
// Initialize L1
|
||||
RCconfig_NR_L1();
|
||||
// Initialize Positioning Reference Signal configuration
|
||||
if(NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_AERIAL)
|
||||
RCconfig_nr_prs();
|
||||
}
|
||||
|
||||
if (NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
int ret = create_gNB_tasks(node_type, uniqCfg);
|
||||
@@ -651,10 +560,6 @@ int main( int argc, char **argv ) {
|
||||
// start the main threads
|
||||
number_of_cards = 1;
|
||||
|
||||
if (RC.nb_nr_L1_inst > 0) {
|
||||
init_gNB(wait_for_sync);
|
||||
}
|
||||
|
||||
wait_gNBs();
|
||||
int sl_ahead = NFAPI_MODE == NFAPI_MODE_AERIAL ? 0 : 6;
|
||||
if (RC.nb_RU >0) {
|
||||
|
||||
@@ -41,7 +41,7 @@ extern uint64_t ulsch_slot_bitmap;
|
||||
extern char *uecap_file;
|
||||
|
||||
// In nr-gnb.c
|
||||
extern void init_gNB(int wait_for_sync);
|
||||
extern void init_gNB();
|
||||
extern void stop_gNB(int);
|
||||
|
||||
// In nr-ru.c
|
||||
|
||||
@@ -125,7 +125,6 @@ extern "C"
|
||||
#define DO_RA softmodem_params.do_ra
|
||||
#define SA softmodem_params.sa
|
||||
#define SL_MODE softmodem_params.sl_mode
|
||||
#define WAIT_FOR_SYNC softmodem_params.wait_for_sync
|
||||
#define CHAIN_OFFSET softmodem_params.chain_offset
|
||||
#define NUMEROLOGY softmodem_params.numerology
|
||||
#define BAND softmodem_params.band
|
||||
@@ -161,7 +160,6 @@ extern int usrp_tx_thread;
|
||||
{"clock-source", CONFIG_HLP_CLK, 0, .uptr=&CLOCK_SOURCE, .defintval=0, TYPE_UINT, 0}, \
|
||||
{"time-source", CONFIG_HLP_TME, 0, .uptr=&TIMING_SOURCE, .defintval=0, TYPE_UINT, 0}, \
|
||||
{"tune-offset", CONFIG_HLP_TUNE_OFFSET, 0, .dblptr=&TUNE_OFFSET, .defintval=0, TYPE_DOUBLE, 0}, \
|
||||
{"wait-for-sync", NULL, PARAMFLAG_BOOL, .iptr=&WAIT_FOR_SYNC, .defintval=0, TYPE_INT, 0}, \
|
||||
{"C" , CONFIG_HLP_DLF, 0, .u64ptr=&(downlink_frequency[0][0]), .defuintval=0, TYPE_UINT64, 0}, \
|
||||
{"CO" , CONFIG_HLP_ULF, 0, .iptr=&(uplink_frequency_offset[0][0]), .defintval=0, TYPE_INT, 0}, \
|
||||
{"a" , CONFIG_HLP_CHOFF, 0, .iptr=&CHAIN_OFFSET, .defintval=0, TYPE_INT, 0}, \
|
||||
@@ -224,7 +222,6 @@ extern int usrp_tx_thread;
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s3a = { config_checkstr_assign_integer, \
|
||||
{"MONOLITHIC", "PNF", "VNF", "AERIAL","UE_STUB_PNF","UE_STUB_OFFNET","STANDALONE_PNF"}, \
|
||||
{NFAPI_MONOLITHIC, NFAPI_MODE_PNF, NFAPI_MODE_VNF, NFAPI_MODE_AERIAL,NFAPI_UE_STUB_PNF,NFAPI_UE_STUB_OFFNET,NFAPI_MODE_STANDALONE_PNF}, \
|
||||
@@ -309,7 +306,6 @@ typedef struct {
|
||||
uint8_t sl_mode;
|
||||
uint8_t usim_test;
|
||||
int emulate_rf;
|
||||
int wait_for_sync; //eNodeB only
|
||||
int chain_offset;
|
||||
int numerology;
|
||||
int band;
|
||||
|
||||
+13
-26
@@ -41,28 +41,24 @@
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
|
||||
|
||||
int l1_north_init_gNB() {
|
||||
int l1_north_init_gNB()
|
||||
{
|
||||
AssertFatal(RC.nb_nr_L1_inst > 0, "Failed to init PHY callbacks: nb_nr_L1_inst = %d\n", RC.nb_nr_L1_inst);
|
||||
AssertFatal(RC.gNB != NULL, "Failed to init PHY callbacks: RC.gNB is null\n");
|
||||
|
||||
if (RC.nb_nr_L1_inst > 0 && RC.gNB != NULL) {
|
||||
for (uint8_t i = 0; i < RC.nb_nr_L1_inst; i++) {
|
||||
|
||||
AssertFatal(RC.nb_nr_L1_inst>0,"nb_nr_L1_inst=%d\n",RC.nb_nr_L1_inst);
|
||||
AssertFatal(RC.gNB!=NULL,"RC.gNB is null\n");
|
||||
LOG_D(PHY, "%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst);
|
||||
|
||||
for (int i=0; i<RC.nb_nr_L1_inst; i++) {
|
||||
AssertFatal(RC.gNB[i]!=NULL,"RC.gNB[%d] is null\n",i);
|
||||
|
||||
if ((RC.gNB[i]->if_inst = NR_IF_Module_init(i))<0) return(-1);
|
||||
|
||||
LOG_D(PHY, "%s() RC.gNB[%d] installing callbacks\n", __FUNCTION__, i);
|
||||
RC.gNB[i]->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
RC.gNB[i]->if_inst->NR_Schedule_response = nr_schedule_response;
|
||||
if ((RC.gNB[i]->if_inst = NR_IF_Module_init(i)) < 0) {
|
||||
LOG_E(NR_PHY, "Error: Failed to initialize NR_IF_Module for gNB[%d]\n", i);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
LOG_D(PHY, "%s() Not installing PHY callbacks - RC.nb_nr_L1_inst:%d RC.gNB:%p\n", __FUNCTION__, RC.nb_nr_L1_inst, RC.gNB);
|
||||
|
||||
LOG_D(NR_PHY, "RC.gNB[%d]: installing callbacks\n", i);
|
||||
RC.gNB[i]->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
RC.gNB[i]->if_inst->NR_Schedule_response = nr_schedule_response;
|
||||
}
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NR_gNB_PHY_STATS_t *get_phy_stats(PHY_VARS_gNB *gNB, uint16_t rnti)
|
||||
@@ -312,15 +308,6 @@ void install_nr_schedule_handlers(NR_IF_Module_t *if_inst)
|
||||
if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
if_inst->NR_Schedule_response = nr_schedule_response;
|
||||
}
|
||||
/*
|
||||
void install_schedule_handlers(IF_Module_t *if_inst)
|
||||
{
|
||||
if_inst->PHY_config_req = phy_config_request;
|
||||
if_inst->schedule_response = schedule_response;
|
||||
}*/
|
||||
|
||||
/// this function is a temporary addition for NR configuration
|
||||
|
||||
|
||||
void nr_phy_config_request_sim(PHY_VARS_gNB *gNB,
|
||||
int N_RB_DL,
|
||||
|
||||
@@ -42,42 +42,6 @@ c16_t nr_ru[839]; // quantized roots of unity
|
||||
static uint32_t nr_ZC_inv[839]; // multiplicative inverse for roots u
|
||||
uint16_t nr_du[838];
|
||||
|
||||
/*void dump_nr_prach_config(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe) {
|
||||
|
||||
FILE *fd;
|
||||
|
||||
fd = fopen("prach_config.txt","w");
|
||||
fprintf(fd,"prach_config: subframe = %d\n",subframe);
|
||||
fprintf(fd,"prach_config: N_RB_UL = %d\n",frame_parms->N_RB_UL);
|
||||
fprintf(fd,"prach_config: frame_type = %s\n",(frame_parms->frame_type==1) ? "TDD":"FDD");
|
||||
|
||||
if (frame_parms->frame_type==TDD) {
|
||||
fprintf(fd,"prach_config: p_tdd_UL_DL_Configuration.referenceSCS = %d\n",frame_parms->p_tdd_UL_DL_Configuration->referenceSubcarrierSpacing);
|
||||
fprintf(fd,"prach_config: p_tdd_UL_DL_Configuration.dl_UL_TransmissionPeriodicity = %d\n",frame_parms->p_tdd_UL_DL_Configuration->dl_UL_TransmissionPeriodicity);
|
||||
fprintf(fd,"prach_config: p_tdd_UL_DL_Configuration.nrofDownlinkSlots = %d\n",frame_parms->p_tdd_UL_DL_Configuration->nrofDownlinkSlots);
|
||||
fprintf(fd,"prach_config: p_tdd_UL_DL_Configuration.nrofDownlinkSymbols = %d\n",frame_parms->p_tdd_UL_DL_Configuration->nrofDownlinkSymbols);
|
||||
fprintf(fd,"prach_config: p_tdd_UL_DL_Configuration.nrofUownlinkSlots = %d\n",frame_parms->p_tdd_UL_DL_Configuration->nrofDownlinkSlots);
|
||||
fprintf(fd,"prach_config: p_tdd_UL_DL_Configuration.nrofUownlinkSymbols = %d\n",frame_parms->p_tdd_UL_DL_Configuration->nrofDownlinkSymbols);
|
||||
if (frame_parms->p_tdd_UL_DL_Configuration->p_next) {
|
||||
fprintf(fd,"prach_config: p_tdd_UL_DL_Configuration.referenceSCS2 = %d\n",frame_parms->p_tdd_UL_DL_Configuration->p_next->referenceSubcarrierSpacing);
|
||||
fprintf(fd,"prach_config: p_tdd_UL_DL_Configuration.dl_UL_TransmissionPeriodicity2 = %d\n",frame_parms->p_tdd_UL_DL_Configuration->p_next->dl_UL_TransmissionPeriodicity);
|
||||
fprintf(fd,"prach_config: p_tdd_UL_DL_Configuration.nrofDownlinkSlots2 = %d\n",frame_parms->p_tdd_UL_DL_Configuration->p_next->nrofDownlinkSlots);
|
||||
fprintf(fd,"prach_config: p_tdd_UL_DL_Configuration.nrofDownlinkSymbols2 = %d\n",frame_parms->p_tdd_UL_DL_Configuration->p_next->nrofDownlinkSymbols);
|
||||
fprintf(fd,"prach_config: p_tdd_UL_DL_Configuration.nrofUownlinkSlots2 = %d\n",frame_parms->p_tdd_UL_DL_Configuration->p_next->nrofDownlinkSlots);
|
||||
fprintf(fd,"prach_config: p_tdd_UL_DL_Configuration.nrofUownlinkSymbols2 = %d\n",frame_parms->p_tdd_UL_DL_Configuration->p_next->nrofDownlinkSymbols);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(fd,"prach_config: rootSequenceIndex = %d\n",frame_parms->prach_config_common.rootSequenceIndex);
|
||||
fprintf(fd,"prach_config: prach_ConfigIndex = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex);
|
||||
fprintf(fd,"prach_config: Ncs_config = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig);
|
||||
fprintf(fd,"prach_config: highSpeedFlag = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag);
|
||||
fprintf(fd,"prach_config: n_ra_prboffset = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.msg1_frequencystart);
|
||||
fclose(fd);
|
||||
|
||||
}*/
|
||||
|
||||
// This function computes the du
|
||||
void nr_fill_du(uint16_t N_ZC, const uint16_t *prach_root_sequence_map)
|
||||
{
|
||||
|
||||
@@ -514,7 +514,7 @@ typedef struct PHY_VARS_gNB_s {
|
||||
int srs_thres;
|
||||
uint64_t bad_pucch;
|
||||
int num_ulprbbl;
|
||||
int ulprbbl[275];
|
||||
uint16_t ulprbbl [MAX_BWP_SIZE];
|
||||
|
||||
time_stats_t phy_proc_tx;
|
||||
time_stats_t phy_proc_rx;
|
||||
|
||||
@@ -63,9 +63,6 @@ static const short primary_synch2[144] = {
|
||||
-13477, 29867, -7292, -31946, -29523, -14218, 25100, -21063, -16384, -28378, 27073, -18459, -26120, -19785, 2448, -32676,
|
||||
-24020, 22287, -31754, 8085, 32767, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
extern unsigned char NB_RU;
|
||||
|
||||
|
||||
static const char NB_functions[7][20] = {
|
||||
"eNodeB_3GPP",
|
||||
"eNodeB_3GPP_BBU",
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
PHY_VARS_UE ***PHY_vars_UE_g;
|
||||
UL_RCC_IND_t UL_RCC_INFO;
|
||||
unsigned char NB_RU=0;
|
||||
int number_of_cards;
|
||||
uint8_t max_turbo_iterations=4;
|
||||
|
||||
|
||||
@@ -662,9 +662,6 @@ int main(int argc, char **argv){
|
||||
LOG_M("txsig0_frame.m","txs0", txdata[0],frame_parms->samples_per_frame,1,1);
|
||||
#endif
|
||||
|
||||
// multipath channel
|
||||
// dump_nr_prach_config(&gNB->frame_parms,subframe);
|
||||
|
||||
for (i = 0; i < frame_parms->samples_per_subframe; i++) {
|
||||
for (aa=0; aa<1; aa++) {
|
||||
if (awgn_flag == 0) {
|
||||
|
||||
@@ -54,8 +54,6 @@
|
||||
#include "gnb_config.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
|
||||
extern unsigned char NB_gNB_INST;
|
||||
|
||||
extern RAN_CONTEXT_t RC;
|
||||
|
||||
#define GNB_REGISTER_RETRY_DELAY 10
|
||||
|
||||
+183
-177
@@ -746,25 +746,15 @@ void RCconfig_nr_prs(void)
|
||||
prs_config_t *prs_config = NULL;
|
||||
char str[7][100] = {0};
|
||||
|
||||
AssertFatal(RC.gNB != NULL, "gNB context is null, cannot complete PRS configuration\n");
|
||||
|
||||
paramdef_t PRS_Params[] = PRS_PARAMS_DESC;
|
||||
paramlist_def_t PRS_ParamList = {CONFIG_STRING_PRS_CONFIG,NULL,0};
|
||||
if (RC.gNB == NULL) {
|
||||
RC.gNB = (PHY_VARS_gNB **)malloc((1+NUMBER_OF_gNB_MAX)*sizeof(PHY_VARS_gNB*));
|
||||
LOG_I(NR_PHY,"RC.gNB = %p\n",RC.gNB);
|
||||
memset(RC.gNB,0,(1+NUMBER_OF_gNB_MAX)*sizeof(PHY_VARS_gNB*));
|
||||
}
|
||||
|
||||
config_getlist(config_get_if(), &PRS_ParamList, PRS_Params, sizeofArray(PRS_Params), NULL);
|
||||
|
||||
if (PRS_ParamList.numelt > 0) {
|
||||
for (j = 0; j < RC.nb_nr_L1_inst; j++) {
|
||||
|
||||
if (RC.gNB[j] == NULL) {
|
||||
RC.gNB[j] = (PHY_VARS_gNB *)malloc(sizeof(PHY_VARS_gNB));
|
||||
LOG_I(NR_PHY,"RC.gNB[%d] = %p\n",j,RC.gNB[j]);
|
||||
memset(RC.gNB[j],0,sizeof(PHY_VARS_gNB));
|
||||
RC.gNB[j]->Mod_id = j;
|
||||
}
|
||||
AssertFatal(RC.gNB[j] != NULL, "gNB L1 instance is null at index %d, cannot complete L1 configuration\n", j);
|
||||
|
||||
RC.gNB[j]->prs_vars.NumPRSResources = *(PRS_ParamList.paramarray[j][NUM_PRS_RESOURCES].uptr);
|
||||
for (k = 0; k < RC.gNB[j]->prs_vars.NumPRSResources; k++)
|
||||
@@ -834,135 +824,122 @@ void RCconfig_nr_prs(void)
|
||||
}
|
||||
}
|
||||
|
||||
#define ALL_SYMBOLS_TAKEN 0x3FFF
|
||||
|
||||
/**
|
||||
* @brief Get number or blacklisted UL PRBs and their mapping from gNB config
|
||||
*/
|
||||
static int get_prb_blacklist(uint8_t instance, uint16_t *prbbl)
|
||||
{
|
||||
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
||||
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0};
|
||||
config_get(config_get_if(), GNBSParams, sizeofArray(GNBSParams), NULL);
|
||||
int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
|
||||
AssertFatal(num_gnbs > 0, "Failed to parse config file, no GNBs found in field %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS);
|
||||
paramdef_t GNBParams[] = GNBPARAMS_DESC;
|
||||
config_getlist(config_get_if(), &GNBParamList, GNBParams, sizeofArray(GNBParams), NULL);
|
||||
|
||||
int num_prbbl = 0;
|
||||
char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr;
|
||||
|
||||
if (!ulprbbl)
|
||||
return -1;
|
||||
|
||||
LOG_D(NR_PHY, "PRB blacklist found: %s\n", ulprbbl);
|
||||
char *save = NULL;
|
||||
char *pt = strtok_r(ulprbbl, ",", &save);
|
||||
|
||||
while (pt) {
|
||||
const int rb = atoi(pt);
|
||||
AssertFatal(rb < MAX_BWP_SIZE, "RB %d out of bounds (max 275 PRBs)\n", rb);
|
||||
prbbl[rb] = ALL_SYMBOLS_TAKEN;
|
||||
LOG_D(NR_PHY, "Blacklisting prb %d\n", rb);
|
||||
pt = strtok_r(NULL, ",", &save);
|
||||
num_prbbl++;
|
||||
}
|
||||
return num_prbbl;
|
||||
}
|
||||
|
||||
void RCconfig_NR_L1(void)
|
||||
{
|
||||
int j = 0;
|
||||
if (RC.gNB == NULL) {
|
||||
RC.gNB = (PHY_VARS_gNB **)malloc((1 + NUMBER_OF_gNB_MAX) * sizeof(PHY_VARS_gNB *));
|
||||
LOG_I(NR_PHY, "RC.gNB = %p\n", RC.gNB);
|
||||
memset(RC.gNB, 0, (1 + NUMBER_OF_gNB_MAX) * sizeof(PHY_VARS_gNB *));
|
||||
LOG_I(NR_PHY, "Initializing NR L1: RC.nb_nr_L1_inst = %d\n", RC.nb_nr_L1_inst);
|
||||
|
||||
if (RC.gNB[j] == NULL) {
|
||||
RC.gNB[j] = calloc(1, sizeof(PHY_VARS_gNB));
|
||||
}
|
||||
}
|
||||
if (NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
||||
////////// Identification parameters
|
||||
paramdef_t GNBParams[] = GNBPARAMS_DESC;
|
||||
for (int j = 0; j < RC.nb_nr_L1_inst; j++) {
|
||||
PHY_VARS_gNB *gNB = RC.gNB[j];
|
||||
AssertFatal(RC.gNB[j] != NULL, "gNB L1 instance is null at index %d, cannot complete L1 configuration\n", j);
|
||||
// gNB params
|
||||
if (NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
||||
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0};
|
||||
config_get(config_get_if(), GNBSParams, sizeofArray(GNBSParams), NULL);
|
||||
int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
|
||||
AssertFatal(num_gnbs > 0, "Failed to parse config file, no GNBs found in field %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS);
|
||||
|
||||
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0};
|
||||
paramdef_t GNBParams[] = GNBPARAMS_DESC;
|
||||
config_getlist(config_get_if(), &GNBParamList, GNBParams, sizeofArray(GNBParams), NULL);
|
||||
int N1 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N1_IDX].iptr;
|
||||
int N2 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N2_IDX].iptr;
|
||||
int XP = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr;
|
||||
|
||||
config_get(config_get_if(), GNBSParams, sizeofArray(GNBSParams), NULL);
|
||||
int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
|
||||
AssertFatal(num_gnbs > 0, "Failed to parse config file no gnbs %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS);
|
||||
|
||||
config_getlist(config_get_if(), &GNBParamList, GNBParams, sizeofArray(GNBParams), NULL);
|
||||
int N1 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N1_IDX].iptr;
|
||||
int N2 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N2_IDX].iptr;
|
||||
int XP = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr;
|
||||
char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr;
|
||||
if (ulprbbl)
|
||||
LOG_D(NR_PHY, "PRB blacklist %s\n", ulprbbl);
|
||||
char *save = NULL;
|
||||
char *pt = strtok_r(ulprbbl, ",", &save);
|
||||
int prbbl[275];
|
||||
int num_prbbl = 0;
|
||||
memset(prbbl, 0, 275 * sizeof(int));
|
||||
|
||||
while (pt) {
|
||||
const int rb = atoi(pt);
|
||||
AssertFatal(rb < 275, "RB %d out of bounds (max 275)\n", rb);
|
||||
prbbl[rb] = 0x3FFF; // all symbols taken
|
||||
LOG_D(NR_PHY, "Blacklisting prb %d\n", atoi(pt));
|
||||
pt = strtok_r(NULL, ",", &save);
|
||||
num_prbbl++;
|
||||
}
|
||||
|
||||
RC.gNB[j]->num_ulprbbl = num_prbbl;
|
||||
LOG_D(NR_PHY, "Copying %d blacklisted PRB to L1 context\n", num_prbbl);
|
||||
memcpy(RC.gNB[j]->ulprbbl, prbbl, 275 * sizeof(int));
|
||||
|
||||
RC.gNB[j]->ap_N1 = N1;
|
||||
RC.gNB[j]->ap_N2 = N2;
|
||||
RC.gNB[j]->ap_XP = XP;
|
||||
}
|
||||
|
||||
paramdef_t L1_Params[] = L1PARAMS_DESC;
|
||||
paramlist_def_t L1_ParamList = {CONFIG_STRING_L1_LIST, NULL, 0};
|
||||
|
||||
config_getlist(config_get_if(), &L1_ParamList, L1_Params, sizeofArray(L1_Params), NULL);
|
||||
|
||||
if (L1_ParamList.numelt > 0) {
|
||||
for (j = 0; j < RC.nb_nr_L1_inst; j++) {
|
||||
if (RC.gNB[j] == NULL) {
|
||||
RC.gNB[j] = (PHY_VARS_gNB *)malloc(sizeof(PHY_VARS_gNB));
|
||||
memset(RC.gNB[j], 0, sizeof(PHY_VARS_gNB));
|
||||
RC.gNB[j]->Mod_id = j;
|
||||
// PRB Blacklist
|
||||
uint16_t prbbl[MAX_BWP_SIZE] = {0};
|
||||
int num_ulprbbl = get_prb_blacklist(j, prbbl);
|
||||
if (num_ulprbbl != -1) {
|
||||
RC.gNB[j]->num_ulprbbl = num_ulprbbl;
|
||||
LOG_D(NR_PHY, "Copying %d blacklisted PRB to L1 context\n", RC.gNB[j]->num_ulprbbl);
|
||||
memcpy(RC.gNB[j]->ulprbbl, prbbl, MAX_BWP_SIZE * sizeof(prbbl[0]));
|
||||
}
|
||||
AssertFatal(*L1_ParamList.paramarray[j][L1_THREAD_POOL_SIZE].uptr == 2022, "thread_pool_size removed, please use --thread-pool\n");
|
||||
RC.gNB[j]->ofdm_offset_divisor = *(L1_ParamList.paramarray[j][L1_OFDM_OFFSET_DIVISOR].uptr);
|
||||
RC.gNB[j]->pucch0_thres = *(L1_ParamList.paramarray[j][L1_PUCCH0_DTX_THRESHOLD].uptr);
|
||||
RC.gNB[j]->prach_thres = *(L1_ParamList.paramarray[j][L1_PRACH_DTX_THRESHOLD].uptr);
|
||||
RC.gNB[j]->pusch_thres = *(L1_ParamList.paramarray[j][L1_PUSCH_DTX_THRESHOLD].uptr);
|
||||
RC.gNB[j]->srs_thres = *(L1_ParamList.paramarray[j][L1_SRS_DTX_THRESHOLD].uptr);
|
||||
RC.gNB[j]->max_ldpc_iterations = *(L1_ParamList.paramarray[j][L1_MAX_LDPC_ITERATIONS].uptr);
|
||||
RC.gNB[j]->L1_rx_thread_core = *(L1_ParamList.paramarray[j][L1_RX_THREAD_CORE].iptr);
|
||||
RC.gNB[j]->L1_tx_thread_core = *(L1_ParamList.paramarray[j][L1_TX_THREAD_CORE].iptr);
|
||||
LOG_I(PHY,"L1_RX_THREAD_CORE %d (%d)\n",*(L1_ParamList.paramarray[j][L1_RX_THREAD_CORE].iptr),L1_RX_THREAD_CORE);
|
||||
RC.gNB[j]->TX_AMP = (int16_t)(32767.0 / pow(10.0, .05 * (double)(*L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr)));
|
||||
RC.gNB[j]->phase_comp = *L1_ParamList.paramarray[j][L1_PHASE_COMP].uptr;
|
||||
LOG_I(PHY, "TX_AMP = %d (-%d dBFS)\n", RC.gNB[j]->TX_AMP, *L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr);
|
||||
AssertFatal(RC.gNB[j]->TX_AMP > 300, "TX_AMP is too small, must be larger than 300 (is %d)\n", RC.gNB[j]->TX_AMP);
|
||||
|
||||
// Antenna ports
|
||||
gNB->ap_N1 = N1;
|
||||
gNB->ap_N2 = N2;
|
||||
gNB->ap_XP = XP;
|
||||
}
|
||||
|
||||
// L1 params
|
||||
paramdef_t L1_Params[] = L1PARAMS_DESC;
|
||||
paramlist_def_t L1_ParamList = {CONFIG_STRING_L1_LIST, NULL, 0};
|
||||
config_getlist(config_get_if(), &L1_ParamList, L1_Params, sizeofArray(L1_Params), NULL);
|
||||
if (L1_ParamList.numelt > 0) {
|
||||
AssertFatal(*L1_ParamList.paramarray[j][L1_THREAD_POOL_SIZE].uptr == 2022,
|
||||
"thread_pool_size removed, please use --thread-pool\n");
|
||||
gNB->ofdm_offset_divisor = *(L1_ParamList.paramarray[j][L1_OFDM_OFFSET_DIVISOR].uptr);
|
||||
gNB->pucch0_thres = *(L1_ParamList.paramarray[j][L1_PUCCH0_DTX_THRESHOLD].uptr);
|
||||
gNB->prach_thres = *(L1_ParamList.paramarray[j][L1_PRACH_DTX_THRESHOLD].uptr);
|
||||
gNB->pusch_thres = *(L1_ParamList.paramarray[j][L1_PUSCH_DTX_THRESHOLD].uptr);
|
||||
gNB->srs_thres = *(L1_ParamList.paramarray[j][L1_SRS_DTX_THRESHOLD].uptr);
|
||||
gNB->max_ldpc_iterations = *(L1_ParamList.paramarray[j][L1_MAX_LDPC_ITERATIONS].uptr);
|
||||
gNB->L1_rx_thread_core = *(L1_ParamList.paramarray[j][L1_RX_THREAD_CORE].iptr);
|
||||
gNB->L1_tx_thread_core = *(L1_ParamList.paramarray[j][L1_TX_THREAD_CORE].iptr);
|
||||
LOG_I(NR_PHY, "L1_RX_THREAD_CORE %d (%d)\n", *(L1_ParamList.paramarray[j][L1_RX_THREAD_CORE].iptr), L1_RX_THREAD_CORE);
|
||||
gNB->TX_AMP = (int16_t)(32767.0 / pow(10.0, .05 * (double)(*L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr)));
|
||||
gNB->phase_comp = *L1_ParamList.paramarray[j][L1_PHASE_COMP].uptr;
|
||||
LOG_I(NR_PHY, "TX_AMP = %d (-%d dBFS)\n", gNB->TX_AMP, *L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr);
|
||||
AssertFatal(gNB->TX_AMP > 300, "TX_AMP is too small, must be larger than 300 (is %d)\n", gNB->TX_AMP);
|
||||
// Midhaul configuration
|
||||
if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) {
|
||||
// sf_ahead = 2; // Need 4 subframe gap between RX and TX
|
||||
// do nothing
|
||||
} else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) {
|
||||
RC.gNB[j]->eth_params_n.my_addr = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_ADDRESS_IDX].strptr));
|
||||
RC.gNB[j]->eth_params_n.remote_addr = strdup(*(L1_ParamList.paramarray[j][L1_REMOTE_N_ADDRESS_IDX].strptr));
|
||||
RC.gNB[j]->eth_params_n.my_portc = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTC_IDX].iptr);
|
||||
RC.gNB[j]->eth_params_n.remote_portc = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTC_IDX].iptr);
|
||||
RC.gNB[j]->eth_params_n.my_portd = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTD_IDX].iptr);
|
||||
RC.gNB[j]->eth_params_n.remote_portd = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTD_IDX].iptr);
|
||||
RC.gNB[j]->eth_params_n.transp_preference = ETH_UDP_MODE;
|
||||
gNB->eth_params_n.my_addr = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_ADDRESS_IDX].strptr));
|
||||
gNB->eth_params_n.remote_addr = strdup(*(L1_ParamList.paramarray[j][L1_REMOTE_N_ADDRESS_IDX].strptr));
|
||||
gNB->eth_params_n.my_portc = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTC_IDX].iptr);
|
||||
gNB->eth_params_n.remote_portc = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTC_IDX].iptr);
|
||||
gNB->eth_params_n.my_portd = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTD_IDX].iptr);
|
||||
gNB->eth_params_n.remote_portd = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTD_IDX].iptr);
|
||||
gNB->eth_params_n.transp_preference = ETH_UDP_MODE;
|
||||
|
||||
// sf_ahead = 2; // Cannot cope with 4 subframes betweem RX and TX - set it to 2
|
||||
|
||||
RC.nb_nr_macrlc_inst = 1; // This is used by mac_top_init_gNB()
|
||||
|
||||
// This is used by init_gNB_afterRU()
|
||||
RC.nb_nr_CC = (int *)malloc((1 + RC.nb_nr_inst) * sizeof(int));
|
||||
RC.nb_nr_CC[0] = 1;
|
||||
|
||||
LOG_D(PHY,
|
||||
"%s() NFAPI PNF mode - RC.nb_nr_inst=1 this is because phy_init_RU() uses that to index and not RC.num_gNB - why the "
|
||||
"2 similar variables?\n",
|
||||
__FUNCTION__);
|
||||
LOG_D(PHY, "%s() NFAPI PNF mode - RC.nb_nr_CC[0]=%d for init_gNB_afterRU()\n", __FUNCTION__, RC.nb_nr_CC[0]);
|
||||
LOG_D(PHY,
|
||||
"%s() NFAPI PNF mode - RC.nb_nr_macrlc_inst:%d because used by mac_top_init_gNB()\n",
|
||||
__FUNCTION__,
|
||||
RC.nb_nr_macrlc_inst);
|
||||
|
||||
configure_nr_nfapi_pnf(RC.gNB[j]->eth_params_n.remote_addr,
|
||||
RC.gNB[j]->eth_params_n.remote_portc,
|
||||
RC.gNB[j]->eth_params_n.my_addr,
|
||||
RC.gNB[j]->eth_params_n.my_portd,
|
||||
RC.gNB[j]->eth_params_n.remote_portd);
|
||||
} else { // other midhaul
|
||||
configure_nr_nfapi_pnf(gNB->eth_params_n.remote_addr,
|
||||
gNB->eth_params_n.remote_portc,
|
||||
gNB->eth_params_n.my_addr,
|
||||
gNB->eth_params_n.my_portd,
|
||||
gNB->eth_params_n.remote_portd);
|
||||
} else {
|
||||
// other midhaul, do nothing
|
||||
}
|
||||
} // for (j = 0; j < RC.nb_nr_L1_inst; j++)
|
||||
l1_north_init_gNB();
|
||||
} else {
|
||||
LOG_E(PHY, "No " CONFIG_STRING_L1_LIST " configuration found");
|
||||
|
||||
// need to create some structures for VNF
|
||||
|
||||
j = 0;
|
||||
|
||||
if (RC.gNB[j] == NULL) {
|
||||
RC.gNB[j] = (PHY_VARS_gNB *)malloc(sizeof(PHY_VARS_gNB));
|
||||
memset((void *)RC.gNB[j], 0, sizeof(PHY_VARS_gNB));
|
||||
RC.gNB[j]->Mod_id = j;
|
||||
LOG_D(NR_PHY, "Initializing northbound interface for L1\n");
|
||||
l1_north_init_gNB();
|
||||
} else {
|
||||
LOG_E(NR_PHY, "No " CONFIG_STRING_L1_LIST " configuration found");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1258,8 +1235,6 @@ static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
|
||||
void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
{
|
||||
int j = 0;
|
||||
uint16_t prbbl[275] = {0};
|
||||
int num_prbbl = 0;
|
||||
|
||||
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0};
|
||||
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
||||
@@ -1276,21 +1251,6 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
GNBParams[i].chkPptr = &(config_check_GNBParams[i]);
|
||||
config_getlist(cfg, &GNBParamList, GNBParams, sizeofArray(GNBParams), NULL);
|
||||
|
||||
if (NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
////////// Identification parameters
|
||||
|
||||
char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr;
|
||||
char *save = NULL;
|
||||
char *pt = strtok_r(ulprbbl, ",", &save);
|
||||
memset(prbbl, 0, sizeof(prbbl));
|
||||
while (pt) {
|
||||
const int prb = atoi(pt);
|
||||
AssertFatal(prb < 275, "RB %d out of bounds (max 275)\n", prb);
|
||||
prbbl[prb] = 0x3FFF; // all symbols taken
|
||||
pt = strtok_r(NULL, ",", &save);
|
||||
num_prbbl++;
|
||||
}
|
||||
}
|
||||
paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC;
|
||||
paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST, NULL, 0};
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
@@ -1401,7 +1361,6 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
NR_ServingCellConfig_t *scd = get_scd_config(cfg);
|
||||
|
||||
if (MacRLC_ParamList.numelt > 0) {
|
||||
RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt;
|
||||
ngran_node_t node_type = get_node_type();
|
||||
mac_top_init_gNB(node_type, scc, scd, &config);
|
||||
RC.nb_nr_mac_CC = (int *)malloc(RC.nb_nr_macrlc_inst * sizeof(int));
|
||||
@@ -1482,8 +1441,13 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
RC.nrmac[j]->min_grant_prb = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_PRB_IDX].u8ptr);
|
||||
RC.nrmac[j]->min_grant_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_MCS_IDX].u8ptr);
|
||||
RC.nrmac[j]->identity_pm = *(MacRLC_ParamList.paramarray[j][MACRLC_IDENTITY_PM_IDX].u8ptr);
|
||||
RC.nrmac[j]->num_ulprbbl = num_prbbl;
|
||||
memcpy(RC.nrmac[j]->ulprbbl, prbbl, 275 * sizeof(prbbl[0]));
|
||||
// PRB Blacklist
|
||||
uint16_t prbbl[MAX_BWP_SIZE] = {0};
|
||||
int num_ulprbbl = get_prb_blacklist(j, prbbl);
|
||||
if (num_ulprbbl != -1) {
|
||||
LOG_I(NR_PHY, "Copying %d blacklisted PRB to L1 context\n", num_ulprbbl);
|
||||
memcpy(RC.nrmac[j]->ulprbbl, prbbl, MAX_BWP_SIZE * sizeof(prbbl[0]));
|
||||
}
|
||||
bool ab = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMFORMING_IDX].u8ptr;
|
||||
if (ab) {
|
||||
NR_beam_info_t *beam_info = &RC.nrmac[j]->beam_info;
|
||||
@@ -1797,8 +1761,14 @@ static void fill_measurement_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
|
||||
}
|
||||
}
|
||||
|
||||
void RCconfig_NRRRC(gNB_RRC_INST *rrc)
|
||||
/**
|
||||
* @brief Allocates and initializes RRC instances
|
||||
* Currently assuming 1 instance
|
||||
*/
|
||||
gNB_RRC_INST *RCconfig_NRRRC()
|
||||
{
|
||||
// Allocate memory for 1 RRC instance
|
||||
gNB_RRC_INST *rrc = calloc(1, sizeof(*rrc));
|
||||
|
||||
int num_gnbs = 0;
|
||||
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
|
||||
@@ -1938,7 +1908,9 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
|
||||
}//End if (num_gnbs>0)
|
||||
|
||||
config_security(rrc);
|
||||
}//End RCconfig_NRRRC function
|
||||
|
||||
return rrc;
|
||||
}
|
||||
|
||||
int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i) {
|
||||
|
||||
@@ -2149,30 +2121,68 @@ int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NRRCConfig(void) {
|
||||
static pthread_mutex_t rc_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool rc_done = false;
|
||||
|
||||
/**
|
||||
* @brief This function is initializing the RAN context
|
||||
* the its various layer instances
|
||||
*/
|
||||
void NRRCConfig(void)
|
||||
{
|
||||
// Call NRRCConfig only once
|
||||
pthread_mutex_lock(&rc_mutex);
|
||||
if (rc_done) {
|
||||
LOG_E(GNB_APP, "RAN Context has been already initialized\n");
|
||||
pthread_mutex_unlock(&rc_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
memset((void *)&RC, 0, sizeof(RC));
|
||||
|
||||
paramlist_def_t MACRLCParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0};
|
||||
paramlist_def_t L1ParamList = {CONFIG_STRING_L1_LIST,NULL,0};
|
||||
paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
|
||||
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
||||
|
||||
/* get global parameters, defined outside any section in the config file */
|
||||
|
||||
config_get(config_get_if(), GNBSParams, sizeofArray(GNBSParams), NULL);
|
||||
RC.nb_nr_inst = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
|
||||
|
||||
// Get num MACRLC instances
|
||||
// Set num of gNBs instances
|
||||
RC.nb_nr_inst = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
|
||||
AssertFatal(RC.nb_nr_inst == NUMBER_OF_gNB_MAX,
|
||||
"Configuration error: RC.nb_nr_inst (%d) must equal NUMBER_OF_gNB_MAX (%d).\n"
|
||||
"Currently, only one instance of each layer (L1, L2, L3) is supported.\n"
|
||||
"Ensure that nb_nr_inst matches the maximum allowed gNB instances in this configuration.",
|
||||
RC.nb_nr_inst, NUMBER_OF_gNB_MAX);
|
||||
|
||||
// Set num MACRLC instances
|
||||
paramlist_def_t MACRLCParamList = {CONFIG_STRING_MACRLC_LIST, NULL, 0};
|
||||
config_getlist(config_get_if(), &MACRLCParamList, NULL, 0, NULL);
|
||||
RC.nb_nr_macrlc_inst = MACRLCParamList.numelt;
|
||||
// Get num L1 instances
|
||||
RC.nb_nr_macrlc_inst = MACRLCParamList.numelt;
|
||||
|
||||
// Set num L1 instances
|
||||
paramlist_def_t L1ParamList = {CONFIG_STRING_L1_LIST, NULL, 0};
|
||||
config_getlist(config_get_if(), &L1ParamList, NULL, 0, NULL);
|
||||
RC.nb_nr_L1_inst = L1ParamList.numelt;
|
||||
|
||||
// Get num RU instances
|
||||
config_getlist(config_get_if(), &RUParamList, NULL, 0, NULL);
|
||||
RC.nb_RU = RUParamList.numelt;
|
||||
}
|
||||
|
||||
// Set num RU instances
|
||||
paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST, NULL, 0};
|
||||
config_getlist(config_get_if(), &RUParamList, NULL, 0, NULL);
|
||||
RC.nb_RU = RUParamList.numelt;
|
||||
|
||||
// Set num component carriers
|
||||
RC.nb_nr_CC = calloc_or_fail(1, sizeof(*RC.nb_nr_CC));
|
||||
*RC.nb_nr_CC = RC.nb_nr_L1_inst;
|
||||
AssertFatal(*RC.nb_nr_CC <= MAX_NUM_CCs, "Configured number of CCs (%d) not supported\n", *RC.nb_nr_CC);
|
||||
|
||||
LOG_I(GNB_APP,
|
||||
"Initialized RAN Context: RC.nb_nr_inst = %d, RC.nb_nr_macrlc_inst = %d, RC.nb_nr_L1_inst = %d, RC.nb_RU = %d, "
|
||||
"RC.nb_nr_CC[0] = %d\n",
|
||||
RC.nb_nr_inst,
|
||||
RC.nb_nr_macrlc_inst,
|
||||
RC.nb_nr_L1_inst,
|
||||
RC.nb_RU,
|
||||
*RC.nb_nr_CC);
|
||||
|
||||
rc_done = true;
|
||||
pthread_mutex_unlock(&rc_mutex);
|
||||
}
|
||||
|
||||
int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) {
|
||||
int J, l;
|
||||
@@ -2407,7 +2417,6 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up
|
||||
gnb_cu_cfg_update->num_cells_to_activate, RC.nb_nr_inst);
|
||||
|
||||
AssertFatal(gnb_cu_cfg_update->num_cells_to_activate == 1, "only one cell supported at the moment\n");
|
||||
AssertFatal(RC.nb_nr_inst == 1, "expected one instance\n");
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
NR_SCHED_LOCK(&mac->sched_lock);
|
||||
for (j = 0; j < gnb_cu_cfg_update->num_cells_to_activate; j++) {
|
||||
@@ -2477,12 +2486,9 @@ ngran_node_t get_node_type(void)
|
||||
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
|
||||
sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0);
|
||||
config_getlist(config_get_if(), &GNBE1ParamList, GNBE1Params, sizeofArray(GNBE1Params), aprefix);
|
||||
if (MacRLC_ParamList.numelt > 0) {
|
||||
RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt;
|
||||
for (int j = 0; j < RC.nb_nr_macrlc_inst; j++) {
|
||||
if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) {
|
||||
return ngran_gNB_DU; // MACRLCs present in config: it must be a DU
|
||||
}
|
||||
for (int j = 0; j < MacRLC_ParamList.numelt; j++) {
|
||||
if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) {
|
||||
return ngran_gNB_DU; // MACRLCs present in config: it must be a DU
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ extern void NRRCConfig(void);
|
||||
//void enb_config_display(void);
|
||||
//void ru_config_display(void);
|
||||
|
||||
void RCconfig_NRRRC(gNB_RRC_INST *rrc);
|
||||
gNB_RRC_INST *RCconfig_NRRRC();
|
||||
int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i);
|
||||
int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i);
|
||||
void wait_f1_setup_response(void);
|
||||
|
||||
@@ -712,14 +712,6 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
|
||||
(nrmac->ulsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0);
|
||||
}
|
||||
|
||||
if (get_softmodem_params()->phy_test) {
|
||||
nrmac->pre_processor_dl = nr_preprocessor_phytest;
|
||||
nrmac->pre_processor_ul = nr_ul_preprocessor_phytest;
|
||||
} else {
|
||||
nrmac->pre_processor_dl = nr_init_fr1_dlsch_preprocessor(0);
|
||||
nrmac->pre_processor_ul = nr_init_fr1_ulsch_preprocessor(0);
|
||||
}
|
||||
|
||||
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
|
||||
NR_SCHED_LOCK(&nrmac->sched_lock);
|
||||
for (int n = 0; n < NR_NB_RA_PROC_MAX; n++) {
|
||||
|
||||
@@ -842,7 +842,7 @@ typedef struct gNB_MAC_INST_s {
|
||||
NR_COMMON_channels_t common_channels[NFAPI_CC_MAX];
|
||||
/// current PDU index (BCH,DLSCH)
|
||||
uint16_t pdu_index[NFAPI_CC_MAX];
|
||||
int num_ulprbbl;
|
||||
/// UL PRBs blacklist
|
||||
uint16_t ulprbbl[MAX_BWP_SIZE];
|
||||
/// NFAPI Config Request Structure
|
||||
nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX];
|
||||
|
||||
@@ -219,7 +219,7 @@ static void init_NR_SI(gNB_RRC_INST *rrc)
|
||||
AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "phy_test and do_ra only work in monolithic\n");
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_allocate_new_ue_context(rrc);
|
||||
LOG_I(NR_RRC,"Adding new user (%p)\n",ue_context_p);
|
||||
if (!NODE_IS_CU(RC.nrrrc[0]->node_type)) {
|
||||
if (!NODE_IS_CU(rrc->node_type)) {
|
||||
rrc_add_nsa_user(rrc,ue_context_p,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user