Merge branch 'develop' into NR_UE_RA_fixes
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+37
-3090
File diff suppressed because it is too large
Load Diff
@@ -2253,6 +2253,60 @@ function run_test_on_vm {
|
||||
######### start of PHY TEST loop
|
||||
while [ $try_cnt -lt 4 ]
|
||||
do
|
||||
|
||||
#start RA test
|
||||
SYNC_STATUS=0
|
||||
PING_STATUS=0
|
||||
IPERF_STATUS=0
|
||||
|
||||
echo "############################################################"
|
||||
echo "${CN_CONFIG} : Starting the gNB"
|
||||
echo "############################################################"
|
||||
CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log
|
||||
#last argument = 1 is to enable --do-ra for RA test
|
||||
start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 1
|
||||
|
||||
echo "############################################################"
|
||||
echo "${CN_CONFIG} : Starting the NR-UE"
|
||||
echo "############################################################"
|
||||
CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log
|
||||
#last argument = 1 is to enable --do-ra for RA test
|
||||
start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 1
|
||||
if [ $NR_UE_SYNC -eq 0 ]
|
||||
then
|
||||
echo "Problem w/ gNB and NR-UE not syncing"
|
||||
terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2
|
||||
terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1
|
||||
scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC
|
||||
scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC
|
||||
SYNC_STATUS=-1
|
||||
try_cnt=$[$try_cnt+1]
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "############################################################"
|
||||
echo "${CN_CONFIG} : Terminate gNB/NR-UE simulators"
|
||||
echo "############################################################"
|
||||
sleep 20
|
||||
terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2
|
||||
terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1
|
||||
scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC
|
||||
scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC
|
||||
|
||||
#check RA markers in gNB and NR UE log files
|
||||
echo "############################################################"
|
||||
echo "${CN_CONFIG} : Checking RA on gNB / NR-UE"
|
||||
echo "############################################################"
|
||||
|
||||
mv $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/ra_check_$CURRENT_GNB_LOG_FILE
|
||||
mv $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC/ra_check_$CURRENT_NR_UE_LOG_FILE
|
||||
# Proper check to be done when RA test is working!
|
||||
#check_ra_result $ARCHIVES_LOC/ra_check_$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/ra_check_$CURRENT_NR_UE_LOG_FILE
|
||||
|
||||
|
||||
#end RA test
|
||||
sleep 30
|
||||
|
||||
SYNC_STATUS=0
|
||||
PING_STATUS=0
|
||||
IPERF_STATUS=0
|
||||
|
||||
@@ -1095,9 +1095,22 @@ add_library(FLEXRAN_AGENT
|
||||
${OPENAIR2_DIR}/ENB_APP/flexran_agent_async.c
|
||||
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
|
||||
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c
|
||||
${OPENAIR2_DIR}/ENB_APP/flexran_agent_app.c
|
||||
)
|
||||
add_dependencies(FLEXRAN_AGENT rrc_flag)
|
||||
set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT)
|
||||
add_library(flapp_sample SHARED
|
||||
${OPENAIR2_DIR}/ENB_APP/flexran_apps/sample.c
|
||||
)
|
||||
set_target_properties(flapp_sample PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
add_library(flapp_imsi SHARED
|
||||
${OPENAIR2_DIR}/ENB_APP/flexran_apps/imsi.c
|
||||
)
|
||||
set_target_properties(flapp_imsi PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
add_custom_target(flapp_all DEPENDS
|
||||
flapp_sample
|
||||
flapp_imsi
|
||||
)
|
||||
#include_directories(${OPENAIR2_DIR}/ENB_APP)
|
||||
|
||||
set(PROTOBUF_LIB "protobuf-c")
|
||||
|
||||
@@ -179,7 +179,7 @@ void prach_eNB_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_r
|
||||
ru=eNB->RU_list[i];
|
||||
|
||||
for (ru_aa=0,aa=0; ru_aa<ru->nb_rx; ru_aa++,aa++) {
|
||||
eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa];
|
||||
eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[0][ru_aa];
|
||||
int ce_level;
|
||||
|
||||
for (ce_level=0; ce_level<4; ce_level++)
|
||||
|
||||
@@ -228,7 +228,7 @@ void init_eNB_afterRU(void) {
|
||||
|
||||
for (int i=0; i<eNB->RU_list[ru_id]->nb_rx; aa++,i++) {
|
||||
LOG_I(PHY,"Attaching RU %d antenna %d to eNB antenna %d\n",eNB->RU_list[ru_id]->idx,i,aa);
|
||||
eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[ru_id]->prach_rxsigF[i];
|
||||
eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[ru_id]->prach_rxsigF[0][i];
|
||||
|
||||
for (int ce_level=0; ce_level<4; ce_level++)
|
||||
eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[ru_id]->prach_rxsigF_br[ce_level][i];
|
||||
@@ -483,7 +483,7 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int br_flag)
|
||||
ru=eNB->RU_list[i];
|
||||
|
||||
for (ru_aa=0,aa=0; ru_aa<ru->nb_rx; ru_aa++,aa++) {
|
||||
eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa];
|
||||
eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[0][ru_aa];
|
||||
int ce_level;
|
||||
|
||||
if (br_flag==1)
|
||||
|
||||
@@ -255,11 +255,7 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
|
||||
// TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT
|
||||
|
||||
// Do PRACH RU processing
|
||||
int prach_id=find_nr_prach(gNB,frame_rx,slot_rx,0,SEARCH_EXIST);
|
||||
if (prach_id>=0) {
|
||||
L1_nr_prach_procedures(gNB,frame_rx,slot_rx,&gNB->prach_vars.list[prach_id].pdu);
|
||||
gNB->prach_vars.list[prach_id].frame=-1;
|
||||
}
|
||||
L1_nr_prach_procedures(gNB,frame_rx,slot_rx);
|
||||
phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
|
||||
}
|
||||
|
||||
@@ -981,7 +977,7 @@ void init_eNB_afterRU(void) {
|
||||
|
||||
for (i=0; i<gNB->RU_list[ru_id]->nb_rx; aa++,i++) {
|
||||
LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n",gNB->RU_list[ru_id]->idx,i,aa);
|
||||
gNB->prach_vars.rxsigF[aa] = gNB->RU_list[ru_id]->prach_rxsigF[i];
|
||||
gNB->prach_vars.rxsigF[aa] = gNB->RU_list[ru_id]->prach_rxsigF[0][i];
|
||||
gNB->common_vars.rxdataF[aa] = gNB->RU_list[ru_id]->common.rxdataF[i];
|
||||
}
|
||||
}
|
||||
|
||||
+28
-5
@@ -1594,13 +1594,36 @@ void *ru_thread( void *param ) {
|
||||
(void*)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t));
|
||||
|
||||
// Do PRACH RU processing
|
||||
|
||||
int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST);
|
||||
uint8_t prachStartSymbol,N_dur;
|
||||
if (prach_id>=0) {
|
||||
rx_nr_prach_ru(ru,
|
||||
ru->prach_list[prach_id].fmt,
|
||||
ru->prach_list[prach_id].numRA,
|
||||
ru->prach_list[prach_id].prachStartSymbol,
|
||||
proc->frame_rx,proc->tti_rx);
|
||||
N_dur = get_nr_prach_duration(ru->prach_list[prach_id].fmt);
|
||||
/*
|
||||
get_nr_prach_info_from_index(ru->config.prach_config.prach_ConfigurationIndex.value,
|
||||
proc->frame_rx,proc->tti_rx,
|
||||
ru->config.carrier_config.dl_frequency.value,
|
||||
fp->numerology_index,
|
||||
fp->frame_type,
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur,
|
||||
&RA_sfn_index,
|
||||
&N_RA_slot,
|
||||
&config_period);
|
||||
*/
|
||||
for (int prach_oc = 0; prach_oc<ru->prach_list[prach_id].num_prach_ocas; prach_oc++) {
|
||||
prachStartSymbol = ru->prach_list[prach_id].prachStartSymbol+prach_oc*N_dur;
|
||||
//comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}.
|
||||
|
||||
rx_nr_prach_ru(ru,
|
||||
ru->prach_list[prach_id].fmt, //could also use format
|
||||
ru->prach_list[prach_id].numRA,
|
||||
prachStartSymbol,
|
||||
prach_oc,
|
||||
proc->frame_rx,proc->tti_rx);
|
||||
}
|
||||
free_nr_ru_prach_entry(ru,prach_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +348,15 @@ int wake_eNB_rxtx(PHY_VARS_eNB *eNB, uint16_t sfn, uint16_t sf) {
|
||||
old_sf = sf;
|
||||
old_sfn = sfn;
|
||||
|
||||
if (old_sf == 0 && old_sfn % 100==0) LOG_W( PHY,"[eNB] sfn/sf:%d%d old_sfn/sf:%d%d proc[rx:%d%d]\n", sfn, sf, old_sfn, old_sf, proc->frame_rx, proc->subframe_rx);
|
||||
if (old_sf == 0 && old_sfn % 100==0)
|
||||
LOG_D(PHY,
|
||||
"[eNB] sfn/sf:%d%d old_sfn/sf:%d%d proc[rx:%d%d]\n",
|
||||
sfn,
|
||||
sf,
|
||||
old_sfn,
|
||||
old_sf,
|
||||
proc->frame_rx,
|
||||
proc->subframe_rx);
|
||||
}
|
||||
|
||||
++L1_proc->instance_cnt;
|
||||
@@ -435,6 +443,7 @@ int phy_rach_indication(struct nfapi_vnf_p7_config *config, nfapi_rach_indicatio
|
||||
}
|
||||
if(index == -1){
|
||||
LOG_E(MAC,"phy_rach_indication : num of rach reach max \n");
|
||||
pthread_mutex_unlock(&eNB->UL_INFO_mutex);
|
||||
return 0;
|
||||
}
|
||||
UL_RCC_INFO.rach_ind[index] = *ind;
|
||||
@@ -499,6 +508,7 @@ int phy_harq_indication(struct nfapi_vnf_p7_config *config, nfapi_harq_indicatio
|
||||
}
|
||||
if(index == -1){
|
||||
LOG_E(MAC,"phy_harq_indication : num of harq reach max \n");
|
||||
pthread_mutex_unlock(&eNB->UL_INFO_mutex);
|
||||
return 0;
|
||||
}
|
||||
UL_RCC_INFO.harq_ind[index] = *ind;
|
||||
@@ -538,6 +548,7 @@ int phy_crc_indication(struct nfapi_vnf_p7_config *config, nfapi_crc_indication_
|
||||
}
|
||||
if(index == -1){
|
||||
LOG_E(MAC,"phy_crc_indication : num of crc reach max \n");
|
||||
pthread_mutex_unlock(&eNB->UL_INFO_mutex);
|
||||
return 0;
|
||||
}
|
||||
UL_RCC_INFO.crc_ind[index] = *ind;
|
||||
@@ -603,6 +614,7 @@ int phy_rx_indication(struct nfapi_vnf_p7_config *config, nfapi_rx_indication_t
|
||||
}
|
||||
if(index == -1){
|
||||
LOG_E(MAC,"phy_rx_indication : num of rx reach max \n");
|
||||
pthread_mutex_unlock(&eNB->UL_INFO_mutex);
|
||||
return 0;
|
||||
}
|
||||
UL_RCC_INFO.rx_ind[index] = *ind;
|
||||
@@ -686,6 +698,7 @@ int phy_sr_indication(struct nfapi_vnf_p7_config *config, nfapi_sr_indication_t
|
||||
}
|
||||
if(index == -1){
|
||||
LOG_E(MAC,"phy_sr_indication : num of sr reach max \n");
|
||||
pthread_mutex_unlock(&eNB->UL_INFO_mutex);
|
||||
return 0;
|
||||
}
|
||||
UL_RCC_INFO.sr_ind[index] = *ind;
|
||||
@@ -737,6 +750,7 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_
|
||||
}
|
||||
if(index == -1){
|
||||
LOG_E(MAC,"phy_cqi_indication : num of cqi reach max \n");
|
||||
pthread_mutex_unlock(&eNB->UL_INFO_mutex);
|
||||
return 0;
|
||||
}
|
||||
UL_RCC_INFO.cqi_ind[index] = *ind;
|
||||
|
||||
@@ -321,6 +321,7 @@ typedef enum {
|
||||
#define NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG 0x1012
|
||||
#define NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG 0x1013
|
||||
#define NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG 0x1014
|
||||
#define NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG 0x1029
|
||||
#define NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG 0x1015
|
||||
#define NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG 0x1016
|
||||
#define NFAPI_NR_CONFIG_K1_TAG 0x1017
|
||||
@@ -385,7 +386,6 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t num_prach_fd_occasions;
|
||||
nfapi_uint16_tlv_t prach_root_sequence_index;//Starting logical root sequence index, 𝑖, equivalent to higher layer parameter prach-RootSequenceIndex [38.211, sec 6.3.3.1] Value: 0 -> 837
|
||||
nfapi_uint8_tlv_t num_root_sequences;//Number of root sequences for a particular FD occasion that are required to generate the necessary number of preambles
|
||||
nfapi_uint16_tlv_t k1;//Frequency offset (from UL bandwidth part) for each FD. [38.211, sec 6.3.3.2] Value: from 0 to 272
|
||||
@@ -401,7 +401,9 @@ typedef struct
|
||||
nfapi_uint8_tlv_t prach_sub_c_spacing;//Subcarrier spacing of PRACH. [38.211 sec 4.2] Value:0->4
|
||||
nfapi_uint8_tlv_t restricted_set_config;//PRACH restricted set config Value: 0: unrestricted 1: restricted set type A 2: restricted set type B
|
||||
nfapi_uint8_tlv_t num_prach_fd_occasions;//Corresponds to the parameter 𝑀 in [38.211, sec 6.3.3.2] which equals the higher layer parameter msg1FDM Value: 1,2,4,8
|
||||
nfapi_uint8_tlv_t prach_ConfigurationIndex;//PRACH configuration index. Value:0->255
|
||||
nfapi_nr_num_prach_fd_occasions_t* num_prach_fd_occasions_list;
|
||||
|
||||
nfapi_uint8_tlv_t ssb_per_rach;//SSB-per-RACH-occasion Value: 0: 1/8 1:1/4, 2:1/2 3:1 4:2 5:4, 6:8 7:16
|
||||
nfapi_uint8_tlv_t prach_multiple_carriers_in_a_band;//0 = disabled 1 = enabled
|
||||
|
||||
|
||||
@@ -955,7 +955,7 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n",
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n",
|
||||
NFAPI_SFNSF2SFN(phy->sfn_sf), NFAPI_SFNSF2SF(phy->sfn_sf), ts.tv_sec, ts.tv_nsec, ind.header.phy_id,
|
||||
ind.t1, ind.t2, ind.t3, t4,
|
||||
tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->sf_offset, phy->sf_offset_filtered,
|
||||
@@ -1016,7 +1016,7 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
|
||||
{
|
||||
phy->adjustment = NFAPI_SFNSF2DEC(new_sfn_sf) - NFAPI_SFNSF2DEC(curr_sfn_sf);
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_sf_offset_filtered:%d phy->previous_sf_offset_filtered:%d phy->sf_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_sf_offset_filtered, phy->previous_sf_offset_filtered, phy->sf_offset_trend);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF to VNF phy_id:%d adjustment%d phy->previous_sf_offset_filtered:%d phy->previous_sf_offset_filtered:%d phy->sf_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_sf_offset_filtered, phy->previous_sf_offset_filtered, phy->sf_offset_trend);
|
||||
|
||||
phy->previous_t1 = 0;
|
||||
phy->previous_t2 = 0;
|
||||
|
||||
@@ -121,13 +121,13 @@ int phy_init_RU(RU_t *ru) {
|
||||
/* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */
|
||||
//AssertFatal(ru->nb_rx <= sizeof(ru->prach_rxsigF) / sizeof(ru->prach_rxsigF[0]),
|
||||
//"nb_antennas_rx too large");
|
||||
ru->prach_rxsigF = (int16_t **)malloc(ru->nb_rx * sizeof(int16_t *));
|
||||
ru->prach_rxsigF[0] = (int16_t **)malloc(ru->nb_rx * sizeof(int16_t *));
|
||||
|
||||
for (j=0; j<4; j++) ru->prach_rxsigF_br[j] = (int16_t **)malloc(ru->nb_rx * sizeof(int16_t *));
|
||||
|
||||
for (i=0; i<ru->nb_rx; i++) {
|
||||
ru->prach_rxsigF[i] = (int16_t *)malloc16_clear( fp->ofdm_symbol_size*12*2*sizeof(int16_t) );
|
||||
LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,ru->prach_rxsigF[i]);
|
||||
ru->prach_rxsigF[0][i] = (int16_t *)malloc16_clear( fp->ofdm_symbol_size*12*2*sizeof(int16_t) );
|
||||
LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,ru->prach_rxsigF[0][i]);
|
||||
|
||||
for (j=0; j<4; j++) {
|
||||
ru->prach_rxsigF_br[j][i] = (int16_t *)malloc16_clear( fp->ofdm_symbol_size*12*2*sizeof(int16_t) );
|
||||
@@ -230,14 +230,14 @@ void phy_free_RU(RU_t *ru) {
|
||||
}
|
||||
|
||||
for (i = 0; i < ru->nb_rx; i++) {
|
||||
free_and_zero(ru->prach_rxsigF[i]);
|
||||
free_and_zero(ru->prach_rxsigF[0][i]);
|
||||
|
||||
for (j = 0; j < 4; j++) free_and_zero(ru->prach_rxsigF_br[j][i]);
|
||||
}
|
||||
|
||||
for (j = 0; j < 4; j++) free_and_zero(ru->prach_rxsigF_br[j]);
|
||||
|
||||
free_and_zero(ru->prach_rxsigF);
|
||||
free_and_zero(ru->prach_rxsigF[0]);
|
||||
/* ru->prach_rxsigF_br is not allocated -> don't free */
|
||||
|
||||
for (i = 0; i < RC.nb_L1_inst; i++) {
|
||||
|
||||
@@ -497,11 +497,12 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) {
|
||||
fd_occasion = 0;
|
||||
nfapi_nr_prach_config_t *prach_config = &gNB_config->prach_config;
|
||||
short_sequence = prach_config->prach_sequence_length.value;
|
||||
// for(fd_occasion = 0; fd_occasion <= prach_config->num_prach_fd_occasions.value ; fd_occasion) { // TODO Need to handle for msg1-fdm > 1
|
||||
num_sequences = prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value;
|
||||
rootSequenceIndex = prach_config->num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index.value;
|
||||
|
||||
compute_nr_prach_seq(short_sequence, num_sequences, rootSequenceIndex, RC.gNB[Mod_id]->X_u);
|
||||
|
||||
// }
|
||||
RC.gNB[Mod_id]->configured = 1;
|
||||
|
||||
init_symbol_rotation(fp,fp->dl_CarrierFreq);
|
||||
|
||||
@@ -107,12 +107,14 @@ int nr_phy_init_RU(RU_t *ru) {
|
||||
/* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */
|
||||
// AssertFatal(ru->nb_rx <= sizeof(ru->prach_rxsigF) / sizeof(ru->prach_rxsigF[0]),
|
||||
// "nb_antennas_rx too large");
|
||||
ru->prach_rxsigF = (int16_t**)malloc(ru->nb_rx * sizeof(int16_t*));
|
||||
|
||||
for (i=0; i<ru->nb_rx; i++) {
|
||||
// largest size for PRACH FFT is 4x98304 (16*24576)
|
||||
ru->prach_rxsigF[i] = (int16_t*)malloc16_clear( 4*98304*2*sizeof(int16_t) );
|
||||
LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,ru->prach_rxsigF[i]);
|
||||
for (j=0;j<NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX;j++) {
|
||||
ru->prach_rxsigF[j] = (int16_t**)malloc(ru->nb_rx * sizeof(int16_t*));
|
||||
|
||||
for (i=0; i<ru->nb_rx; i++) {
|
||||
// largest size for PRACH FFT is 4x98304 (16*24576)
|
||||
ru->prach_rxsigF[j][i] = (int16_t*)malloc16_clear( 4*98304*2*sizeof(int16_t) );
|
||||
LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,ru->prach_rxsigF[j][i]);
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(RC.nb_nr_L1_inst <= NUMBER_OF_eNB_MAX,"gNB instances %d > %d\n",
|
||||
@@ -186,10 +188,12 @@ void nr_phy_free_RU(RU_t *ru)
|
||||
for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdataF[i]);
|
||||
free_and_zero(ru->common.rxdataF);
|
||||
|
||||
for (i = 0; i < ru->nb_rx; i++) {
|
||||
free_and_zero(ru->prach_rxsigF[i]);
|
||||
for (j=0;j<NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX;j++) {
|
||||
for (i = 0; i < ru->nb_rx; i++) {
|
||||
free_and_zero(ru->prach_rxsigF[j][i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < RC.nb_nr_L1_inst; i++) {
|
||||
for (p = 0; p < 15; p++) {
|
||||
for (j=0; j<ru->nb_tx; j++) free_and_zero(ru->beam_weights[i][p][j]);
|
||||
|
||||
@@ -49,7 +49,7 @@ void send_IF4p5(RU_t *ru,
|
||||
LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
|
||||
int32_t **txdataF = ru->common.txdataF_BF;
|
||||
int32_t **rxdataF = ru->common.rxdataF;
|
||||
int16_t **prach_rxsigF = ru->prach_rxsigF;
|
||||
int16_t **prach_rxsigF = ru->prach_rxsigF[0];
|
||||
int16_t ***prach_rxsigF_br = ru->prach_rxsigF_br;
|
||||
void *tx_buffer = ru->ifbuffer.tx[subframe&1];
|
||||
void *tx_buffer_prach = ru->ifbuffer.tx_prach;
|
||||
@@ -276,7 +276,7 @@ void recv_IF4p5(RU_t *ru,
|
||||
LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
|
||||
int32_t **txdataF = ru->common.txdataF_BF;
|
||||
int32_t **rxdataF = ru->common.rxdataF;
|
||||
int16_t **prach_rxsigF = ru->prach_rxsigF;
|
||||
int16_t **prach_rxsigF = ru->prach_rxsigF[0];
|
||||
int16_t ***prach_rxsigF_br = ru->prach_rxsigF_br;
|
||||
void *rx_buffer = ru->ifbuffer.rx;
|
||||
uint16_t element_id;
|
||||
|
||||
@@ -167,7 +167,7 @@ void rx_prach0(PHY_VARS_eNB *eNB,
|
||||
br_flag,ce_level,frame_prach,subframe,fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level],prach_ConfigIndex);
|
||||
}
|
||||
} else {
|
||||
rxsigF = ru->prach_rxsigF;
|
||||
rxsigF = ru->prach_rxsigF[0];
|
||||
|
||||
if (LOG_DEBUGFLAG(PRACH)) {
|
||||
if (((frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n",
|
||||
|
||||
@@ -64,37 +64,23 @@ void nr_pdcch_scrambling(uint32_t *in,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t nr_generate_dci_top(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu,
|
||||
nfapi_nr_dl_tti_pdcch_pdu *ul_dci_pdu,
|
||||
uint32_t **gold_pdcch_dmrs,
|
||||
int32_t *txdataF,
|
||||
int16_t amp,
|
||||
NR_DL_FRAME_PARMS frame_parms) {
|
||||
void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
|
||||
uint32_t **gold_pdcch_dmrs,
|
||||
int32_t *txdataF,
|
||||
int16_t amp,
|
||||
NR_DL_FRAME_PARMS frame_parms) {
|
||||
|
||||
int16_t mod_dmrs[NR_MAX_CSET_DURATION][NR_MAX_PDCCH_DMRS_LENGTH>>1] __attribute__((aligned(16))); // 3 for the max coreset duration
|
||||
uint16_t cset_start_sc;
|
||||
uint8_t cset_start_symb, cset_nsymb;
|
||||
int k,l,k_prime,dci_idx, dmrs_idx;
|
||||
/*First iteration: single DCI*/
|
||||
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15=NULL;
|
||||
|
||||
|
||||
// find coreset descriptor
|
||||
|
||||
int rb_offset;
|
||||
int n_rb;
|
||||
|
||||
AssertFatal(pdcch_pdu!=NULL || ul_dci_pdu!=NULL,"At least one pointer has to be !NULL\n");
|
||||
AssertFatal(pdcch_pdu==NULL || ul_dci_pdu==NULL,"Can't handle both DL and UL DCI in same slot\n");
|
||||
|
||||
|
||||
if (pdcch_pdu) pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu_rel15;
|
||||
else if (ul_dci_pdu) pdcch_pdu_rel15 = &ul_dci_pdu->pdcch_pdu_rel15;
|
||||
|
||||
nr_fill_cce_list(gNB,0,pdcch_pdu_rel15);
|
||||
|
||||
get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset);
|
||||
@@ -241,6 +227,25 @@ uint8_t nr_generate_dci_top(PHY_VARS_gNB *gNB,
|
||||
} // reg_idx
|
||||
|
||||
} // for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nr_generate_dci_top(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu,
|
||||
nfapi_nr_dl_tti_pdcch_pdu *ul_dci_pdu,
|
||||
uint32_t **gold_pdcch_dmrs,
|
||||
int32_t *txdataF,
|
||||
int16_t amp,
|
||||
NR_DL_FRAME_PARMS frame_parms) {
|
||||
|
||||
AssertFatal(pdcch_pdu!=NULL || ul_dci_pdu!=NULL,"At least one pointer has to be !NULL\n");
|
||||
|
||||
if (pdcch_pdu && ul_dci_pdu) {
|
||||
nr_generate_dci(gNB,&pdcch_pdu->pdcch_pdu_rel15,gold_pdcch_dmrs,txdataF,amp,frame_parms);
|
||||
nr_generate_dci(gNB,&ul_dci_pdu->pdcch_pdu_rel15,gold_pdcch_dmrs,txdataF,amp,frame_parms);
|
||||
}
|
||||
else if (pdcch_pdu)
|
||||
nr_generate_dci(gNB,&pdcch_pdu->pdcch_pdu_rel15,gold_pdcch_dmrs,txdataF,amp,frame_parms);
|
||||
else
|
||||
nr_generate_dci(gNB,&ul_dci_pdu->pdcch_pdu_rel15,gold_pdcch_dmrs,txdataF,amp,frame_parms);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ uint16_t nr_get_dci_size(nfapi_nr_dci_format_e format,
|
||||
nfapi_nr_rnti_type_e rnti_type,
|
||||
uint16_t N_RB);
|
||||
|
||||
uint8_t nr_generate_dci_top(PHY_VARS_gNB *gNB,
|
||||
void nr_generate_dci_top(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu,
|
||||
nfapi_nr_dl_tti_pdcch_pdu *ul_pdcch_pdu,
|
||||
uint32_t **gold_pdcch_dmrs,
|
||||
|
||||
@@ -37,31 +37,42 @@
|
||||
extern uint16_t prach_root_sequence_map_0_3[838];
|
||||
extern uint16_t prach_root_sequence_map_abc[138];
|
||||
extern uint16_t nr_du[838];
|
||||
extern const char *prachfmt[9];
|
||||
extern const char *prachfmt[];
|
||||
|
||||
void init_prach_list(PHY_VARS_gNB *gNB) {
|
||||
|
||||
AssertFatal(gNB!=NULL,"gNB is null\n");
|
||||
for (int i=0; i<NUMBER_OF_NR_PRACH_MAX; i++) gNB->prach_vars.list[i].frame=-1;
|
||||
for (int i=0; i<NUMBER_OF_NR_PRACH_MAX; i++){
|
||||
gNB->prach_vars.list[i].frame = -1;
|
||||
gNB->prach_vars.list[i].slot = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame,int slot, int numRA, find_type_t type) {
|
||||
void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id) {
|
||||
|
||||
uint16_t i;
|
||||
int16_t first_free_index=-1;
|
||||
gNB->prach_vars.list[prach_id].frame = -1;
|
||||
gNB->prach_vars.list[prach_id].slot = -1;
|
||||
|
||||
}
|
||||
|
||||
int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame, int slot, find_type_t type) {
|
||||
|
||||
AssertFatal(gNB!=NULL,"gNB is null\n");
|
||||
for (i=0; i<NUMBER_OF_NR_PRACH_MAX; i++) {
|
||||
LOG_D(PHY,"searching for PRACH in %d.%d with numRA %d: prach_index %d=> %d.%d numRA %d\n", frame,slot,numRA,i,
|
||||
gNB->prach_vars.list[i].frame,gNB->prach_vars.list[i].slot,gNB->prach_vars.list[i].pdu.num_ra);
|
||||
if ((gNB->prach_vars.list[i].frame == frame) &&
|
||||
(gNB->prach_vars.list[i].slot == slot) &&
|
||||
(gNB->prach_vars.list[i].pdu.num_ra == numRA)) return i;
|
||||
else if ((gNB->prach_vars.list[i].frame == -1) && (first_free_index==-1)) first_free_index=i;
|
||||
for (uint16_t i=0; i<NUMBER_OF_NR_PRACH_MAX; i++) {
|
||||
LOG_D(PHY,"searching for PRACH in %d.%d prach_index %d=> %d.%d\n", frame,slot,i,
|
||||
gNB->prach_vars.list[i].frame,gNB->prach_vars.list[i].slot);
|
||||
if((type == SEARCH_EXIST_OR_FREE) &&
|
||||
(gNB->prach_vars.list[i].frame == -1) &&
|
||||
(gNB->prach_vars.list[i].slot == -1)) {
|
||||
return i;
|
||||
}
|
||||
else if ((type == SEARCH_EXIST) &&
|
||||
(gNB->prach_vars.list[i].frame == frame) &&
|
||||
(gNB->prach_vars.list[i].slot == slot)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (type == SEARCH_EXIST) return -1;
|
||||
|
||||
return first_free_index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void nr_fill_prach(PHY_VARS_gNB *gNB,
|
||||
@@ -69,9 +80,9 @@ void nr_fill_prach(PHY_VARS_gNB *gNB,
|
||||
int Slot,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu) {
|
||||
|
||||
int prach_id = find_nr_prach(gNB,SFN,Slot,prach_pdu->num_ra,SEARCH_EXIST_OR_FREE);
|
||||
AssertFatal( (prach_id>=0) && (prach_id<NUMBER_OF_NR_PRACH_MAX),
|
||||
"illegal or no prach_id found!!! numRA %d prach_id %d\n",prach_pdu->num_ra,prach_id);
|
||||
int prach_id = find_nr_prach(gNB,SFN,Slot,SEARCH_EXIST_OR_FREE);
|
||||
AssertFatal( ((prach_id>=0) && (prach_id<NUMBER_OF_NR_PRACH_MAX)) || (prach_id < 0),
|
||||
"illegal or no prach_id found!!! prach_id %d\n",prach_id);
|
||||
|
||||
gNB->prach_vars.list[prach_id].frame=SFN;
|
||||
gNB->prach_vars.list[prach_id].slot=Slot;
|
||||
@@ -82,31 +93,35 @@ void nr_fill_prach(PHY_VARS_gNB *gNB,
|
||||
void init_prach_ru_list(RU_t *ru) {
|
||||
|
||||
AssertFatal(ru!=NULL,"ruis null\n");
|
||||
for (int i=0; i<NUMBER_OF_NR_RU_PRACH_MAX; i++) ru->prach_list[i].frame=-1;
|
||||
for (int i=0; i<NUMBER_OF_NR_RU_PRACH_MAX; i++) {
|
||||
ru->prach_list[i].frame = -1;
|
||||
ru->prach_list[i].slot = -1;
|
||||
}
|
||||
pthread_mutex_init(&ru->prach_list_mutex,NULL);
|
||||
}
|
||||
|
||||
int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type) {
|
||||
|
||||
uint16_t i;
|
||||
int16_t first_free_index=-1;
|
||||
|
||||
AssertFatal(ru!=NULL,"ru is null\n");
|
||||
pthread_mutex_lock(&ru->prach_list_mutex);
|
||||
for (i=0; i<NUMBER_OF_NR_RU_PRACH_MAX; i++) {
|
||||
for (uint16_t i=0; i<NUMBER_OF_NR_RU_PRACH_MAX; i++) {
|
||||
LOG_D(PHY,"searching for PRACH in %d.%d : prach_index %d=> %d.%d\n", frame,slot,i,
|
||||
ru->prach_list[i].frame,ru->prach_list[i].slot);
|
||||
if ((ru->prach_list[i].frame == frame) &&
|
||||
(ru->prach_list[i].slot == slot)) {
|
||||
if((type == SEARCH_EXIST_OR_FREE) &&
|
||||
(ru->prach_list[i].frame == -1) &&
|
||||
(ru->prach_list[i].slot == -1)) {
|
||||
pthread_mutex_unlock(&ru->prach_list_mutex);
|
||||
return i;
|
||||
}
|
||||
else if ((type == SEARCH_EXIST) &&
|
||||
(ru->prach_list[i].frame == frame) &&
|
||||
(ru->prach_list[i].slot == slot)) {
|
||||
pthread_mutex_unlock(&ru->prach_list_mutex);
|
||||
return i;
|
||||
}
|
||||
else if ((ru->prach_list[i].frame == -1) && (first_free_index==-1)) first_free_index=i;
|
||||
}
|
||||
pthread_mutex_unlock(&ru->prach_list_mutex);
|
||||
if (type == SEARCH_EXIST) return -1;
|
||||
|
||||
return first_free_index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void nr_fill_prach_ru(RU_t *ru,
|
||||
@@ -115,7 +130,7 @@ void nr_fill_prach_ru(RU_t *ru,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu) {
|
||||
|
||||
int prach_id = find_nr_prach_ru(ru,SFN,Slot,SEARCH_EXIST_OR_FREE);
|
||||
AssertFatal( (prach_id>=0) && (prach_id<NUMBER_OF_NR_PRACH_MAX),
|
||||
AssertFatal( ((prach_id>=0) && (prach_id<NUMBER_OF_NR_PRACH_MAX)) || (prach_id < 0) ,
|
||||
"illegal or no prach_id found!!! prach_id %d\n",prach_id);
|
||||
|
||||
pthread_mutex_lock(&ru->prach_list_mutex);
|
||||
@@ -124,6 +139,7 @@ void nr_fill_prach_ru(RU_t *ru,
|
||||
ru->prach_list[prach_id].fmt = prach_pdu->prach_format;
|
||||
ru->prach_list[prach_id].numRA = prach_pdu->num_ra;
|
||||
ru->prach_list[prach_id].prachStartSymbol = prach_pdu->prach_start_symbol;
|
||||
ru->prach_list[prach_id].num_prach_ocas = prach_pdu->num_prach_ocas;
|
||||
pthread_mutex_unlock(&ru->prach_list_mutex);
|
||||
|
||||
}
|
||||
@@ -132,7 +148,8 @@ void free_nr_ru_prach_entry(RU_t *ru,
|
||||
int prach_id) {
|
||||
|
||||
pthread_mutex_lock(&ru->prach_list_mutex);
|
||||
ru->prach_list[prach_id].frame=-1;
|
||||
ru->prach_list[prach_id].frame = -1;
|
||||
ru->prach_list[prach_id].slot = -1;
|
||||
pthread_mutex_unlock(&ru->prach_list_mutex);
|
||||
|
||||
}
|
||||
@@ -142,6 +159,7 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
int prachFormat,
|
||||
int numRA,
|
||||
int prachStartSymbol,
|
||||
int prachOccasion,
|
||||
int frame,
|
||||
int slot) {
|
||||
|
||||
@@ -156,15 +174,21 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
|
||||
int msg1_frequencystart = ru->config.prach_config.num_prach_fd_occasions_list[numRA].k1.value;
|
||||
|
||||
rxsigF = ru->prach_rxsigF;
|
||||
int sample_offset_slot = (prachStartSymbol==0?0:fp->ofdm_symbol_size*prachStartSymbol+fp->nb_prefix_samples0+fp->nb_prefix_samples*(prachStartSymbol-1));
|
||||
//to be checked for mu=0;
|
||||
|
||||
LOG_D(PHY,"frame %d, slot %d: doing rx_nr_prach_ru for format %d, numRA %d, prachStartSymbol %d, prachOccasion %d\n",frame,slot,prachFormat,numRA,prachStartSymbol,prachOccasion);
|
||||
|
||||
rxsigF = ru->prach_rxsigF[prachOccasion];
|
||||
|
||||
AssertFatal(ru->if_south == LOCAL_RF,"we shouldn't call this if if_south != LOCAL_RF\n");
|
||||
|
||||
for (int aa=0; aa<ru->nb_rx; aa++){
|
||||
if (prach_sequence_length == 0) slot2=(slot/fp->slots_per_subframe)*fp->slots_per_subframe;
|
||||
prach[aa] = (int16_t*)&ru->common.rxdata[aa][(slot2*fp->get_samples_per_slot(slot,fp))-ru->N_TA_offset];
|
||||
prach[aa] = (int16_t*)&ru->common.rxdata[aa][(slot2*fp->get_samples_per_slot(slot,fp))+sample_offset_slot-ru->N_TA_offset];
|
||||
}
|
||||
|
||||
|
||||
int dftlen=0;
|
||||
int mu = fp->numerology_index;
|
||||
int Ncp = 0;
|
||||
@@ -198,22 +222,24 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
ru->idx,frame,slot,prachfmt[prachFormat],msg1_frequencystart,prachStartSymbol);
|
||||
|
||||
switch (prachFormat) {
|
||||
case 0: //A1
|
||||
case 4: //A1
|
||||
Ncp = 288/(1<<mu);
|
||||
break;
|
||||
|
||||
case 1: //A2
|
||||
case 5: //A2
|
||||
Ncp = 576/(1<<mu);
|
||||
break;
|
||||
|
||||
case 2: //A3
|
||||
case 6: //A3
|
||||
Ncp = 864/(1<<mu);
|
||||
break;
|
||||
|
||||
case 3: //B1
|
||||
case 7: //B1
|
||||
Ncp = 216/(1<<mu);
|
||||
break;
|
||||
|
||||
/*
|
||||
// B2 and B3 do not exist in FAPI
|
||||
case 4: //B2
|
||||
Ncp = 360/(1<<mu);
|
||||
break;
|
||||
@@ -221,16 +247,16 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
case 5: //B3
|
||||
Ncp = 504/(1<<mu);
|
||||
break;
|
||||
|
||||
case 6: //B4
|
||||
*/
|
||||
case 8: //B4
|
||||
Ncp = 936/(1<<mu);
|
||||
break;
|
||||
|
||||
case 7: //C0
|
||||
case 9: //C0
|
||||
Ncp = 1240/(1<<mu);
|
||||
break;
|
||||
|
||||
case 8: //C2
|
||||
case 10: //C2
|
||||
Ncp = 2048/(1<<mu);
|
||||
break;
|
||||
|
||||
@@ -265,7 +291,8 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
if (k<0) k+=(fp->ofdm_symbol_size);
|
||||
|
||||
k*=K;
|
||||
k+=kbar;
|
||||
k+=kbar;
|
||||
|
||||
int reps=1;
|
||||
|
||||
for (int aa=0; aa<ru->nb_rx; aa++) {
|
||||
@@ -308,21 +335,21 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
else if (mu==1) {
|
||||
dftlen=2048;
|
||||
dft(DFT_2048,prach2,rxsigF[aa],1);
|
||||
if (prachFormat != 7) { // !=C0
|
||||
if (prachFormat != 9/*C0*/) {
|
||||
dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1);
|
||||
reps++;
|
||||
}
|
||||
if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) {
|
||||
if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {
|
||||
dft(DFT_2048,prach2+4096*2,rxsigF[aa]+4096*2,1);
|
||||
dft(DFT_2048,prach2+4096*3,rxsigF[aa]+4096*3,1);
|
||||
reps+=2;
|
||||
}
|
||||
if (prachFormat == 2 || prachFormat == 5 || prachFormat == 6) {
|
||||
if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {
|
||||
dft(DFT_2048,prach2+4096*4,rxsigF[aa]+4096*4,1);
|
||||
dft(DFT_2048,prach2+4096*5,rxsigF[aa]+4096*5,1);
|
||||
reps+=2;
|
||||
}
|
||||
if (prachFormat == 6) {
|
||||
if (prachFormat == 8/*B4*/) {
|
||||
for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1);
|
||||
reps+=6;
|
||||
}
|
||||
@@ -363,22 +390,22 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
else if (mu==1) {
|
||||
dftlen=1536;
|
||||
dft(DFT_1536,prach2,rxsigF[aa],1);
|
||||
if (prachFormat != 7) {
|
||||
if (prachFormat != 9/*C0*/) {
|
||||
dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1);
|
||||
reps++;
|
||||
}
|
||||
|
||||
if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) {
|
||||
if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {
|
||||
dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1);
|
||||
dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1);
|
||||
reps+=2;
|
||||
}
|
||||
if (prachFormat == 2 || prachFormat == 5 || prachFormat == 6) {
|
||||
if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {
|
||||
dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1);
|
||||
dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1);
|
||||
reps+=2;
|
||||
}
|
||||
if (prachFormat == 6) {
|
||||
if (prachFormat == 8/*B4*/) {
|
||||
for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1);
|
||||
reps+=6;
|
||||
}
|
||||
@@ -423,22 +450,22 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
else if (mu==1) {
|
||||
dftlen=4096;
|
||||
dft(DFT_4096,prach2,rxsigF[aa],1);
|
||||
if (prachFormat != 7) { //!=C0
|
||||
if (prachFormat != 9/*C0*/) {
|
||||
dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1);
|
||||
reps++;
|
||||
}
|
||||
|
||||
if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) {
|
||||
if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {
|
||||
dft(DFT_4096,prach2+8192*2,rxsigF[aa]+8192*2,1);
|
||||
dft(DFT_4096,prach2+8192*3,rxsigF[aa]+8192*3,1);
|
||||
reps+=2;
|
||||
}
|
||||
if (prachFormat == 2 || prachFormat == 5 || prachFormat == 6) {
|
||||
if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {
|
||||
dft(DFT_4096,prach2+8192*4,rxsigF[aa]+8192*4,1);
|
||||
dft(DFT_4096,prach2+8192*5,rxsigF[aa]+8192*5,1);
|
||||
reps+=2;
|
||||
}
|
||||
if (prachFormat == 6) {
|
||||
if (prachFormat == 8/*B4*/) {
|
||||
for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1);
|
||||
reps+=6;
|
||||
}
|
||||
@@ -475,22 +502,22 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
else if (mu==1) {
|
||||
dftlen=3072;
|
||||
dft(DFT_3072,prach2,rxsigF[aa],1);
|
||||
if (prachFormat != 7) { //!=C0
|
||||
if (prachFormat != 9/*C0*/) {
|
||||
dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1);
|
||||
reps++;
|
||||
}
|
||||
|
||||
if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) {
|
||||
if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {
|
||||
dft(DFT_3072,prach2+6144*2,rxsigF[aa]+6144*2,1);
|
||||
dft(DFT_3072,prach2+6144*3,rxsigF[aa]+6144*3,1);
|
||||
reps+=2;
|
||||
}
|
||||
if (prachFormat == 2 || prachFormat == 5 || prachFormat == 6) {
|
||||
if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {
|
||||
dft(DFT_3072,prach2+6144*4,rxsigF[aa]+6144*4,1);
|
||||
dft(DFT_3072,prach2+6144*5,rxsigF[aa]+6144*5,1);
|
||||
reps+=2;
|
||||
}
|
||||
if (prachFormat == 6) {
|
||||
if (prachFormat == 8/*B4*/) {
|
||||
for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1);
|
||||
reps+=6;
|
||||
}
|
||||
@@ -515,13 +542,13 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
for (int i=1;i<reps;i++) rxsigF_tmp[j] += rxsigF2[k2+(i*dftlen<<1)];
|
||||
}
|
||||
memcpy((void*)rxsigF2,(void *)rxsigF_tmp,N_ZC<<2);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void rx_nr_prach(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu,
|
||||
int prachOccasion,
|
||||
int frame,
|
||||
int subframe,
|
||||
uint16_t *max_preamble,
|
||||
@@ -570,13 +597,11 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
|
||||
fp = &gNB->frame_parms;
|
||||
|
||||
nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value;
|
||||
|
||||
rootSequenceIndex = cfg->num_prach_fd_occasions_list[0].prach_root_sequence_index.value;
|
||||
numrootSequenceIndex = cfg->num_prach_fd_occasions_list[0].num_root_sequences.value;
|
||||
rootSequenceIndex = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].prach_root_sequence_index.value;
|
||||
numrootSequenceIndex = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].num_root_sequences.value;
|
||||
NCS = prach_pdu->num_cs;//cfg->num_prach_fd_occasions_list[0].prach_zero_corr_conf.value;
|
||||
int prach_sequence_length = cfg->prach_sequence_length.value;
|
||||
|
||||
int msg1_frequencystart = cfg->num_prach_fd_occasions_list[0].k1.value;
|
||||
int msg1_frequencystart = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].k1.value;
|
||||
// int num_unused_root_sequences = cfg->num_prach_fd_occasions_list[0].num_unused_root_sequences.value;
|
||||
// cfg->num_prach_fd_occasions_list[0].unused_root_sequences_list
|
||||
|
||||
@@ -585,7 +610,7 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
|
||||
uint8_t prach_fmt = prach_pdu->prach_format;
|
||||
uint16_t N_ZC = (prach_sequence_length==0)?839:139;
|
||||
|
||||
LOG_D(PHY,"L1 PRACH RX: rooSequenceIndex %d, numRootSeqeuences %d, NCS %d, N_ZC %d \n", rootSequenceIndex,numrootSequenceIndex,NCS,N_ZC);
|
||||
LOG_D(PHY,"L1 PRACH RX: rooSequenceIndex %d, numRootSeqeuences %d, NCS %d, N_ZC %d, format %d \n",rootSequenceIndex,numrootSequenceIndex,NCS,N_ZC,prach_fmt);
|
||||
|
||||
prach_ifft = gNB->prach_vars.prach_ifft;
|
||||
prachF = gNB->prach_vars.prachF;
|
||||
|
||||
@@ -288,6 +288,7 @@ void nr_fill_prach(PHY_VARS_gNB *gNB,
|
||||
|
||||
void rx_nr_prach(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu,
|
||||
int prachOccasion,
|
||||
int frame,
|
||||
int subframe,
|
||||
uint16_t *max_preamble,
|
||||
@@ -298,6 +299,7 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
int prach_fmt,
|
||||
int numRA,
|
||||
int prachStartSymbol,
|
||||
int prachOccasion,
|
||||
int frame,
|
||||
int subframe);
|
||||
|
||||
@@ -306,7 +308,7 @@ void nr_fill_prach_ru(RU_t *ru,
|
||||
int Slot,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu);
|
||||
|
||||
int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame,int slot, int numRA, find_type_t type);
|
||||
int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame,int slot, find_type_t type);
|
||||
int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type);
|
||||
|
||||
NR_gNB_PUCCH_t *new_gNB_pucch(void);
|
||||
@@ -325,7 +327,7 @@ int nr_find_pucch(uint16_t rnti,
|
||||
void init_prach_list(PHY_VARS_gNB *gNB);
|
||||
void init_prach_ru_list(RU_t *ru);
|
||||
void free_nr_ru_prach_entry(RU_t *ru, int prach_id);
|
||||
|
||||
void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id);
|
||||
|
||||
void nr_decode_pucch1(int32_t **rxdataF,
|
||||
pucch_GroupHopping_t pucch_GroupHopping,
|
||||
|
||||
@@ -48,8 +48,7 @@ extern uint16_t prach_root_sequence_map_0_3[838];
|
||||
extern uint16_t prach_root_sequence_map_abc[138];
|
||||
extern uint16_t nr_du[838];
|
||||
extern int16_t nr_ru[2*839];
|
||||
extern const char *prachfmt[9];
|
||||
extern const char *prachfmt03[4];
|
||||
extern const char *prachfmt[];
|
||||
|
||||
// Note:
|
||||
// - prach_fmt_id is an ID used to map to the corresponding PRACH format value in prachfmt
|
||||
@@ -181,14 +180,14 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
}
|
||||
|
||||
// now generate PRACH signal
|
||||
#ifdef NR_PRACH_DEBUG
|
||||
#ifdef NR_PRACH_DEBUG
|
||||
if (NCS>0)
|
||||
LOG_I(PHY, "PRACH [UE %d] generate PRACH in slot %d for RootSeqIndex %d, Preamble Index %d, PRACH Format %s, NCS %d (N_ZC %d): Preamble_offset %d, Preamble_shift %d msg1 frequency start %d\n",
|
||||
Mod_id,
|
||||
slot,
|
||||
rootSequenceIndex,
|
||||
preamble_index,
|
||||
prach_sequence_length == 0 ? prachfmt03[prach_fmt_id] : prachfmt[prach_fmt_id],
|
||||
prachfmt[prach_fmt_id],
|
||||
NCS,
|
||||
N_ZC,
|
||||
preamble_offset,
|
||||
@@ -362,31 +361,33 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
} else {
|
||||
|
||||
switch (prach_fmt_id) {
|
||||
case 0: //A1
|
||||
case 4: //A1
|
||||
Ncp = 288/(1<<mu);
|
||||
break;
|
||||
case 1: //A2
|
||||
case 5: //A2
|
||||
Ncp = 576/(1<<mu);
|
||||
break;
|
||||
case 2: //A3
|
||||
case 6: //A3
|
||||
Ncp = 864/(1<<mu);
|
||||
break;
|
||||
case 3: //B1
|
||||
case 7: //B1
|
||||
Ncp = 216/(1<<mu);
|
||||
break;
|
||||
/*
|
||||
case 4: //B2
|
||||
Ncp = 360/(1<<mu);
|
||||
break;
|
||||
case 5: //B3
|
||||
Ncp = 504/(1<<mu);
|
||||
break;
|
||||
case 6: //B4
|
||||
*/
|
||||
case 8: //B4
|
||||
Ncp = 936/(1<<mu);
|
||||
break;
|
||||
case 7: //C0
|
||||
case 9: //C0
|
||||
Ncp = 1240/(1<<mu);
|
||||
break;
|
||||
case 8: //C2
|
||||
case 10: //C2
|
||||
Ncp = 2048/(1<<mu);
|
||||
break;
|
||||
default:
|
||||
@@ -440,19 +441,19 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
prach_len = (12288*4)+Ncp;
|
||||
}
|
||||
} else { // short PRACH sequence
|
||||
if (prach_fmt_id == 0 || prach_fmt_id == 3 || prach_fmt_id == 7) {
|
||||
if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) {
|
||||
Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_2048,prachF,prach2,1);
|
||||
// here we have |empty | Prach2048 |
|
||||
if (prach_fmt_id != 7) {
|
||||
if (prach_fmt_id != 9) {
|
||||
memmove(prach2+(2048<<1),prach2,(2048<<2));
|
||||
prach_len = (2048*2)+Ncp;
|
||||
}
|
||||
else prach_len = (2048*1)+Ncp;
|
||||
memmove(prach,prach+(2048<<1),(Ncp<<2));
|
||||
// here we have |Prefix | Prach2048 | Prach2048 (if ! 0xc0) |
|
||||
} else if (prach_fmt_id == 1 || prach_fmt_id == 4) { // 6x2048
|
||||
} else if (prach_fmt_id == 5) { // 6x2048
|
||||
Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_2048,prachF,prach2,1);
|
||||
@@ -464,7 +465,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
memmove(prach,prach+(2048<<1),(Ncp<<2));
|
||||
// here we have |Prefix | Prach2048 |
|
||||
prach_len = (2048*4)+Ncp;
|
||||
} else if (prach_fmt_id == 2 || prach_fmt_id == 5) { // 6x2048
|
||||
} else if (prach_fmt_id == 6) { // 6x2048
|
||||
Ncp+=32;
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_2048,prachF,prach2,1);
|
||||
@@ -478,7 +479,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
memmove(prach,prach+(2048<<1),(Ncp<<2));
|
||||
// here we have |Prefix | Prach2048 |
|
||||
prach_len = (2048*6)+Ncp;
|
||||
} else if (prach_fmt_id == 6) { // 12x2048
|
||||
} else if (prach_fmt_id == 8) { // 12x2048
|
||||
Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_2048,prachF,prach2,1);
|
||||
@@ -533,12 +534,12 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
prach_len = (9216*4)+Ncp;
|
||||
}
|
||||
} else { // short sequence
|
||||
if (prach_fmt_id == 0 || prach_fmt_id == 3 || prach_fmt_id == 7) {
|
||||
if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) {
|
||||
Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_1536,prachF,prach2,1);
|
||||
// here we have |empty | Prach1536 |
|
||||
if (prach_fmt_id != 7) {
|
||||
if (prach_fmt_id != 9) {
|
||||
memmove(prach2+(1536<<1),prach2,(1536<<2));
|
||||
prach_len = (1536*2)+Ncp;
|
||||
} else prach_len = (1536*1)+Ncp;
|
||||
@@ -546,7 +547,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
memmove(prach,prach+(1536<<1),(Ncp<<2));
|
||||
// here we have |Prefix | Prach1536 | Prach1536 (if ! 0xc0) |
|
||||
|
||||
} else if (prach_fmt_id == 1 || prach_fmt_id == 4) { // 6x1536
|
||||
} else if (prach_fmt_id == 5) { // 6x1536
|
||||
|
||||
Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
@@ -559,7 +560,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
memmove(prach,prach+(1536<<1),(Ncp<<2));
|
||||
// here we have |Prefix | Prach1536 |
|
||||
prach_len = (1536*4)+Ncp;
|
||||
} else if (prach_fmt_id == 2 || prach_fmt_id == 5) { // 6x1536
|
||||
} else if (prach_fmt_id == 6) { // 6x1536
|
||||
Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_1536,prachF,prach2,1);
|
||||
@@ -573,7 +574,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
memmove(prach,prach+(1536<<1),(Ncp<<2));
|
||||
// here we have |Prefix | Prach1536 |
|
||||
prach_len = (1536*6)+Ncp;
|
||||
} else if (prach_fmt_id == 6) { // 12x1536
|
||||
} else if (prach_fmt_id == 8) { // 12x1536
|
||||
Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_1536,prachF,prach2,1);
|
||||
@@ -630,18 +631,18 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
prach_len = (24576*4)+Ncp;
|
||||
}
|
||||
} else { // short sequence
|
||||
if (prach_fmt_id == 0 || prach_fmt_id == 3 || prach_fmt_id == 7) {
|
||||
if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) {
|
||||
Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_4096,prachF,prach2,1);
|
||||
// here we have |empty | Prach4096 |
|
||||
if (prach_fmt_id != 7) {
|
||||
if (prach_fmt_id != 9) {
|
||||
memmove(prach2+(4096<<1),prach2,(4096<<2));
|
||||
prach_len = (4096*2)+Ncp;
|
||||
} else prach_len = (4096*1)+Ncp;
|
||||
memmove(prach,prach+(4096<<1),(Ncp<<2));
|
||||
// here we have |Prefix | Prach4096 | Prach4096 (if ! 0xc0) |
|
||||
} else if (prach_fmt_id == 1 || prach_fmt_id == 4) { // 4x4096
|
||||
} else if (prach_fmt_id == 5) { // 4x4096
|
||||
Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_4096,prachF,prach2,1);
|
||||
@@ -653,7 +654,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
memmove(prach,prach+(4096<<1),(Ncp<<2));
|
||||
// here we have |Prefix | Prach4096 |
|
||||
prach_len = (4096*4)+Ncp;
|
||||
} else if (prach_fmt_id == 2 || prach_fmt_id == 5) { // 6x4096
|
||||
} else if (prach_fmt_id == 6) { // 6x4096
|
||||
Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_4096,prachF,prach2,1);
|
||||
@@ -667,7 +668,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
memmove(prach,prach+(4096<<1),(Ncp<<2));
|
||||
// here we have |Prefix | Prach4096 |
|
||||
prach_len = (4096*6)+Ncp;
|
||||
} else if (prach_fmt_id == 6) { // 12x4096
|
||||
} else if (prach_fmt_id == 8) { // 12x4096
|
||||
Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_4096,prachF,prach2,1);
|
||||
@@ -722,18 +723,18 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
prach_len = (18432*4)+Ncp;
|
||||
}
|
||||
} else { // short sequence
|
||||
if (prach_fmt_id == 0 || prach_fmt_id == 3 || prach_fmt_id == 7) {
|
||||
if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) {
|
||||
Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_3072,prachF,prach2,1);
|
||||
// here we have |empty | Prach3072 |
|
||||
if (prach_fmt_id != 7) {
|
||||
if (prach_fmt_id != 9) {
|
||||
memmove(prach2+(3072<<1),prach2,(3072<<2));
|
||||
prach_len = (3072*2)+Ncp;
|
||||
} else prach_len = (3072*1)+Ncp;
|
||||
memmove(prach,prach+(3072<<1),(Ncp<<2));
|
||||
// here we have |Prefix | Prach3072 | Prach3072 (if ! 0xc0) |
|
||||
} else if (prach_fmt_id == 2 || prach_fmt_id == 5) { // 6x3072
|
||||
} else if (prach_fmt_id == 6) { // 6x3072
|
||||
Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_3072,prachF,prach2,1);
|
||||
@@ -747,7 +748,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
memmove(prach,prach+(3072<<1),(Ncp<<2));
|
||||
// here we have |Prefix | Prach3072 |
|
||||
prach_len = (3072*6)+Ncp;
|
||||
} else if (prach_fmt_id == 1 || prach_fmt_id == 4) { // 4x3072
|
||||
} else if (prach_fmt_id == 5) { // 4x3072
|
||||
Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
|
||||
prach2 = prach+(Ncp<<1);
|
||||
idft(IDFT_3072,prachF,prach2,1);
|
||||
|
||||
@@ -191,9 +191,11 @@ typedef struct {
|
||||
int fmt;
|
||||
int numRA;
|
||||
int prachStartSymbol;
|
||||
int num_prach_ocas;
|
||||
} RU_PRACH_list_t;
|
||||
|
||||
#define NUMBER_OF_NR_RU_PRACH_MAX 8
|
||||
#define NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX 12
|
||||
|
||||
typedef struct RU_proc_t_s {
|
||||
/// Pointer to associated RU descriptor
|
||||
@@ -594,8 +596,8 @@ typedef struct RU_t_s {
|
||||
RU_PRACH_list_t prach_list[NUMBER_OF_NR_RU_PRACH_MAX];
|
||||
/// mutex for prach_list access
|
||||
pthread_mutex_t prach_list_mutex;
|
||||
/// received frequency-domain signal for PRACH (IF4p5 RRU)
|
||||
int16_t **prach_rxsigF;
|
||||
/// received frequency-domain signal for PRACH (IF4p5 RRU)
|
||||
int16_t **prach_rxsigF[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX];
|
||||
/// received frequency-domain signal for PRACH BR (IF4p5 RRU)
|
||||
int16_t **prach_rxsigF_br[4];
|
||||
/// sequence number for IF5
|
||||
|
||||
@@ -80,7 +80,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,
|
||||
ru=eNB->RU_list[i];
|
||||
|
||||
for (ru_aa=0,aa=0; ru_aa<ru->nb_rx; ru_aa++,aa++) {
|
||||
eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa];
|
||||
eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[0][ru_aa];
|
||||
int ce_level;
|
||||
|
||||
if (br_flag==1)
|
||||
|
||||
@@ -52,87 +52,114 @@ extern uint8_t nfapi_mode;
|
||||
extern int oai_nfapi_nr_rach_ind(nfapi_rach_indication_t *rach_ind);
|
||||
|
||||
|
||||
void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu) {
|
||||
void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot) {
|
||||
|
||||
uint16_t max_preamble[4]={0},max_preamble_energy[4]={0},max_preamble_delay[4]={0};
|
||||
uint16_t i;
|
||||
|
||||
|
||||
gNB->UL_INFO.rach_ind.number_of_pdus=0;
|
||||
|
||||
uint8_t pdu_index = 0;
|
||||
RU_t *ru;
|
||||
int aa=0;
|
||||
int ru_aa;
|
||||
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
|
||||
gNB->UL_INFO.rach_ind.sfn = frame;
|
||||
gNB->UL_INFO.rach_ind.slot = slot;
|
||||
gNB->UL_INFO.rach_ind.pdu_list = gNB->prach_pdu_indication_list;
|
||||
gNB->UL_INFO.rach_ind.number_of_pdus = 0;
|
||||
|
||||
ru=gNB->RU_list[0];
|
||||
|
||||
int prach_id=find_nr_prach(gNB,frame,slot,SEARCH_EXIST);
|
||||
|
||||
if (prach_id>=0) {
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_vars.list[prach_id].pdu;
|
||||
uint8_t prachStartSymbol;
|
||||
uint8_t N_dur = get_nr_prach_duration(prach_pdu->prach_format);
|
||||
|
||||
/*
|
||||
uint16_t format,RA_sfn_index;
|
||||
uint8_t start_symbol,N_t_slot,N_dur,N_RA_slot,config_period;
|
||||
|
||||
for (i=0;i<gNB->num_RU;i++) {
|
||||
ru=gNB->RU_list[i];
|
||||
for (ru_aa=0,aa=0;ru_aa<ru->nb_rx;ru_aa++,aa++) {
|
||||
gNB->prach_vars.rxsigF[aa] = gNB->RU_list[i]->prach_rxsigF[ru_aa];
|
||||
}
|
||||
}
|
||||
get_nr_prach_info_from_index(gNB->gNB_config.prach_config.prach_ConfigurationIndex.value,
|
||||
frame,slot,
|
||||
gNB->gNB_config.carrier_config.dl_frequency.value,
|
||||
gNB->frame_parms.numerology_index,
|
||||
gNB->frame_parms.frame_type,
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur,
|
||||
&RA_sfn_index,
|
||||
&N_RA_slot,
|
||||
&config_period);
|
||||
*/
|
||||
|
||||
for(int prach_oc = 0; prach_oc < prach_pdu->num_prach_ocas; prach_oc++) {
|
||||
for (ru_aa=0,aa=0;ru_aa<ru->nb_rx;ru_aa++,aa++) {
|
||||
gNB->prach_vars.rxsigF[aa] = ru->prach_rxsigF[prach_oc][ru_aa];
|
||||
}
|
||||
|
||||
rx_nr_prach(gNB,
|
||||
prach_pdu,
|
||||
prachStartSymbol = prach_pdu->prach_start_symbol+prach_oc*N_dur;
|
||||
//comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}.
|
||||
|
||||
rx_nr_prach(gNB,
|
||||
prach_pdu,
|
||||
prach_oc,
|
||||
frame,
|
||||
slot,
|
||||
&max_preamble[0],
|
||||
&max_preamble_energy[0],
|
||||
&max_preamble_delay[0]
|
||||
);
|
||||
free_nr_prach_entry(gNB,prach_id);
|
||||
LOG_D(PHY,"[RAPROC] Frame %d, slot %d, occasion %d (prachStartSymbol %d) : Most likely preamble %d, energy %d dB delay %d (prach_energy counter %d)\n",
|
||||
frame,slot,prach_oc,prachStartSymbol,
|
||||
max_preamble[0],
|
||||
max_preamble_energy[0]/10,
|
||||
max_preamble_delay[0],
|
||||
gNB->prach_energy_counter);
|
||||
|
||||
if ((gNB->prach_energy_counter == 100) &&
|
||||
(max_preamble_energy[0] > gNB->measurements.prach_I0+100)) {
|
||||
|
||||
LOG_I(PHY,"[gNB %d][RAPROC] Frame %d, slot %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d start symbol %u freq index %u\n",
|
||||
gNB->Mod_id,
|
||||
frame,
|
||||
slot,
|
||||
&max_preamble[0],
|
||||
&max_preamble_energy[0],
|
||||
&max_preamble_delay[0]
|
||||
);
|
||||
|
||||
LOG_D(PHY,"[RAPROC] Frame %d, slot %d : Most likely preamble %d, energy %d dB delay %d (prach_energy counter %d)\n",
|
||||
frame,slot,
|
||||
max_preamble[0],
|
||||
max_preamble_energy[0]/10,
|
||||
max_preamble_delay[0],
|
||||
gNB->prach_energy_counter);
|
||||
|
||||
if ((gNB->prach_energy_counter == 100) &&
|
||||
(max_preamble_energy[0] > gNB->measurements.prach_I0+100)) {
|
||||
|
||||
LOG_I(PHY,"[gNB %d][RAPROC] Frame %d, slot %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n",
|
||||
gNB->Mod_id,
|
||||
frame,
|
||||
slot,
|
||||
max_preamble[0],
|
||||
max_preamble_energy[0]/10,
|
||||
max_preamble_energy[0]%10,
|
||||
max_preamble_delay[0]);
|
||||
|
||||
T(T_ENB_PHY_INITIATE_RA_PROCEDURE, T_INT(gNB->Mod_id), T_INT(frame), T_INT(slot),
|
||||
T_INT(max_preamble[0]), T_INT(max_preamble_energy[0]), T_INT(max_preamble_delay[0]));
|
||||
|
||||
|
||||
gNB->UL_INFO.rach_ind.number_of_pdus = 1;
|
||||
gNB->UL_INFO.rach_ind.pdu_list = &gNB->prach_pdu_indication_list[0];
|
||||
gNB->UL_INFO.rach_ind.sfn = frame;
|
||||
gNB->UL_INFO.rach_ind.slot = slot;
|
||||
|
||||
gNB->prach_pdu_indication_list[0].phy_cell_id = gNB->gNB_config.cell_config.phy_cell_id.value;
|
||||
gNB->prach_pdu_indication_list[0].symbol_index = prach_pdu->prach_start_symbol; // FIXME to be changed for multi-ssb (this is only the start symbol of first occasion)
|
||||
gNB->prach_pdu_indication_list[0].slot_index = slot;
|
||||
gNB->prach_pdu_indication_list[0].freq_index = prach_pdu->num_ra;
|
||||
gNB->prach_pdu_indication_list[0].avg_rssi = (max_preamble_energy[0]<631) ? (128+(max_preamble_energy[0]/5)) : 254;
|
||||
gNB->prach_pdu_indication_list[0].avg_snr = 0xff; // invalid for now
|
||||
|
||||
|
||||
gNB->prach_pdu_indication_list[0].num_preamble = 1;
|
||||
gNB->prach_pdu_indication_list[0].preamble_list = gNB->preamble_list;
|
||||
gNB->prach_pdu_indication_list[0].preamble_list[0].preamble_index = max_preamble[0];
|
||||
gNB->prach_pdu_indication_list[0].preamble_list[0].timing_advance = max_preamble_delay[0];
|
||||
gNB->prach_pdu_indication_list[0].preamble_list[0].preamble_pwr = 0xffffffff;
|
||||
}
|
||||
gNB->measurements.prach_I0 = ((gNB->measurements.prach_I0*900)>>10) + ((max_preamble_energy[0]*124)>>10);
|
||||
if (frame==0) LOG_I(PHY,"prach_I0 = %d.%d dB\n",gNB->measurements.prach_I0/10,gNB->measurements.prach_I0%10);
|
||||
if (gNB->prach_energy_counter < 100) gNB->prach_energy_counter++;
|
||||
|
||||
|
||||
max_preamble[0],
|
||||
max_preamble_energy[0]/10,
|
||||
max_preamble_energy[0]%10,
|
||||
max_preamble_delay[0],
|
||||
prachStartSymbol,
|
||||
prach_pdu->num_ra);
|
||||
|
||||
T(T_ENB_PHY_INITIATE_RA_PROCEDURE, T_INT(gNB->Mod_id), T_INT(frame), T_INT(slot),
|
||||
T_INT(max_preamble[0]), T_INT(max_preamble_energy[0]), T_INT(max_preamble_delay[0]));
|
||||
|
||||
|
||||
gNB->UL_INFO.rach_ind.number_of_pdus += 1;
|
||||
|
||||
gNB->prach_pdu_indication_list[pdu_index].phy_cell_id = gNB->gNB_config.cell_config.phy_cell_id.value;
|
||||
gNB->prach_pdu_indication_list[pdu_index].symbol_index = prachStartSymbol;
|
||||
gNB->prach_pdu_indication_list[pdu_index].slot_index = slot;
|
||||
gNB->prach_pdu_indication_list[pdu_index].freq_index = prach_pdu->num_ra;
|
||||
gNB->prach_pdu_indication_list[pdu_index].avg_rssi = (max_preamble_energy[0]<631) ? (128+(max_preamble_energy[0]/5)) : 254;
|
||||
gNB->prach_pdu_indication_list[pdu_index].avg_snr = 0xff; // invalid for now
|
||||
|
||||
gNB->prach_pdu_indication_list[pdu_index].num_preamble = 1;
|
||||
gNB->prach_pdu_indication_list[pdu_index].preamble_list = gNB->preamble_list;
|
||||
gNB->prach_pdu_indication_list[pdu_index].preamble_list[0].preamble_index = max_preamble[0];
|
||||
gNB->prach_pdu_indication_list[pdu_index].preamble_list[0].timing_advance = max_preamble_delay[0];
|
||||
gNB->prach_pdu_indication_list[pdu_index].preamble_list[0].preamble_pwr = 0xffffffff;
|
||||
pdu_index++;
|
||||
}
|
||||
gNB->measurements.prach_I0 = ((gNB->measurements.prach_I0*900)>>10) + ((max_preamble_energy[0]*124)>>10);
|
||||
if (frame==0) LOG_I(PHY,"prach_I0 = %d.%d dB\n",gNB->measurements.prach_I0/10,gNB->measurements.prach_I0%10);
|
||||
if (gNB->prach_energy_counter < 100) gNB->prach_energy_counter++;
|
||||
} //if prach_id>0
|
||||
} //for NUMBER_OF_NR_PRACH_OCCASION_MAX
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
|
||||
}
|
||||
|
||||
|
||||
@@ -536,7 +536,7 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
|
||||
(pucch->frame == frame_rx) &&
|
||||
(pucch->slot == slot_rx) ) {
|
||||
|
||||
nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch[i].pucch_pdu;
|
||||
nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu;
|
||||
uint16_t num_ucis;
|
||||
|
||||
switch (pucch_pdu->format_type) {
|
||||
|
||||
@@ -39,7 +39,7 @@ void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_scf_t *cfg, NR_DL_FRAME
|
||||
void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, int frame_tx, int slot_tx, int do_meas);
|
||||
void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx);
|
||||
void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx);
|
||||
void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_prach_pdu_t *prach_pdu);
|
||||
void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot);
|
||||
void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot);
|
||||
void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx);
|
||||
void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx);
|
||||
|
||||
@@ -778,6 +778,8 @@ int main(int argc, char **argv)
|
||||
UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].round = round;
|
||||
UE_info->UE_sched_ctrl[0].current_harq_pid = harq_pid;
|
||||
gNB->dlsch[0][0]->harq_processes[harq_pid]->round = round;
|
||||
for (int i=0; i<MAX_NUM_CORESET; i++)
|
||||
gNB_mac->UE_info.num_pdcch_cand[0][i] = 0;
|
||||
|
||||
if (css_flag == 0) nr_schedule_uss_dlsch_phytest(0,frame,slot,&pucch_sched,&dlsch_config);
|
||||
else nr_schedule_css_dlsch_phytest(0,frame,slot);
|
||||
|
||||
@@ -113,6 +113,10 @@ int main(int argc, char **argv){
|
||||
uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format, format0, format1;
|
||||
uint32_t tx_lev = 10000, prach_errors = 0, samp_count; //,tx_lev_dB;
|
||||
uint64_t SSB_positions = 0x01, absoluteFrequencyPointA = 640000;
|
||||
uint16_t RA_sfn_index;
|
||||
uint8_t N_RA_slot;
|
||||
uint8_t config_period;
|
||||
int prachOccasion = 0;
|
||||
double DS_TDL = .03;
|
||||
|
||||
// int8_t interf1=-19,interf2=-19;
|
||||
@@ -428,15 +432,18 @@ int main(int argc, char **argv){
|
||||
gNB->proc.slot_rx = slot;
|
||||
|
||||
int ret = get_nr_prach_info_from_index(config_index,
|
||||
(int)frame,
|
||||
(int)slot_gNB,
|
||||
absoluteFrequencyPointA,
|
||||
mu,
|
||||
frame_parms->frame_type,
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur);
|
||||
(int)frame,
|
||||
(int)slot_gNB,
|
||||
absoluteFrequencyPointA,
|
||||
mu,
|
||||
frame_parms->frame_type,
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur,
|
||||
&RA_sfn_index,
|
||||
&N_RA_slot,
|
||||
&config_period);
|
||||
|
||||
if (ret == 0) {printf("No prach in %d.%d, mu %d, config_index %d\n",frame,slot,mu,config_index); exit(-1);}
|
||||
format0 = format&0xff; // first column of format from table
|
||||
@@ -445,60 +452,54 @@ int main(int argc, char **argv){
|
||||
if (format1 != 0xff) {
|
||||
switch(format0) {
|
||||
case 0xa1:
|
||||
prach_format = 9;
|
||||
prach_format = 11;
|
||||
break;
|
||||
case 0xa2:
|
||||
prach_format = 10;
|
||||
prach_format = 12;
|
||||
break;
|
||||
case 0xa3:
|
||||
prach_format = 11;
|
||||
prach_format = 13;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
|
||||
}
|
||||
} else {
|
||||
switch(format0) {
|
||||
case 0xa1:
|
||||
prach_format = 0;
|
||||
break;
|
||||
case 0xa2:
|
||||
prach_format = 1;
|
||||
break;
|
||||
case 0xa3:
|
||||
prach_format = 2;
|
||||
break;
|
||||
case 0xb1:
|
||||
prach_format = 3;
|
||||
break;
|
||||
case 0xb2:
|
||||
prach_format = 4;
|
||||
break;
|
||||
case 0xb3:
|
||||
prach_format = 5;
|
||||
break;
|
||||
case 0xb4:
|
||||
prach_format = 6;
|
||||
break;
|
||||
case 0xc0:
|
||||
prach_format = 7;
|
||||
break;
|
||||
case 0xc2:
|
||||
prach_format = 8;
|
||||
break;
|
||||
case 0:
|
||||
// long formats are handled @ PHY
|
||||
break;
|
||||
case 1:
|
||||
// long formats are handled @ PHY
|
||||
break;
|
||||
case 2:
|
||||
// long formats are handled @ PHY
|
||||
break;
|
||||
case 3:
|
||||
// long formats are handled @ PHY
|
||||
break;
|
||||
switch(format0) { // single PRACH format
|
||||
case 0:
|
||||
prach_format = 0;
|
||||
break;
|
||||
case 1:
|
||||
prach_format = 1;
|
||||
break;
|
||||
case 2:
|
||||
prach_format = 2;
|
||||
break;
|
||||
case 3:
|
||||
prach_format = 3;
|
||||
break;
|
||||
case 0xa1:
|
||||
prach_format = 4;
|
||||
break;
|
||||
case 0xa2:
|
||||
prach_format = 5;
|
||||
break;
|
||||
case 0xa3:
|
||||
prach_format = 6;
|
||||
break;
|
||||
case 0xb1:
|
||||
prach_format = 7;
|
||||
break;
|
||||
case 0xb4:
|
||||
prach_format = 8;
|
||||
break;
|
||||
case 0xc0:
|
||||
prach_format = 9;
|
||||
break;
|
||||
case 0xc2:
|
||||
prach_format = 10;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0, "Invalid PRACH format");
|
||||
AssertFatal(1 == 0, "Invalid PRACH format");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -721,11 +722,11 @@ int main(int argc, char **argv){
|
||||
}
|
||||
|
||||
|
||||
rx_nr_prach_ru(ru, prach_format, numRA, prachStartSymbol, frame, slot);
|
||||
rx_nr_prach_ru(ru, prach_format, numRA, prachStartSymbol, prachOccasion, frame, slot);
|
||||
|
||||
gNB->prach_vars.rxsigF = ru->prach_rxsigF;
|
||||
gNB->prach_vars.rxsigF = ru->prach_rxsigF[prachOccasion];
|
||||
if (n_frames == 1) printf("ncs %d,num_seq %d\n",prach_pdu->num_cs, prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value);
|
||||
rx_nr_prach(gNB, prach_pdu, frame, subframe, &preamble_rx, &preamble_energy, &preamble_delay);
|
||||
rx_nr_prach(gNB, prach_pdu, prachOccasion, frame, subframe, &preamble_rx, &preamble_energy, &preamble_delay);
|
||||
|
||||
// printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", preamble_energy, preamble_rx, preamble_tx);
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
/*Array containing the Agent-MAC interfaces*/
|
||||
AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];
|
||||
|
||||
@@ -53,10 +55,20 @@ struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_element *slice_config_array[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_state slice_config_ringbuffer_state[NUM_MAX_ENB];
|
||||
|
||||
/* Ringbuffer related to slice configuration if we need to wait for additional
|
||||
* controller information */
|
||||
struct lfds700_ringbuffer_element *store_slice_config_array[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_state store_slice_config_ringbuffer_state[NUM_MAX_ENB];
|
||||
/* stores the (increasing) xid for messages to prevent double use */
|
||||
int xid = 50;
|
||||
|
||||
/* Ringbuffer-related to slice configuration */
|
||||
struct lfds700_ringbuffer_element *ue_assoc_array[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_state ue_assoc_ringbuffer_state[NUM_MAX_ENB];
|
||||
|
||||
/* a list of shared objects that are loaded into the user plane */
|
||||
SLIST_HEAD(flexran_so_handle, flexran_agent_so_handle_s) flexran_handles[NUM_MAX_ENB];
|
||||
|
||||
int flexran_agent_mac_stats_reply_ue(mid_t mod_id,
|
||||
Protocol__FlexUeStatsReport **ue_report,
|
||||
int n_ue,
|
||||
@@ -1363,6 +1375,19 @@ void flexran_agent_init_mac_agent(mid_t mod_id) {
|
||||
&scrng,
|
||||
NULL);
|
||||
|
||||
struct lfds700_misc_prng_state sscrng;
|
||||
i = posix_memalign((void **) &store_slice_config_array[mod_id],
|
||||
LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES,
|
||||
sizeof(struct lfds700_ringbuffer_element) * num_elements);
|
||||
AssertFatal(i == 0,
|
||||
"posix_memalign(): could not allocate aligned memory\n");
|
||||
lfds700_ringbuffer_init_valid_on_current_logical_core(
|
||||
&store_slice_config_ringbuffer_state[mod_id],
|
||||
store_slice_config_array[mod_id],
|
||||
num_elements,
|
||||
&sscrng,
|
||||
NULL);
|
||||
|
||||
struct lfds700_misc_prng_state uarng;
|
||||
i = posix_memalign((void **) &ue_assoc_array[mod_id],
|
||||
LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES,
|
||||
@@ -1382,6 +1407,8 @@ void flexran_agent_init_mac_agent(mid_t mod_id) {
|
||||
RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SLIST_INIT(&flexran_handles[mod_id]);
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
@@ -1659,6 +1686,8 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id)
|
||||
free(dl_mac_config_array[mod_id]);
|
||||
lfds700_ringbuffer_cleanup(&slice_config_ringbuffer_state[mod_id], NULL );
|
||||
free(slice_config_array[mod_id]);
|
||||
lfds700_ringbuffer_cleanup(&store_slice_config_ringbuffer_state[mod_id], NULL );
|
||||
free(store_slice_config_array[mod_id]);
|
||||
lfds700_ringbuffer_cleanup(&ue_assoc_ringbuffer_state[mod_id], NULL );
|
||||
free(ue_assoc_array[mod_id]);
|
||||
lfds700_misc_library_cleanup();
|
||||
@@ -1698,7 +1727,81 @@ void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) {
|
||||
flexran_agent_destroy_mac_slice_config(&helper);
|
||||
}
|
||||
|
||||
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) {
|
||||
int check_scheduler(mid_t mod_id, char *s) {
|
||||
if (!s)
|
||||
return 1;
|
||||
if (dlsym(NULL, s))
|
||||
return 1;
|
||||
flexran_agent_so_handle_t *so = NULL;
|
||||
SLIST_FOREACH(so, &flexran_handles[mod_id], entries) {
|
||||
if (strcmp(so->name, s) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void request_scheduler(mid_t mod_id, char *s, int xid) {
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"unknown scheduler %s, requesting controller to send it\n",
|
||||
s);
|
||||
Protocol__FlexControlDelegationRequest *req = malloc(sizeof(Protocol__FlexControlDelegationRequest));
|
||||
DevAssert(req);
|
||||
protocol__flex_control_delegation_request__init(req);
|
||||
Protocol__FlexHeader *header = NULL;
|
||||
int rc = flexran_create_header(
|
||||
xid, PROTOCOL__FLEX_TYPE__FLPT_DELEGATE_REQUEST, &header);
|
||||
AssertFatal(rc == 0, "%s(): cannot create header\n", __func__);
|
||||
req->header = header;
|
||||
req->delegation_type = PROTOCOL__FLEX_CONTROL_DELEGATION_TYPE__FLCDT_MAC_DL_UE_SCHEDULER;
|
||||
req->name = strdup(s);
|
||||
|
||||
Protocol__FlexranMessage *msg = malloc(sizeof(Protocol__FlexranMessage));
|
||||
DevAssert(msg);
|
||||
protocol__flexran_message__init(msg);
|
||||
msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DEL_REQ_MSG;
|
||||
msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
|
||||
msg->control_del_req_msg = req;
|
||||
|
||||
int size = 0;
|
||||
void *data = flexran_agent_pack_message(msg, &size);
|
||||
if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_DEFAULT, data, size, 0) < 0)
|
||||
LOG_E(FLEXRAN_AGENT, "%s(): error while sending message\n", __func__);
|
||||
}
|
||||
|
||||
Protocol__FlexranMessage *request_scheduler_timeout(
|
||||
mid_t mod_id,
|
||||
const Protocol__FlexranMessage *msg) {
|
||||
const Protocol__FlexEnbConfigReply *ecr = msg->enb_config_reply_msg;
|
||||
|
||||
struct lfds700_misc_prng_state ls;
|
||||
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
||||
lfds700_misc_prng_init(&ls);
|
||||
|
||||
Protocol__FlexranMessage *smsg = NULL;
|
||||
struct lfds700_ringbuffer_state *state = &store_slice_config_ringbuffer_state[mod_id];
|
||||
if (lfds700_ringbuffer_read(state, NULL, (void **) &smsg, &ls)) {
|
||||
AssertFatal(msg == smsg,
|
||||
"expected and returned enb_config_reply are not the same\n");
|
||||
AssertFatal(ecr->header->xid == smsg->enb_config_reply_msg->header->xid,
|
||||
"expected and returned enb_config_reply are not the same\n");
|
||||
} else {
|
||||
LOG_E(FLEXRAN_AGENT, "%s(): could not read config from ringbuffer\n", __func__);
|
||||
}
|
||||
/* call the helper so that scheduler names are correctly freed */
|
||||
helper_destroy_mac_slice_config(ecr->cell_config[0]->slice_config);
|
||||
ecr->cell_config[0]->slice_config = NULL;
|
||||
/* we should not call flexran_agent_destroy_enb_config_reply(smsg); since
|
||||
* upon timer removal, this is automatically done */
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"remove stored slice config (xid %d) after timeout\n",
|
||||
ecr->header->xid);
|
||||
flexran_agent_destroy_timer(mod_id, ecr->header->xid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void prepare_update_slice_config(mid_t mod_id,
|
||||
Protocol__FlexSliceConfig **slice_config,
|
||||
int request_objects) {
|
||||
if (!*slice_config) return;
|
||||
/* just use the memory and set to NULL in original */
|
||||
Protocol__FlexSliceConfig *sc = *slice_config;
|
||||
@@ -1709,6 +1812,63 @@ void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice
|
||||
lfds700_misc_prng_init(&ls);
|
||||
enum lfds700_misc_flag overwrite_occurred_flag;
|
||||
|
||||
int put_on_hold = 0;
|
||||
if (request_objects
|
||||
&& sc->dl->scheduler
|
||||
&& !check_scheduler(mod_id, sc->dl->scheduler)) {
|
||||
request_scheduler(mod_id, sc->dl->scheduler, xid++);
|
||||
put_on_hold = 1;
|
||||
}
|
||||
for (int i = 0; request_objects && i < sc->dl->n_slices; ++i) {
|
||||
Protocol__FlexSlice *sl = sc->dl->slices[i];
|
||||
if (sl->scheduler && !check_scheduler(mod_id, sl->scheduler)) {
|
||||
request_scheduler(mod_id, sl->scheduler, xid++);
|
||||
put_on_hold = 1;
|
||||
}
|
||||
}
|
||||
if (put_on_hold) {
|
||||
Protocol__FlexEnbConfigReply *reply = malloc(sizeof(Protocol__FlexEnbConfigReply));
|
||||
DevAssert(reply);
|
||||
protocol__flex_enb_config_reply__init(reply);
|
||||
/* use the last used xid so we can correlate answer and waiting config */
|
||||
int rc = flexran_create_header(
|
||||
xid - 1, PROTOCOL__FLEX_TYPE__FLPT_GET_ENB_CONFIG_REPLY, &reply->header);
|
||||
AssertFatal(rc == 0, "%s(): cannot create header\n", __func__);
|
||||
reply->n_cell_config = 1;
|
||||
reply->cell_config = malloc(sizeof(Protocol__FlexCellConfig *));
|
||||
DevAssert(reply->cell_config);
|
||||
reply->cell_config[0] = malloc(sizeof(Protocol__FlexCellConfig));
|
||||
DevAssert(reply->cell_config[0]);
|
||||
protocol__flex_cell_config__init(reply->cell_config[0]);
|
||||
reply->cell_config[0]->slice_config = sc;
|
||||
|
||||
Protocol__FlexranMessage *msg = malloc(sizeof(Protocol__FlexranMessage));
|
||||
DevAssert(msg);
|
||||
protocol__flexran_message__init(msg);
|
||||
msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG;
|
||||
msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
|
||||
msg->enb_config_reply_msg = reply;
|
||||
|
||||
Protocol__FlexEnbConfigReply *o;
|
||||
lfds700_ringbuffer_write(&store_slice_config_ringbuffer_state[mod_id],
|
||||
NULL,
|
||||
(void *)msg,
|
||||
&overwrite_occurred_flag,
|
||||
NULL,
|
||||
(void **) &o,
|
||||
&ls);
|
||||
AssertFatal(overwrite_occurred_flag == LFDS700_MISC_FLAG_LOWERED,
|
||||
"unhandled: stored slice config for controller has been overwritten\n");
|
||||
|
||||
flexran_agent_create_timer(mod_id,
|
||||
3000,
|
||||
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC,
|
||||
xid - 1,
|
||||
request_scheduler_timeout,
|
||||
msg); /* need reply for xid */
|
||||
return;
|
||||
}
|
||||
|
||||
Protocol__FlexSliceConfig *overwritten_sc;
|
||||
lfds700_ringbuffer_write(&slice_config_ringbuffer_state[mod_id],
|
||||
NULL,
|
||||
@@ -1756,6 +1916,69 @@ void flexran_agent_slice_update(mid_t mod_id) {
|
||||
apply_update_dl_slice_config(mod_id, sc->dl);
|
||||
apply_update_ul_slice_config(mod_id, sc->ul);
|
||||
helper_destroy_mac_slice_config(sc);
|
||||
|
||||
flexran_agent_so_handle_t *so = NULL;
|
||||
flexran_agent_so_handle_t *prev = NULL; // the previous to current element, if we delete in order to go back
|
||||
//SLIST_FOREACH(so, &flexran_handles[mod_id], entries)
|
||||
for(so = flexran_handles[mod_id].slh_first; so;) {
|
||||
char *name = so->name;
|
||||
int in_use = strcmp(flexran_get_dl_scheduler_name(mod_id), name) == 0
|
||||
|| strcmp(flexran_get_ul_scheduler_name(mod_id), name) == 0;
|
||||
Protocol__FlexSliceAlgorithm dl_algo = flexran_get_dl_slice_algo(mod_id);
|
||||
if (!in_use && dl_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
int n = flexran_get_num_dl_slices(mod_id);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
Protocol__FlexSlice s;
|
||||
/* NONE so it won't do any allocations */
|
||||
flexran_get_dl_slice(mod_id, i, &s, PROTOCOL__FLEX_SLICE_ALGORITHM__None);
|
||||
if (strcmp(s.scheduler, name) == 0) {
|
||||
in_use = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Protocol__FlexSliceAlgorithm ul_algo = flexran_get_ul_slice_algo(mod_id);
|
||||
if (!in_use && ul_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
int n = flexran_get_num_ul_slices(mod_id);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
Protocol__FlexSlice s;
|
||||
/* NONE so it won't do any allocations */
|
||||
flexran_get_ul_slice(mod_id, i, &s, PROTOCOL__FLEX_SLICE_ALGORITHM__None);
|
||||
if (strcmp(s.scheduler, name) == 0) {
|
||||
in_use = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!in_use) {
|
||||
char s[512];
|
||||
int rc = flexran_agent_map_name_to_delegated_object(mod_id, so->name, s, 512);
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"removing %s (library handle %p) since it is not used in the user "
|
||||
"plane anymore\n",
|
||||
s,
|
||||
so->dl_handle);
|
||||
dlclose(so->dl_handle);
|
||||
if (rc < 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", so->name);
|
||||
} else {
|
||||
int rc = remove(s);
|
||||
if (rc < 0)
|
||||
LOG_E(FLEXRAN_AGENT, "cannot remove file %s: %s\n", s, strerror(errno));
|
||||
}
|
||||
free (so->name);
|
||||
if (!prev) { //it's the head, start over
|
||||
SLIST_REMOVE_HEAD(&flexran_handles[mod_id], entries);
|
||||
so = flexran_handles[mod_id].slh_first;
|
||||
} else {
|
||||
SLIST_REMOVE(&flexran_handles[mod_id], so, flexran_agent_so_handle_s, entries);
|
||||
so = prev->entries.sle_next;
|
||||
}
|
||||
} else {
|
||||
prev = so;
|
||||
so = so->entries.sle_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Protocol__FlexUeConfig *ue_config = NULL;
|
||||
@@ -1765,3 +1988,92 @@ void flexran_agent_slice_update(mid_t mod_id) {
|
||||
free(ue_config);
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_agent_mac_inform_delegation(mid_t mod_id,
|
||||
Protocol__FlexControlDelegation *cdm) {
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"received FlexControlDelegation message for object '%s' xid %d\n",
|
||||
cdm->name,
|
||||
cdm->header->xid);
|
||||
if (cdm->header->xid < xid - 1) {
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"waiting for %d more messages (up to xid %d)\n",
|
||||
xid - 1 - cdm->header->xid,
|
||||
xid - 1);
|
||||
return;
|
||||
}
|
||||
/* should receive up to xid - 1, otherwise it means there was no request */
|
||||
AssertFatal(xid > cdm->header->xid,
|
||||
"received control delegation with xid %d that we never requested "
|
||||
"(last request %d)\n",
|
||||
cdm->header->xid,
|
||||
xid - 1);
|
||||
|
||||
/* Load the library so the user plane can search it */
|
||||
char s[512];
|
||||
int rc = flexran_agent_map_name_to_delegated_object(mod_id, cdm->name, s, 512);
|
||||
if (rc < 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", cdm->name);
|
||||
return;
|
||||
}
|
||||
/* TODO where to unload/save handle?? */
|
||||
void *h = dlopen(s, RTLD_NOW);
|
||||
if (!h) {
|
||||
LOG_E(FLEXRAN_AGENT, "dlopen(): %s\n", dlerror());
|
||||
return;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "library handle %p\n", h);
|
||||
|
||||
struct lfds700_misc_prng_state ls;
|
||||
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
||||
lfds700_misc_prng_init(&ls);
|
||||
|
||||
Protocol__FlexranMessage *msg = NULL;
|
||||
struct lfds700_ringbuffer_state *state = &store_slice_config_ringbuffer_state[mod_id];
|
||||
if (lfds700_ringbuffer_read(state, NULL, (void **) &msg, &ls) == 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "%s(): could not read config from ringbuffer\n", __func__);
|
||||
return;
|
||||
}
|
||||
AssertFatal(cdm->header->xid == msg->enb_config_reply_msg->header->xid,
|
||||
"expected and retrieved xid of stored slice configuration does "
|
||||
"not match (expected %d, retrieved %d)\n",
|
||||
cdm->header->xid,
|
||||
msg->enb_config_reply_msg->header->xid);
|
||||
|
||||
/* Since we recover, stop the timeout */
|
||||
rc = flexran_agent_destroy_timer(mod_id, cdm->header->xid);
|
||||
|
||||
prepare_update_slice_config(
|
||||
mod_id,
|
||||
&msg->enb_config_reply_msg->cell_config[0]->slice_config,
|
||||
0 /* don't do a request */);
|
||||
/* we should not call flexran_agent_destroy_enb_config_reply(smsg); since
|
||||
* upon timer removal, this is automatically done.
|
||||
* prepare_update_slice_config() takes ownership of the slice config, it is
|
||||
* freed inside */
|
||||
|
||||
flexran_agent_so_handle_t *so = malloc(sizeof(flexran_agent_so_handle_t));
|
||||
DevAssert(so);
|
||||
so->name = strdup(cdm->name);
|
||||
DevAssert(so->name);
|
||||
so->dl_handle = h;
|
||||
SLIST_INSERT_HEAD(&flexran_handles[mod_id], so, entries);
|
||||
}
|
||||
|
||||
void flexran_agent_mac_fill_loaded_mac_objects(
|
||||
mid_t mod_id,
|
||||
Protocol__FlexEnbConfigReply *reply) {
|
||||
int n = 0;
|
||||
flexran_agent_so_handle_t *so = NULL;
|
||||
SLIST_FOREACH(so, &flexran_handles[mod_id], entries)
|
||||
++n;
|
||||
reply->n_loadedmacobjects = n;
|
||||
reply->loadedmacobjects = calloc(n, sizeof(char *));
|
||||
if (!reply->loadedmacobjects) {
|
||||
reply->n_loadedmacobjects = 0;
|
||||
return;
|
||||
}
|
||||
n = 0;
|
||||
SLIST_FOREACH(so, &flexran_handles[mod_id], entries)
|
||||
reply->loadedmacobjects[n++] = so->name;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,12 @@
|
||||
// for flexran_agent_get_mac_xface()
|
||||
#include "flexran_agent_extern.h"
|
||||
|
||||
/* Type for a list of shared objects used in the user plane (schedulers) */
|
||||
typedef struct flexran_agent_so_handle_s {
|
||||
char *name; // name of the object
|
||||
void *dl_handle; // handle of associated objects
|
||||
SLIST_ENTRY (flexran_agent_so_handle_s) entries;
|
||||
} flexran_agent_so_handle_t;
|
||||
|
||||
/* Initialization function for the agent structures etc */
|
||||
void flexran_agent_init_mac_agent(mid_t mod_id);
|
||||
@@ -117,7 +123,9 @@ void flexran_agent_slice_update(mid_t mod_id);
|
||||
|
||||
/* marks slice_config so that it can be applied later. Takes ownership of the
|
||||
* FlexSliceConfig message */
|
||||
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice);
|
||||
void prepare_update_slice_config(mid_t mod_id,
|
||||
Protocol__FlexSliceConfig **slice,
|
||||
int request_objects);
|
||||
|
||||
/* inserts a new ue_config into the structure keeping ue to slice association
|
||||
* updates and marks so it can be applied. Takes ownership of the FlexUeConfig message */
|
||||
@@ -127,4 +135,13 @@ void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_con
|
||||
* flexran_agent_fill_mac_cell_config() */
|
||||
void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf);
|
||||
|
||||
/* information about a new (potentially relevant) control delegation message */
|
||||
void flexran_agent_mac_inform_delegation(mid_t mod_id,
|
||||
Protocol__FlexControlDelegation *cdm);
|
||||
|
||||
/* fill the enb_config_reply with the shared objects in use by the MAC sublayer */
|
||||
void flexran_agent_mac_fill_loaded_mac_objects(
|
||||
mid_t mod_id,
|
||||
Protocol__FlexEnbConfigReply *reply);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
#include "flexran_agent_mac_internal.h"
|
||||
#include "flexran_agent_mac_slice_verification.h"
|
||||
|
||||
extern SLIST_HEAD(flexran_so_handle,
|
||||
flexran_agent_so_handle_s) flexran_handles[NUM_MAX_ENB];
|
||||
|
||||
Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message,
|
||||
Protocol__FlexranMessage *old_message) {
|
||||
|
||||
@@ -1025,6 +1028,19 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) {
|
||||
|
||||
}
|
||||
|
||||
void *search_so(mid_t mod_id, char *name) {
|
||||
if (!name) // no name -> nothing to return, so use NULL for executable
|
||||
return NULL;
|
||||
if (dlsym(NULL, name)) // found it in executable
|
||||
return NULL;
|
||||
flexran_agent_so_handle_t *so = NULL;
|
||||
SLIST_FOREACH(so, &flexran_handles[mod_id], entries) {
|
||||
if (strcmp(so->name, name) == 0)
|
||||
return so->dl_handle;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) {
|
||||
if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET
|
||||
&& !s->label && !s->scheduler) {
|
||||
@@ -1033,8 +1049,12 @@ void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) {
|
||||
if (!rc)
|
||||
LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id);
|
||||
} else {
|
||||
LOG_I(FLEXRAN_AGENT, "updating DL slice ID %d\n", s->id);
|
||||
const int rc = flexran_create_dl_slice(mod_id, s);
|
||||
void *lib = search_so(mod_id, s->scheduler);
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"updating DL slice ID %d (library handle %p)\n",
|
||||
s->id,
|
||||
lib);
|
||||
const int rc = flexran_create_dl_slice(mod_id, s, lib);
|
||||
if (rc < 0)
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"error while update slice ID %d: flexran_create_dl_slice() -> %d\n",
|
||||
@@ -1050,8 +1070,12 @@ void update_or_remove_ul(mid_t mod_id, Protocol__FlexSlice *s) {
|
||||
if (!rc)
|
||||
LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id);
|
||||
} else {
|
||||
LOG_I(FLEXRAN_AGENT, "updating UL slice ID %d\n", s->id);
|
||||
const int rc = flexran_create_ul_slice(mod_id, s);
|
||||
void *lib = search_so(mod_id, s->scheduler);
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"updating UL slice ID %d (library handle %p)\n",
|
||||
s->id,
|
||||
lib);
|
||||
const int rc = flexran_create_ul_slice(mod_id, s, lib);
|
||||
if (rc < 0)
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"error while updating slice ID %d: flexran_create_ul_slice() -> %d)\n",
|
||||
@@ -1099,8 +1123,12 @@ void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *d
|
||||
LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n");
|
||||
return;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "loading DL new scheduling algorithm '%s'\n", dl->scheduler);
|
||||
const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler);
|
||||
void *lib = search_so(mod_id, dl->scheduler);
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"loading DL new scheduling algorithm '%s' (library handle %p)\n",
|
||||
dl->scheduler,
|
||||
lib);
|
||||
const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler, lib);
|
||||
if (rc < 0) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"error while updating scheduling algorithm: "
|
||||
@@ -1147,8 +1175,12 @@ void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *u
|
||||
LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n");
|
||||
return;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "loading new UL scheduling algorithm '%s'\n", ul->scheduler);
|
||||
const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler);
|
||||
void *lib = search_so(mod_id, ul->scheduler);
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"loading new UL scheduling algorithm '%s' (library handle %p)\n",
|
||||
ul->scheduler,
|
||||
lib);
|
||||
const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler, lib);
|
||||
if (rc < 0) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"error while updating scheduling algorithm: "
|
||||
|
||||
@@ -3,4 +3,25 @@ package protocol;
|
||||
|
||||
enum flex_control_delegation_type {
|
||||
FLCDT_MAC_DL_UE_SCHEDULER = 1; // DL UE scheduler delegation
|
||||
FLCDT_AGENT_CONTROL_APP = 2; // Generic control application
|
||||
}
|
||||
|
||||
message flex_agent_reconfiguration_system {
|
||||
optional string system = 1;
|
||||
repeated flex_agent_reconfiguration_subsystem subsystems = 2;
|
||||
}
|
||||
|
||||
message flex_agent_reconfiguration_subsystem {
|
||||
optional string name = 1; // Name of the object (app name or user plane object)
|
||||
optional string behavior = 2; // For an app: a callback in a shared library. For any other subsystem: an object name (shared library) with defined syntax.
|
||||
map<string, flex_agent_reconfiguration_param> params = 3; // Param configurations depending on callback/shared library above.
|
||||
}
|
||||
|
||||
message flex_agent_reconfiguration_param {
|
||||
oneof param {
|
||||
int32 integer = 1;
|
||||
float floating = 2;
|
||||
bool boolean = 3;
|
||||
string str = 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import "time_common.proto";
|
||||
import "config_messages.proto";
|
||||
import "controller_commands.proto";
|
||||
import "config_common.proto";
|
||||
import "control_delegation.proto";
|
||||
|
||||
message flexran_message {
|
||||
optional flexran_direction msg_dir = 100;
|
||||
@@ -32,6 +33,7 @@ message flexran_message {
|
||||
flex_ul_mac_config ul_mac_config_msg = 19;
|
||||
flex_disconnect disconnect_msg = 20;
|
||||
flex_ho_command ho_command_msg = 21;
|
||||
flex_control_delegation_request control_del_req_msg = 22;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,6 +159,8 @@ message flex_enb_config_reply {
|
||||
repeated flex_cell_config cell_config = 3;
|
||||
optional uint32 device_spec = 4;
|
||||
optional flex_s1ap_config s1ap = 5;
|
||||
repeated string loadedApps = 6;
|
||||
repeated string loadedMacObjects = 7;
|
||||
}
|
||||
|
||||
message flex_ue_config_request {
|
||||
@@ -225,11 +229,17 @@ message flex_ue_state_change {
|
||||
|
||||
message flex_control_delegation {
|
||||
optional flex_header header = 1;
|
||||
optional uint32 delegation_type = 2; // Bitmap of FLCDT_* flags
|
||||
optional flex_control_delegation_type delegation_type = 2; // The delegated object type, decides about further processing
|
||||
optional bytes payload = 3; // Byte array of shared lib containing the delegated functions
|
||||
optional string name = 4; // The delegated functions names ordered based on bitmap flags
|
||||
}
|
||||
|
||||
message flex_control_delegation_request {
|
||||
optional flex_header header = 1;
|
||||
optional flex_control_delegation_type delegation_type = 2;
|
||||
optional string name = 4;
|
||||
}
|
||||
|
||||
//
|
||||
// Agent reconfiguration message
|
||||
//
|
||||
@@ -237,6 +247,7 @@ message flex_control_delegation {
|
||||
message flex_agent_reconfiguration {
|
||||
optional flex_header header = 1;
|
||||
optional string policy = 2; // The policy changes using YAML syntax in string format
|
||||
repeated flex_agent_reconfiguration_system systems = 3; // The policy changes.
|
||||
}
|
||||
|
||||
// Extensions of the echo request and reply
|
||||
|
||||
@@ -44,5 +44,6 @@ enum flex_type {
|
||||
FLPT_RECONFIGURE_AGENT = 16;
|
||||
FLPT_RRC_TRIGGERING = 17;
|
||||
FLPT_UL_MAC_CONFIG = 18;
|
||||
FLPT_DELEGATE_REQUEST = 22;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,6 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int channel_container_init = 0;
|
||||
int flexran_agent_start(mid_t mod_id)
|
||||
{
|
||||
@@ -233,6 +232,9 @@ int flexran_agent_start(mid_t mod_id)
|
||||
agent_task_created = 1;
|
||||
}
|
||||
|
||||
/* Init the app sublayer */
|
||||
flexran_agent_app_init(mod_id);
|
||||
|
||||
pthread_mutex_init(&flexran->mutex_node_ctrl, NULL);
|
||||
pthread_cond_init(&flexran->cond_node_ctrl, NULL);
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "flexran_agent_rrc.h"
|
||||
#include "flexran_agent_pdcp.h"
|
||||
#include "flexran_agent_s1ap.h"
|
||||
#include "flexran_agent_app.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "assertions.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file flexran_agent_app.c
|
||||
* \brief CM for handling of applications
|
||||
* \author Robert Schmidt
|
||||
* \date 2020
|
||||
* \version 0.1
|
||||
*/
|
||||
|
||||
#include "flexran_agent_app.h"
|
||||
#include "queue.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
/* app definition */
|
||||
typedef struct flexran_agent_app_internal_s {
|
||||
char *name;
|
||||
void *dl_handle;
|
||||
flexran_agent_app_t *app;
|
||||
|
||||
SLIST_ENTRY (flexran_agent_app_internal_s) entries;
|
||||
} flexran_agent_app_internal_t;
|
||||
|
||||
/* a list of all apps */
|
||||
SLIST_HEAD(flexran_apps_s, flexran_agent_app_internal_s) flexran_apps[NUM_MAX_ENB];
|
||||
|
||||
void flexran_agent_app_init(mid_t mod_id) {
|
||||
//flexran_apps[mod_id] = SLIST_HEAD_INITIALIZER(flexran_apps[mod_id]);
|
||||
SLIST_INIT(&flexran_apps[mod_id]);
|
||||
}
|
||||
|
||||
int flexran_agent_start_app_direct(mid_t mod_id, flexran_agent_app_t *app, char *name) {
|
||||
app->start(mod_id, NULL, 0);
|
||||
|
||||
flexran_agent_app_internal_t *so = malloc(sizeof(flexran_agent_app_internal_t));
|
||||
DevAssert(so);
|
||||
so->name = strdup(name);
|
||||
DevAssert(so->name);
|
||||
so->dl_handle = NULL;
|
||||
so->app = app;
|
||||
SLIST_INSERT_HEAD(&flexran_apps[mod_id], so, entries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_agent_start_app(mid_t mod_id, Protocol__FlexAgentReconfigurationSubsystem *sub) {
|
||||
char s[512];
|
||||
int rc = flexran_agent_map_name_to_delegated_object(mod_id, sub->name, s, 512);
|
||||
if (rc < 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", sub->name);
|
||||
return -1;
|
||||
}
|
||||
void *h = dlopen(s, RTLD_NOW);
|
||||
if (!h) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot open shared object %s\n", s);
|
||||
return -1;
|
||||
}
|
||||
flexran_agent_app_t *app = dlsym(h, "app");
|
||||
if (!app) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot locate app inside of shared object %s\n", s);
|
||||
return -1;
|
||||
}
|
||||
app->start(mod_id, sub->params, sub->n_params);
|
||||
|
||||
flexran_agent_app_internal_t *so = malloc(sizeof(flexran_agent_app_internal_t));
|
||||
DevAssert(so);
|
||||
so->name = strdup(sub->name);
|
||||
DevAssert(so->name);
|
||||
so->dl_handle = h;
|
||||
so->app = app;
|
||||
SLIST_INSERT_HEAD(&flexran_apps[mod_id], so, entries);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_agent_stop_app(mid_t mod_id, char *name) {
|
||||
flexran_agent_app_internal_t *so = NULL;
|
||||
SLIST_FOREACH(so, &flexran_apps[mod_id], entries) {
|
||||
if (strcmp(so->name, name) == 0) {
|
||||
LOG_I(FLEXRAN_AGENT, "application %s seems to be running\n", name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!so) {
|
||||
LOG_E(FLEXRAN_AGENT, "no such application %s found\n", name);
|
||||
return -1;
|
||||
}
|
||||
flexran_agent_app_t *app = so->app;
|
||||
app->stop(mod_id);
|
||||
|
||||
SLIST_REMOVE(&flexran_apps[mod_id], so, flexran_agent_app_internal_s, entries);
|
||||
free(so->name);
|
||||
if (so->dl_handle)
|
||||
dlclose(so->dl_handle);
|
||||
free(so);
|
||||
so = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_agent_reconfig_app(
|
||||
mid_t mod_id,
|
||||
Protocol__FlexAgentReconfigurationSubsystem *sub)
|
||||
{
|
||||
flexran_agent_app_internal_t *so = NULL;
|
||||
SLIST_FOREACH(so, &flexran_apps[mod_id], entries) {
|
||||
if (strcmp(so->name, sub->name) == 0) {
|
||||
LOG_I(FLEXRAN_AGENT, "application %s is running\n", sub->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!so) {
|
||||
LOG_E(FLEXRAN_AGENT, "no such application %s found\n", sub->name);
|
||||
return -1;
|
||||
}
|
||||
flexran_agent_app_t *app = so->app;
|
||||
LOG_I(FLEXRAN_AGENT, "reconfiguring app %s\n", so->name);
|
||||
app->reconfig(mod_id, sub->params, sub->n_params);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_agent_custom_command_app(
|
||||
mid_t mod_id,
|
||||
Protocol__FlexAgentReconfigurationSubsystem *sub)
|
||||
{
|
||||
flexran_agent_app_internal_t *so = NULL;
|
||||
SLIST_FOREACH(so, &flexran_apps[mod_id], entries) {
|
||||
if (strcmp(so->name, sub->name) == 0) {
|
||||
LOG_I(FLEXRAN_AGENT, "application %s is running\n", sub->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!so) {
|
||||
LOG_E(FLEXRAN_AGENT, "no such application %s found\n", sub->name);
|
||||
return -1;
|
||||
}
|
||||
void (*cmd)(mid_t, Protocol__FlexAgentReconfigurationSubsystem *) = dlsym(so->dl_handle, sub->behavior);
|
||||
if (!cmd) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"cannot locate command %s inside of app %s\n",
|
||||
sub->behavior,
|
||||
so->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"calling command %s inside of app %s\n",
|
||||
sub->behavior,
|
||||
so->name);
|
||||
(*cmd)(mod_id, sub);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void flexran_agent_handle_apps(
|
||||
mid_t mod_id,
|
||||
Protocol__FlexAgentReconfigurationSubsystem **subs,
|
||||
int n_subs) {
|
||||
for (int i = 0; i < n_subs; ++i) {
|
||||
Protocol__FlexAgentReconfigurationSubsystem *s = subs[i];
|
||||
if (strcmp(s->behavior, "start") == 0) {
|
||||
int rc = flexran_agent_start_app(mod_id, s);
|
||||
if (rc == 0)
|
||||
LOG_I(FLEXRAN_AGENT, "application \"%s\" started\n", s->name);
|
||||
} else if (strcmp(s->behavior, "stop") == 0) {
|
||||
int rc = flexran_agent_stop_app(mod_id, s->name);
|
||||
if (rc == 0)
|
||||
LOG_I(FLEXRAN_AGENT, "application \"%s\" stopped\n", s->name);
|
||||
} else if (strcmp(s->behavior, "reconfig") == 0) {
|
||||
flexran_agent_reconfig_app(mod_id, s);
|
||||
} else {
|
||||
flexran_agent_custom_command_app(mod_id, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_agent_fill_loaded_apps(mid_t mod_id,
|
||||
Protocol__FlexEnbConfigReply *reply) {
|
||||
int n = 0;
|
||||
flexran_agent_app_internal_t *so = NULL;
|
||||
SLIST_FOREACH(so, &flexran_apps[mod_id], entries)
|
||||
++n;
|
||||
reply->n_loadedapps = n;
|
||||
reply->loadedapps = calloc(n, sizeof(char *));
|
||||
if (!reply->loadedapps) {
|
||||
reply->n_loadedapps = 0;
|
||||
return;
|
||||
}
|
||||
n = 0;
|
||||
SLIST_FOREACH(so, &flexran_apps[mod_id], entries)
|
||||
reply->loadedapps[n++] = so->name;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file flexran_agent_app.h
|
||||
* \brief Common app definitions
|
||||
* \author Robert Schmidt
|
||||
* \date 2020
|
||||
* \version 0.1
|
||||
*/
|
||||
|
||||
#ifndef BURST_ANALYSIS_LL_H_
|
||||
#define BURST_ANALYSIS_LL_H_
|
||||
|
||||
#include "flexran_agent_common.h"
|
||||
#include "flexran_agent_async.h"
|
||||
#include "flexran_agent_extern.h"
|
||||
#include "flexran_agent_timer.h"
|
||||
#include "flexran_agent_defs.h"
|
||||
#include "flexran_agent_net_comm.h"
|
||||
#include "flexran_agent_ran_api.h"
|
||||
#include "flexran_agent_phy.h"
|
||||
#include "flexran_agent_mac.h"
|
||||
#include "flexran_agent_rrc.h"
|
||||
#include "flexran_agent_pdcp.h"
|
||||
#include "flexran_agent_s1ap.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "assertions.h"
|
||||
|
||||
/* App type: to be implemented by shared libraries */
|
||||
typedef struct {
|
||||
int (*start)(mid_t mod_id,
|
||||
Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p,
|
||||
int n_p);
|
||||
int (*reconfig)(mid_t mod_id,
|
||||
Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p,
|
||||
int n_p);
|
||||
int (* stop)(mid_t mod_id);
|
||||
} flexran_agent_app_t;
|
||||
|
||||
/* FlexRAN agent app handling init */
|
||||
void flexran_agent_app_init(mid_t mod_id);
|
||||
|
||||
/* Start an app from within the agent */
|
||||
int flexran_agent_start_app_direct(mid_t mod_id, flexran_agent_app_t *app, char *name);
|
||||
|
||||
/* FlexRAN agent handler to setup/teardown apps */
|
||||
void flexran_agent_handle_apps(
|
||||
mid_t mod_id,
|
||||
Protocol__FlexAgentReconfigurationSubsystem **subs,
|
||||
int n_subs);
|
||||
|
||||
/* Fills the enb_config_reply with the currently loaded (started) apps */
|
||||
void flexran_agent_fill_loaded_apps(mid_t mod_id,
|
||||
Protocol__FlexEnbConfigReply *reply);
|
||||
|
||||
#endif
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "flexran_agent_common.h"
|
||||
#include "flexran_agent_common_internal.h"
|
||||
@@ -39,6 +42,7 @@
|
||||
#include "flexran_agent_mac.h"
|
||||
#include "flexran_agent_rrc.h"
|
||||
#include "flexran_agent_s1ap.h"
|
||||
#include "flexran_agent_app.h"
|
||||
//#include "PHY/extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "flexran_agent_mac_internal.h"
|
||||
@@ -326,6 +330,12 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
|
||||
if (reply->s1ap)
|
||||
flexran_agent_free_s1ap_cell_config(&reply->s1ap);
|
||||
|
||||
if (reply->loadedapps)
|
||||
free(reply->loadedapps);
|
||||
|
||||
if (reply->loadedmacobjects)
|
||||
free(reply->loadedmacobjects);
|
||||
|
||||
free(reply->cell_config);
|
||||
free(reply);
|
||||
free(msg);
|
||||
@@ -424,26 +434,65 @@ long timer_end(struct timespec start_time) {
|
||||
int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
|
||||
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
|
||||
Protocol__FlexControlDelegation *control_delegation_msg = input->control_delegation_msg;
|
||||
// struct timespec vartime = timer_start();
|
||||
//Write the payload lib into a file in the cache and load the lib
|
||||
char lib_name[120];
|
||||
char target[512];
|
||||
snprintf(lib_name, sizeof(lib_name), "/%s.so", control_delegation_msg->name);
|
||||
strcpy(target, RC.flexran[mod_id]->cache_name);
|
||||
strcat(target, lib_name);
|
||||
FILE *f;
|
||||
f = fopen(target, "wb");
|
||||
*msg = NULL;
|
||||
|
||||
if (f) {
|
||||
fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f);
|
||||
fclose(f);
|
||||
char target[512];
|
||||
int len = snprintf(target, sizeof(target), "%s/libflex.%s.so",
|
||||
RC.flexran[mod_id]->cache_name,
|
||||
control_delegation_msg->name);
|
||||
if (len >= sizeof(target)) {
|
||||
LOG_E(FLEXRAN_AGENT, "target has been truncated, cannot write file name\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (control_delegation_msg->has_payload) {
|
||||
/* use low-level API: check whether exists while creating so we can abort if
|
||||
* it exists to not overwrite anything */
|
||||
int fd = open(target, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR);
|
||||
if (fd >= 0) {
|
||||
ssize_t l = write(fd,
|
||||
control_delegation_msg->payload.data,
|
||||
control_delegation_msg->payload.len);
|
||||
close(fd);
|
||||
if (l < control_delegation_msg->payload.len) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"could not write complete control delegation to %s: only %ld out of "
|
||||
"%ld bytes\n",
|
||||
target,
|
||||
l,
|
||||
control_delegation_msg->payload.len);
|
||||
return 0;
|
||||
} else if (l < 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n",
|
||||
target, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "wrote shared object %s\n", target);
|
||||
} else {
|
||||
if (errno == EEXIST) {
|
||||
LOG_W(FLEXRAN_AGENT, "file %s already exists, remove it first\n", target);
|
||||
} else {
|
||||
LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n",
|
||||
target, strerror(errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] can not write control delegation data to %s\n",
|
||||
mod_id, target);
|
||||
LOG_W(FLEXRAN_AGENT, "remove file %s\n", target);
|
||||
int rc = remove(target);
|
||||
if (rc < 0)
|
||||
LOG_E(FLEXRAN_AGENT, "cannot remove file %s: %s\n", target, strerror(errno));
|
||||
}
|
||||
|
||||
if (control_delegation_msg->has_delegation_type
|
||||
&& control_delegation_msg->delegation_type == PROTOCOL__FLEX_CONTROL_DELEGATION_TYPE__FLCDT_MAC_DL_UE_SCHEDULER
|
||||
&& control_delegation_msg->header
|
||||
&& control_delegation_msg->header->has_xid) {
|
||||
/* Inform the MAC subsystem that a control delegation for it has arrived */
|
||||
/* TODO this should be triggered by an agent reconfiguration? */
|
||||
flexran_agent_mac_inform_delegation(mod_id, control_delegation_msg);
|
||||
}
|
||||
|
||||
// long time_elapsed_nanos = timer_end(vartime);
|
||||
*msg = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -452,10 +501,44 @@ int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_agent_map_name_to_delegated_object(mid_t mod_id, const char *name,
|
||||
char *path, int maxlen) {
|
||||
int len = snprintf(path, maxlen, "%s/libflex.%s.so",
|
||||
RC.flexran[mod_id]->cache_name, name);
|
||||
if (len >= maxlen) {
|
||||
LOG_E(FLEXRAN_AGENT, "path has been truncated, cannot read object\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct stat buf;
|
||||
int status = stat(path, &buf);
|
||||
if (status < 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "Could not stat object %s: %s\n", path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
|
||||
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
|
||||
Protocol__FlexAgentReconfiguration *agent_reconfiguration_msg = input->agent_reconfiguration_msg;
|
||||
apply_reconfiguration_policy(mod_id, agent_reconfiguration_msg->policy, strlen(agent_reconfiguration_msg->policy));
|
||||
if (agent_reconfiguration_msg->policy) {
|
||||
/* for compatibility: call old YAML configuration code, although we don't
|
||||
* use it anymore */
|
||||
apply_reconfiguration_policy(mod_id,
|
||||
agent_reconfiguration_msg->policy,
|
||||
strlen(agent_reconfiguration_msg->policy));
|
||||
}
|
||||
for (int i = 0; i < agent_reconfiguration_msg->n_systems; ++i) {
|
||||
const Protocol__FlexAgentReconfigurationSystem *sys = agent_reconfiguration_msg->systems[i];
|
||||
if (strcmp(sys->system, "app") == 0) {
|
||||
flexran_agent_handle_apps(mod_id, sys->subsystems, sys->n_subsystems);
|
||||
} else {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"unknown system name %s in flex_agent_reconfiguration message\n",
|
||||
sys->system);
|
||||
}
|
||||
}
|
||||
*msg = NULL;
|
||||
return 0;
|
||||
}
|
||||
@@ -465,6 +548,15 @@ int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_agent_destroy_control_delegation_request(Protocol__FlexranMessage *msg) {
|
||||
if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DEL_REQ_MSG)
|
||||
return -1;
|
||||
|
||||
free(msg->control_del_req_msg->header);
|
||||
free(msg->control_del_req_msg->name);
|
||||
free(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
|
||||
xid_t xid;
|
||||
@@ -750,6 +842,10 @@ int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__F
|
||||
if (flexran_agent_get_s1ap_xface(mod_id))
|
||||
flexran_agent_fill_s1ap_cell_config(mod_id, &enb_config_reply_msg->s1ap);
|
||||
|
||||
flexran_agent_fill_loaded_apps(mod_id, enb_config_reply_msg);
|
||||
|
||||
flexran_agent_mac_fill_loaded_mac_objects(mod_id, enb_config_reply_msg);
|
||||
|
||||
*msg = malloc(sizeof(Protocol__FlexranMessage));
|
||||
|
||||
if(*msg == NULL) {
|
||||
@@ -880,7 +976,9 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot
|
||||
|
||||
if (enb_config->n_cell_config > 0) {
|
||||
if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) {
|
||||
prepare_update_slice_config(mod_id, &enb_config->cell_config[0]->slice_config);
|
||||
prepare_update_slice_config(mod_id,
|
||||
&enb_config->cell_config[0]->slice_config,
|
||||
1 /* request objects if necessary */);
|
||||
}
|
||||
if (enb_config->cell_config[0]->has_eutra_band
|
||||
&& enb_config->cell_config[0]->has_dl_freq
|
||||
|
||||
@@ -131,11 +131,20 @@ int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg);
|
||||
/* Control delegation message constructor and destructor */
|
||||
int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
|
||||
int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg);
|
||||
/* Map a name from a control_delegation message to a file name. The function
|
||||
* stat()s the file to check existence and returns the complete path name in
|
||||
* path. The length in path needs to be maxlen, the maximum length the path may
|
||||
* have. */
|
||||
int flexran_agent_map_name_to_delegated_object(mid_t mod_id, const char *name,
|
||||
char *path, int maxlen);
|
||||
|
||||
/* Policy reconfiguration message constructor and destructor */
|
||||
int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
|
||||
int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg);
|
||||
|
||||
/* Policy reconfiguration request message destructor */
|
||||
int flexran_agent_destroy_control_delegation_request(Protocol__FlexranMessage *msg);
|
||||
|
||||
/* rrc triggering measurement message constructor and destructor */
|
||||
int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
|
||||
int flexran_agent_destroy_rrc_reconfiguration(Protocol__FlexranMessage *msg);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "flexran_agent_rrc.h"
|
||||
#include "flexran_agent_pdcp.h"
|
||||
#include "flexran_agent_s1ap.h"
|
||||
#include "flexran_agent_app.h"
|
||||
#include "flexran_agent_timer.h"
|
||||
#include "flexran_agent_ran_api.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
@@ -80,6 +81,11 @@ flexran_agent_message_destruction_callback message_destruction_callback[] = {
|
||||
flexran_agent_destroy_ue_state_change,
|
||||
flexran_agent_destroy_control_delegation,
|
||||
flexran_agent_destroy_agent_reconfiguration,
|
||||
NULL, /* flex_rrc_triggering */
|
||||
NULL, /* flex_ul_mac_config */
|
||||
NULL, /* flex_disconnect */
|
||||
NULL, /* flex_ho_command */
|
||||
flexran_agent_destroy_control_delegation_request,
|
||||
};
|
||||
|
||||
/* static const char *flexran_agent_direction2String[] = { */
|
||||
|
||||
@@ -3092,12 +3092,13 @@ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) {
|
||||
return slices->s[idx]->id;
|
||||
}
|
||||
|
||||
void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
int flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
int idx = flexran_find_dl_slice(mod_id, slice_id);
|
||||
if (idx < 0) return;
|
||||
if (idx < 0) return 0;
|
||||
pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
|
||||
dl->move_UE(dl->slices, ue_id, idx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) {
|
||||
@@ -3108,15 +3109,16 @@ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) {
|
||||
return slices->s[idx]->id;
|
||||
}
|
||||
|
||||
void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
int flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
int idx = flexran_find_ul_slice(mod_id, slice_id);
|
||||
if (idx < 0) return;
|
||||
if (idx < 0) return 0;
|
||||
pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
|
||||
ul->move_UE(ul->slices, ue_id, idx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
|
||||
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
void *params = NULL;
|
||||
switch (s->params_case) {
|
||||
@@ -3133,7 +3135,7 @@ int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
|
||||
char *l = s->label ? strdup(s->label) : NULL;
|
||||
void *algo = &dl->dl_algo; // default scheduler
|
||||
if (s->scheduler) {
|
||||
algo = dlsym(NULL, s->scheduler);
|
||||
algo = dlsym(object, s->scheduler);
|
||||
if (!algo) {
|
||||
free(params);
|
||||
LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler);
|
||||
@@ -3193,7 +3195,7 @@ int flexran_get_num_dl_slices(mid_t mod_id) {
|
||||
return RC.mac[mod_id]->pre_processor_dl.slices->num;
|
||||
}
|
||||
|
||||
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
|
||||
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
void *params = NULL;
|
||||
switch (s->params_case) {
|
||||
@@ -3210,7 +3212,7 @@ int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
|
||||
char *l = s->label ? strdup(s->label) : NULL;
|
||||
void *algo = &ul->ul_algo; // default scheduler
|
||||
if (s->scheduler) {
|
||||
algo = dlsym(NULL, s->scheduler);
|
||||
algo = dlsym(object, s->scheduler);
|
||||
if (!algo) {
|
||||
free(params);
|
||||
LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler);
|
||||
@@ -3276,9 +3278,9 @@ char *flexran_get_dl_scheduler_name(mid_t mod_id) {
|
||||
return RC.mac[mod_id]->pre_processor_dl.dl_algo.name;
|
||||
}
|
||||
|
||||
int flexran_set_dl_scheduler(mid_t mod_id, char *sched) {
|
||||
int flexran_set_dl_scheduler(mid_t mod_id, char *sched, void *object) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
void *d = dlsym(NULL, sched);
|
||||
void *d = dlsym(object, sched);
|
||||
if (!d) return -2;
|
||||
pp_impl_param_t *dl_pp = &RC.mac[mod_id]->pre_processor_dl;
|
||||
dl_pp->dl_algo.unset(&dl_pp->dl_algo.data);
|
||||
@@ -3292,9 +3294,9 @@ char *flexran_get_ul_scheduler_name(mid_t mod_id) {
|
||||
return RC.mac[mod_id]->pre_processor_ul.ul_algo.name;
|
||||
}
|
||||
|
||||
int flexran_set_ul_scheduler(mid_t mod_id, char *sched) {
|
||||
int flexran_set_ul_scheduler(mid_t mod_id, char *sched, void *object) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
void *d = dlsym(NULL, sched);
|
||||
void *d = dlsym(object, sched);
|
||||
if (!d) return -2;
|
||||
pp_impl_param_t *ul_pp = &RC.mac[mod_id]->pre_processor_ul;
|
||||
ul_pp->ul_algo.unset(&ul_pp->ul_algo.data);
|
||||
|
||||
@@ -669,15 +669,16 @@ int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo);
|
||||
/* Get the DL slice ID for a UE */
|
||||
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id);
|
||||
/* Set the DL slice for a UE */
|
||||
void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id);
|
||||
int flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id);
|
||||
|
||||
/* Get the UL slice ID for a UE */
|
||||
int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id);
|
||||
/* Set the UL slice for a UE */
|
||||
void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id);
|
||||
int flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id);
|
||||
|
||||
/* Create slice in DL, returns the new slice index */
|
||||
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s);
|
||||
/* Create slice in DL, returns the new slice index, object can be shared
|
||||
* library for the scheduler or NULL */
|
||||
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object);
|
||||
/* Remove slice in DL, returns new number of slices or -1 on error */
|
||||
int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s);
|
||||
|
||||
@@ -691,8 +692,9 @@ void flexran_get_dl_slice(mid_t mod_id,
|
||||
/* Get the number of slices in DL */
|
||||
int flexran_get_num_dl_slices(mid_t mod_id);
|
||||
|
||||
/* Create slice in UL, returns the new slice index */
|
||||
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s);
|
||||
/* Create slice in UL, returns the new slice index, object can be shared library
|
||||
* for the scheduler or NULL */
|
||||
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object);
|
||||
/* Remove slice in UL */
|
||||
int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s);
|
||||
|
||||
@@ -708,14 +710,14 @@ int flexran_get_num_ul_slices(mid_t mod_id);
|
||||
|
||||
/* Get the name of/Set the DL scheduling algorithm. If slicing is active, this
|
||||
* corresponds to the default algorithm for slices, otherwise the currently
|
||||
* used one. */
|
||||
* used one. object is a shared object in which to find the scheduler */
|
||||
char *flexran_get_dl_scheduler_name(mid_t mod_id);
|
||||
int flexran_set_dl_scheduler(mid_t mod_id, char *sched);
|
||||
int flexran_set_dl_scheduler(mid_t mod_id, char *sched, void *object);
|
||||
|
||||
/* Get the name of/Set the UL scheduler algorithm. Same applies as for the DL
|
||||
* case */
|
||||
* case. object is a shared object in which to find the scheduler */
|
||||
char *flexran_get_ul_scheduler_name(mid_t mod_id);
|
||||
int flexran_set_ul_scheduler(mid_t mod_id, char *sched);
|
||||
int flexran_set_ul_scheduler(mid_t mod_id, char *sched, void *object);
|
||||
|
||||
/************************** S1AP **************************/
|
||||
/* Get the number of MMEs to be connected */
|
||||
|
||||
@@ -58,6 +58,11 @@ struct timesync {
|
||||
|
||||
int timer_num;
|
||||
flexran_agent_timer_element_t *timer[MAX_NUM_TIMERS];
|
||||
|
||||
int add_num;
|
||||
flexran_agent_timer_element_t *add_list[MAX_NUM_TIMERS];
|
||||
int remove_num;
|
||||
int remove_list[MAX_NUM_TIMERS];
|
||||
pthread_mutex_t mutex_timer;
|
||||
|
||||
int exit;
|
||||
@@ -76,8 +81,12 @@ err_code_t flexran_agent_timer_init(mid_t mod_id) {
|
||||
sync->current = 0;
|
||||
sync->next = 0;
|
||||
sync->timer_num = 0;
|
||||
for (int i = 0; i < MAX_NUM_TIMERS; ++i)
|
||||
sync->add_num = 0;
|
||||
sync->remove_num = 0;
|
||||
for (int i = 0; i < MAX_NUM_TIMERS; ++i) {
|
||||
sync->timer[i] = NULL;
|
||||
sync->add_list[i] = NULL;
|
||||
}
|
||||
pthread_mutex_init(&sync->mutex_timer, NULL);
|
||||
sync->exit = 0;
|
||||
|
||||
@@ -170,12 +179,19 @@ void *flexran_agent_timer_thread(void *args) {
|
||||
break;
|
||||
|
||||
pthread_mutex_lock(&sync->mutex_timer);
|
||||
sync->current++;
|
||||
|
||||
if (sync->current < sync->next) {
|
||||
pthread_mutex_unlock(&sync->mutex_timer);
|
||||
continue;
|
||||
for (int i = 0; i < sync->add_num; ++i) {
|
||||
sync->timer[sync->timer_num] = sync->add_list[i];
|
||||
sync->timer_num++;
|
||||
}
|
||||
sync->add_num = 0;
|
||||
for (int i = 0; i < sync->remove_num; ++i)
|
||||
flexran_agent_timer_remove_internal(sync, sync->remove_list[i]);
|
||||
sync->remove_num = 0;
|
||||
pthread_mutex_unlock(&sync->mutex_timer);
|
||||
|
||||
sync->current++;
|
||||
if (sync->current < sync->next)
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < sync->timer_num; ++i) {
|
||||
flexran_agent_timer_element_t *t = sync->timer[i];
|
||||
@@ -186,7 +202,6 @@ void *flexran_agent_timer_thread(void *args) {
|
||||
if (sync->next == sync->current || t->next < sync->next)
|
||||
sync->next = t->next;
|
||||
}
|
||||
pthread_mutex_unlock(&sync->mutex_timer);
|
||||
}
|
||||
LOG_W(FLEXRAN_AGENT, "terminated timer thread\n");
|
||||
return NULL;
|
||||
@@ -230,45 +245,35 @@ err_code_t flexran_agent_create_timer(mid_t mod_id,
|
||||
|
||||
struct timesync *sync = ×ync[mod_id];
|
||||
pthread_mutex_lock(&sync->mutex_timer);
|
||||
if (sync->timer_num >= MAX_NUM_TIMERS) {
|
||||
if (sync->timer_num + sync->add_num >= MAX_NUM_TIMERS) {
|
||||
pthread_mutex_unlock(&sync->mutex_timer);
|
||||
LOG_E(FLEXRAN_AGENT, "maximum number of timers (%d) reached while adding timer %d\n",
|
||||
sync->timer_num, xid);
|
||||
sync->timer_num + sync->add_num, xid);
|
||||
free(t);
|
||||
return TIMER_SETUP_FAILED;
|
||||
}
|
||||
/* TODO check that xid does not exist? */
|
||||
t->next = sync->current + 1;
|
||||
t->next = sync->current + sf;
|
||||
if (sync->next <= sync->current || t->next < sync->next)
|
||||
sync->next = t->next;
|
||||
sync->timer[sync->timer_num] = t;
|
||||
sync->timer_num++;
|
||||
pthread_mutex_unlock(&sync->mutex_timer);
|
||||
LOG_D(FLEXRAN_AGENT, "added new timer xid %d for agent %d\n", xid, mod_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err_code_t flexran_agent_destroy_timers(mid_t mod_id) {
|
||||
struct timesync *sync = ×ync[mod_id];
|
||||
pthread_mutex_lock(&sync->mutex_timer);
|
||||
for (int i = sync->timer_num - 1; i < 0; --i) {
|
||||
flexran_agent_timer_remove_internal(sync, i);
|
||||
}
|
||||
sync->add_list[sync->add_num] = t;
|
||||
sync->add_num++;
|
||||
pthread_mutex_unlock(&sync->mutex_timer);
|
||||
LOG_I(FLEXRAN_AGENT, "added new timer xid %d for agent %d\n", xid, mod_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) {
|
||||
struct timesync *sync = ×ync[mod_id];
|
||||
pthread_mutex_lock(&sync->mutex_timer);
|
||||
for (int i = 0; i < sync->timer_num; ++i) {
|
||||
if (sync->timer[i]->xid == xid) {
|
||||
flexran_agent_timer_remove_internal(sync, i);
|
||||
pthread_mutex_lock(&sync->mutex_timer);
|
||||
sync->remove_list[sync->remove_num] = i;
|
||||
sync->remove_num++;
|
||||
pthread_mutex_unlock(&sync->mutex_timer);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&sync->mutex_timer);
|
||||
LOG_E(FLEXRAN_AGENT, "could not find timer %d\n", xid);
|
||||
return TIMER_ELEMENT_NOT_FOUND;
|
||||
}
|
||||
@@ -277,7 +282,8 @@ err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) {
|
||||
void flexran_agent_timer_remove_internal(struct timesync *sync, int index) {
|
||||
LOG_I(FLEXRAN_AGENT, "remove timer xid %d (index %d) for agent %d\n",
|
||||
sync->timer[index]->xid, index, sync->timer[index]->mod_id);
|
||||
flexran_agent_destroy_flexran_message(sync->timer[index]->msg);
|
||||
if (sync->timer[index]->msg)
|
||||
flexran_agent_destroy_flexran_message(sync->timer[index]->msg);
|
||||
free(sync->timer[index]);
|
||||
for (int i = index + 1; i < sync->timer_num; ++i)
|
||||
sync->timer[i - 1] = sync->timer[i];
|
||||
|
||||
@@ -61,9 +61,6 @@ err_code_t flexran_agent_create_timer(mid_t mod_id,
|
||||
flexran_agent_timer_callback_t cb,
|
||||
Protocol__FlexranMessage *msg);
|
||||
|
||||
/* Destroy all existing timers */
|
||||
err_code_t flexran_agent_destroy_timers(mid_t mod_id);
|
||||
|
||||
/* Destroy the timer for task with id xid */
|
||||
err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid);
|
||||
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file imsi.c
|
||||
* \brief flexran IMSI UE-slice association app
|
||||
* \author Robert Schmidt, Firas Abdeljelil
|
||||
* \date 2020
|
||||
* \version 0.1
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <regex.h>
|
||||
#include "flexran_agent_common.h"
|
||||
#include "flexran_agent_async.h"
|
||||
#include "flexran_agent_extern.h"
|
||||
#include "flexran_agent_timer.h"
|
||||
#include "flexran_agent_defs.h"
|
||||
#include "flexran_agent_net_comm.h"
|
||||
#include "flexran_agent_ran_api.h"
|
||||
#include "flexran_agent_phy.h"
|
||||
#include "flexran_agent_mac.h"
|
||||
#include "flexran_agent_rrc.h"
|
||||
#include "flexran_agent_pdcp.h"
|
||||
#include "flexran_agent_s1ap.h"
|
||||
#include "flexran_agent_app.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "assertions.h"
|
||||
#include "queue.h"
|
||||
typedef struct Map_regex_slice slist_data_t;
|
||||
struct Map_regex_slice {
|
||||
char regex_[30] ;
|
||||
int slice_dl;
|
||||
int slice_ul;
|
||||
regex_t regex;
|
||||
SLIST_ENTRY (Map_regex_slice) entries;
|
||||
};
|
||||
bool reconfig = false;
|
||||
int ue[MAX_MOBILES_PER_ENB]={ [0 ... MAX_MOBILES_PER_ENB - 1] = -1 };
|
||||
|
||||
SLIST_HEAD(slisthead, Map_regex_slice) head;
|
||||
|
||||
int dump_list(void) {
|
||||
int len = 1;
|
||||
slist_data_t *datap = NULL;
|
||||
SLIST_FOREACH(datap, &head, entries) {
|
||||
LOG_W(FLEXRAN_AGENT, "%d: regex %s DL %d UL %d\n", len++, datap->regex_,
|
||||
datap->slice_dl, datap->slice_ul);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void add(char *regex, int dl, int ul) {
|
||||
slist_data_t *datap = malloc(sizeof(slist_data_t));
|
||||
if (!datap) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot allocate memory for slist_data_t\n");
|
||||
return;
|
||||
}
|
||||
strcpy(datap->regex_, regex);
|
||||
datap->slice_dl = dl;
|
||||
datap->slice_ul = ul;
|
||||
regcomp(&datap->regex, datap->regex_, 0);
|
||||
SLIST_INSERT_HEAD(&head, datap, entries);
|
||||
if (ul==-1)
|
||||
LOG_I(FLEXRAN_AGENT, "added new element to list: regex %s slice DL %d\n" ,regex, dl);
|
||||
else if (dl==-1)
|
||||
LOG_I(FLEXRAN_AGENT, "added new element to list: regex %s slice UL %d\n" ,regex, ul);
|
||||
else
|
||||
LOG_I(FLEXRAN_AGENT, "added new element to list: regex %s slice DL %d UL %d\n",
|
||||
regex, dl, ul);
|
||||
}
|
||||
void remove_(char *regex) {
|
||||
slist_data_t *datap = NULL;
|
||||
SLIST_FOREACH(datap, &head, entries) {
|
||||
if (strcmp(datap->regex_, regex) == 0) {
|
||||
SLIST_REMOVE(&head, datap, Map_regex_slice, entries);
|
||||
if (datap->slice_dl==-1)
|
||||
LOG_I(FLEXRAN_AGENT, "removed element from list: regex %s slice UL %d\n",datap->regex_, datap->slice_ul);
|
||||
else if (datap->slice_ul==-1)
|
||||
LOG_I(FLEXRAN_AGENT, "removed element from list: regex %s slice DL %d\n",datap->regex_, datap->slice_dl);
|
||||
else
|
||||
LOG_I(FLEXRAN_AGENT, "removed element from list: regex %s slice DL %d UL %d\n",
|
||||
datap->regex_, datap->slice_dl, datap->slice_ul);
|
||||
regfree(&datap->regex);
|
||||
free(datap);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG_E(FLEXRAN_AGENT, "no regex %s found in list\n", regex);
|
||||
}
|
||||
|
||||
Protocol__FlexranMessage *matching_tick(
|
||||
mid_t mod_id,
|
||||
const Protocol__FlexranMessage *msg) {
|
||||
const int num = flexran_get_mac_num_ues(mod_id);
|
||||
for (int i = 0; i < num; i++) {
|
||||
int ue_id = flexran_get_mac_ue_id(mod_id, i);
|
||||
if (ue[ue_id] >= 0 && !reconfig)
|
||||
continue;
|
||||
rnti_t rnti = flexran_get_mac_ue_crnti(mod_id, ue_id);
|
||||
uint64_t imsi = flexran_get_ue_imsi(mod_id, rnti);
|
||||
char snum[20];
|
||||
sprintf(snum, "%" PRIu64, imsi);
|
||||
slist_data_t *datap = NULL;
|
||||
SLIST_FOREACH(datap, &head, entries) {
|
||||
if (regexec(&datap->regex, snum, 0, NULL, 0) == 0) {
|
||||
|
||||
int dl = datap->slice_dl;
|
||||
if (dl >= 0 && dl != flexran_get_ue_dl_slice_id(mod_id, ue_id)) {
|
||||
int ra = flexran_set_ue_dl_slice_id(mod_id, ue_id, dl);
|
||||
if (ra)
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"RNTI %04x/IMSI %s in the slice_dl %d\n",
|
||||
rnti,
|
||||
snum,
|
||||
dl);
|
||||
else
|
||||
LOG_W(FLEXRAN_AGENT, "No such DL slice %d\n", dl);
|
||||
}
|
||||
|
||||
int ul = datap->slice_ul;
|
||||
if (ul >= 0 && ul != flexran_get_ue_ul_slice_id(mod_id, ue_id)) {
|
||||
int rb = flexran_set_ue_ul_slice_id(mod_id, ue_id, ul);
|
||||
if (rb)
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"RNTI %04x/IMSI %s in the slice_ul %d\n",
|
||||
rnti,
|
||||
snum,
|
||||
ul);
|
||||
else
|
||||
LOG_W(FLEXRAN_AGENT, "No such DL slice %d\n", dl);
|
||||
}
|
||||
}
|
||||
}
|
||||
ue[ue_id] = ue_id;
|
||||
}
|
||||
reconfig = false;
|
||||
return NULL;
|
||||
}
|
||||
void add_param(Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, int n_p) {
|
||||
char s[30];
|
||||
reconfig = true;
|
||||
bool supp=false;
|
||||
bool sl_E=false;
|
||||
int dl=-1;
|
||||
int ul=-1;
|
||||
slist_data_t *datap = NULL;
|
||||
for (int i = 0; i < n_p; ++i) {
|
||||
switch (p[i]->value->param_case) {
|
||||
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM__NOT_SET:
|
||||
LOG_I(FLEXRAN_AGENT, " param %s is not set\n", p[i]->key);
|
||||
break;
|
||||
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_INTEGER:
|
||||
if( strcmp(p[i]->key, "slice_dl")==0)
|
||||
dl= p[i]->value->integer;
|
||||
else
|
||||
ul= p[i]->value->integer;
|
||||
sl_E=true;
|
||||
break;
|
||||
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_STR:
|
||||
strcpy(s,p[i]->value->str);
|
||||
break;
|
||||
default:
|
||||
LOG_W(FLEXRAN_AGENT, " type of param %s is unknown\n", p[i]->key);
|
||||
break;
|
||||
};
|
||||
}
|
||||
if (!SLIST_EMPTY(&head)){
|
||||
SLIST_FOREACH(datap, &head, entries) {
|
||||
if (strcmp(datap->regex_, s) == 0) {
|
||||
if (datap->slice_dl!=dl || datap->slice_ul!=ul)
|
||||
supp=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sl_E==false)
|
||||
remove_(s);
|
||||
else {
|
||||
if (supp==true)
|
||||
remove_(s);
|
||||
add(s,dl,ul);
|
||||
}
|
||||
/* re-verify all UEs again */
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i)
|
||||
ue[i] = -1;
|
||||
}
|
||||
/* imsi_start: entry point for imsi app. Installs a callback using the timer
|
||||
* API to have function imsi_tick() called every 5s */
|
||||
#define TIMER 32
|
||||
int imsi_start(mid_t mod_id,
|
||||
Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p,
|
||||
int n_p)
|
||||
{
|
||||
LOG_W(FLEXRAN_AGENT, "%s(): enable IMSI app timer\n", __func__);
|
||||
flexran_agent_create_timer(mod_id,
|
||||
500,
|
||||
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC,
|
||||
TIMER,
|
||||
matching_tick,
|
||||
NULL);
|
||||
SLIST_INIT(&head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int imsi_reconfig(mid_t mod_id,
|
||||
Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p,
|
||||
int n_p)
|
||||
{
|
||||
add_param(p, n_p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* stop function: cleans up before app can be unloaded. Here: stop the timer */
|
||||
int imsi_stop(mid_t mod_id) {
|
||||
LOG_W(FLEXRAN_AGENT, "%s(): disable IMSI app timer\n", __func__);
|
||||
flexran_agent_destroy_timer(mod_id, TIMER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* app definition. visibility should be set to default so this symbol is
|
||||
* reachable from outside */
|
||||
flexran_agent_app_t __attribute__ ((visibility ("default"))) app = {
|
||||
.start = imsi_start,
|
||||
.reconfig = imsi_reconfig,
|
||||
.stop = imsi_stop
|
||||
};
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file sample.c
|
||||
* \brief flexran sample app
|
||||
* \author Robert Schmidt
|
||||
* \date 2020
|
||||
* \version 0.1
|
||||
*/
|
||||
|
||||
#include "flexran_agent_common.h"
|
||||
#include "flexran_agent_async.h"
|
||||
#include "flexran_agent_extern.h"
|
||||
#include "flexran_agent_timer.h"
|
||||
#include "flexran_agent_defs.h"
|
||||
#include "flexran_agent_net_comm.h"
|
||||
#include "flexran_agent_ran_api.h"
|
||||
#include "flexran_agent_phy.h"
|
||||
#include "flexran_agent_mac.h"
|
||||
#include "flexran_agent_rrc.h"
|
||||
#include "flexran_agent_pdcp.h"
|
||||
#include "flexran_agent_s1ap.h"
|
||||
#include "flexran_agent_app.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "assertions.h"
|
||||
|
||||
/* callback to be called for event: shows exemplary variable use and use of RAN
|
||||
* API */
|
||||
int tick;
|
||||
Protocol__FlexranMessage *sample_tick(
|
||||
mid_t mod_id,
|
||||
const Protocol__FlexranMessage *msg) {
|
||||
tick++;
|
||||
const int num = flexran_get_mac_num_ues(mod_id);
|
||||
LOG_I(FLEXRAN_AGENT, "%s(): tick %d number UEs %d\n", __func__, tick, num);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void print_param(Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, int n_p) {
|
||||
LOG_I(FLEXRAN_AGENT, "%s(): received %d parameters\n", __func__, n_p);
|
||||
for (int i = 0; i < n_p; ++i) {
|
||||
switch (p[i]->value->param_case) {
|
||||
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM__NOT_SET:
|
||||
LOG_I(FLEXRAN_AGENT, " param %s is not set\n", p[i]->key);
|
||||
break;
|
||||
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_INTEGER:
|
||||
LOG_I(FLEXRAN_AGENT, " param %s is %d\n", p[i]->key, p[i]->value->integer);
|
||||
break;
|
||||
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_FLOATING:
|
||||
LOG_I(FLEXRAN_AGENT, " param %s is %f\n", p[i]->key, p[i]->value->floating);
|
||||
break;
|
||||
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_BOOLEAN:
|
||||
LOG_I(FLEXRAN_AGENT, " param %s is %s\n", p[i]->key, p[i]->value->boolean ? "true" : "false");
|
||||
break;
|
||||
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_STR:
|
||||
LOG_I(FLEXRAN_AGENT, " param %s is %s\n", p[i]->key, p[i]->value->str);
|
||||
break;
|
||||
default:
|
||||
LOG_W(FLEXRAN_AGENT, " type of param %s is unknown\n", p[i]->key);
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* sa_start: entry point for sample app. Installs a callback using the timer
|
||||
* API to have function sample_tick() called every 5s */
|
||||
#define TIMER 22
|
||||
int sa_start(mid_t mod_id,
|
||||
Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p,
|
||||
int n_p) {
|
||||
LOG_W(FLEXRAN_AGENT, "%s(): enable sample app timer\n", __func__);
|
||||
flexran_agent_create_timer(mod_id,
|
||||
5000,
|
||||
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC,
|
||||
TIMER,
|
||||
sample_tick,
|
||||
NULL);
|
||||
print_param(p, n_p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sa_reconfig(mid_t mod_id,
|
||||
Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p,
|
||||
int n_p)
|
||||
{
|
||||
print_param(p, n_p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* stop function: cleans up before app can be unloaded. Here: stop the timer */
|
||||
int sa_stop(mid_t mod_id) {
|
||||
LOG_W(FLEXRAN_AGENT, "%s(): disable sample app timer\n", __func__);
|
||||
flexran_agent_destroy_timer(mod_id, TIMER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* app definition. visibility should be set to default so this symbol is
|
||||
* reachable from outside */
|
||||
flexran_agent_app_t __attribute__ ((visibility ("default"))) app = {
|
||||
.start = sa_start,
|
||||
.reconfig = sa_reconfig,
|
||||
.stop = sa_stop
|
||||
};
|
||||
@@ -153,7 +153,7 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) {
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon = CALLOC(1,sizeof(NR_SetupRelease_RACH_ConfigCommon_t));
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->present = NR_SetupRelease_RACH_ConfigCommon_PR_setup;
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_RACH_ConfigCommon));
|
||||
// scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles = CALLOC(1,sizeof(long));
|
||||
// scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles = CALLOC(1,sizeof(long));
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB = CALLOC(1,sizeof(struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB));
|
||||
// scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->groupBconfigured = CALLOC(1,sizeof(struct NR_RACH_ConfigCommon__groupBconfigured));
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB = CALLOC(1,sizeof(NR_RSRP_Range_t));
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
|
||||
|
||||
#include "common/ran_context.h"
|
||||
extern FILL_UL_INFO_MUTEX_t fill_ul_mutex;
|
||||
extern void openair_rrc_top_init_ue( int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active);
|
||||
|
||||
void dl_phy_sync_success(module_id_t module_idP, frame_t frameP, unsigned char eNB_index, uint8_t first_sync) { //init as MR
|
||||
@@ -90,16 +89,6 @@ mac_top_init_ue(int eMBMS_active, char *uecap_xer,
|
||||
UE_mac_inst = NULL;
|
||||
}
|
||||
|
||||
// mutex below are used for multiple UE's L2 FAPI simulation.
|
||||
if (NFAPI_MODE == NFAPI_UE_STUB_PNF) {
|
||||
pthread_mutex_init(&fill_ul_mutex.rx_mutex,NULL);
|
||||
pthread_mutex_init(&fill_ul_mutex.crc_mutex,NULL);
|
||||
pthread_mutex_init(&fill_ul_mutex.sr_mutex,NULL);
|
||||
pthread_mutex_init(&fill_ul_mutex.harq_mutex,NULL);
|
||||
pthread_mutex_init(&fill_ul_mutex.cqi_mutex,NULL);
|
||||
pthread_mutex_init(&fill_ul_mutex.rach_mutex,NULL);
|
||||
}
|
||||
|
||||
LOG_I(MAC, "[MAIN] calling RRC\n");
|
||||
openair_rrc_top_init_ue(eMBMS_active, uecap_xer, cba_group_active,
|
||||
HO_active);
|
||||
|
||||
+107
-151
@@ -69,6 +69,70 @@ int get_rbg_size_last(module_id_t Mod_id, int CC_id) {
|
||||
return RBGsize;
|
||||
}
|
||||
|
||||
bool try_allocate_harq_retransmission(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
int UE_id,
|
||||
int start_rbg,
|
||||
int *n_rbg_sched,
|
||||
uint8_t *rbgalloc_mask) {
|
||||
const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
const int RBGsize = get_min_rb_unit(Mod_id, CC_id);
|
||||
const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id);
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
// check whether there are HARQ retransmissions
|
||||
const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
||||
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
// retransmission: allocate
|
||||
const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid];
|
||||
if (nb_rb == 0) {
|
||||
return false;
|
||||
}
|
||||
int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize;
|
||||
// needs more RBGs than we can allocate
|
||||
if (nb_rbg > *n_rbg_sched) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs more RBGs (%d) than we have (%d)\n",
|
||||
UE_id, nb_rbg, *n_rbg_sched);
|
||||
return false;
|
||||
}
|
||||
// ensure that the number of RBs can be contained by the RBGs (!), i.e.
|
||||
// if we allocate the last RBG this one should have the full RBGsize
|
||||
if ((nb_rb % RBGsize) == 0 && nb_rbg == *n_rbg_sched
|
||||
&& rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n",
|
||||
UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize);
|
||||
return false;
|
||||
}
|
||||
const uint8_t cqi = ue_ctrl->dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0) { // cannot allocate CCE
|
||||
LOG_D(MAC, "cannot allocate UE %d: no CCE can be allocated\n", UE_id);
|
||||
return false;
|
||||
}
|
||||
ue_ctrl->pre_dci_dl_pdu_idx = idx;
|
||||
// retransmissions: directly allocate
|
||||
*n_rbg_sched -= nb_rbg;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb;
|
||||
for (; nb_rbg > 0; start_rbg++) {
|
||||
if (!rbgalloc_mask[start_rbg])
|
||||
continue;
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][start_rbg] = 1;
|
||||
rbgalloc_mask[start_rbg] = 0;
|
||||
nb_rbg--;
|
||||
}
|
||||
LOG_D(MAC,
|
||||
"%4d.%d n_rbg_sched %d after retransmission reservation for UE %d "
|
||||
"retx nb_rb %d pre_nb_available_rbs %d\n",
|
||||
frame, subframe, *n_rbg_sched, UE_id,
|
||||
UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid],
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id]);
|
||||
return true;
|
||||
}
|
||||
|
||||
void *rr_dl_setup(void) {
|
||||
void *data = malloc(sizeof(int));
|
||||
*(int *) data = 0;
|
||||
@@ -115,64 +179,25 @@ int rr_dl_run(module_id_t Mod_id,
|
||||
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const uint8_t round = ue_ctrl->round[CC_id][harq_pid];
|
||||
if (round != 8) { // retransmission: allocate
|
||||
const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid];
|
||||
if (nb_rb == 0)
|
||||
goto skip_ue;
|
||||
int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize;
|
||||
// needs more RBGs than we can allocate
|
||||
if (nb_rbg > n_rbg_sched) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs more RBGs (%d) than we have (%d)\n",
|
||||
UE_id, nb_rbg, n_rbg_sched);
|
||||
goto skip_ue;
|
||||
if (round != 8) {
|
||||
bool r = try_allocate_harq_retransmission(Mod_id, CC_id, frame, subframe,
|
||||
UE_id, rbg, &n_rbg_sched,
|
||||
rbgalloc_mask);
|
||||
if (r) {
|
||||
/* if there are no more RBG to give, return */
|
||||
if (n_rbg_sched <= 0)
|
||||
return 0;
|
||||
max_num_ue--;
|
||||
if (max_num_ue == 0)
|
||||
return n_rbg_sched;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
}
|
||||
// ensure that the number of RBs can be contained by the RBGs (!), i.e.
|
||||
// if we allocate the last RBG this one should have the full RBGsize
|
||||
if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched
|
||||
&& rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n",
|
||||
UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize);
|
||||
goto skip_ue;
|
||||
}
|
||||
const uint8_t cqi = ue_ctrl->dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0)
|
||||
goto skip_ue; // cannot allocate CCE
|
||||
ue_ctrl->pre_dci_dl_pdu_idx = idx;
|
||||
// retransmissions: directly allocate
|
||||
n_rbg_sched -= nb_rbg;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb;
|
||||
for (; nb_rbg > 0; rbg++) {
|
||||
if (!rbgalloc_mask[rbg])
|
||||
continue;
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
nb_rbg--;
|
||||
}
|
||||
LOG_D(MAC,
|
||||
"%4d.%d n_rbg_sched %d after retransmission reservation for UE %d "
|
||||
"round %d retx nb_rb %d pre_nb_available_rbs %d\n",
|
||||
frame, subframe, n_rbg_sched, UE_id, round,
|
||||
UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid],
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id]);
|
||||
/* if there are no more RBG to give, return */
|
||||
if (n_rbg_sched <= 0)
|
||||
return 0;
|
||||
max_num_ue--;
|
||||
/* if there are no UEs that can be allocated anymore, return */
|
||||
if (max_num_ue == 0)
|
||||
return n_rbg_sched;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
} else {
|
||||
if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0) {
|
||||
*cur_UE = UE_id;
|
||||
cur_UE = &UE_sched.next[UE_id];
|
||||
}
|
||||
}
|
||||
|
||||
skip_ue:
|
||||
UE_id = next_ue_list_looped(UE_list, UE_id);
|
||||
} while (UE_id != *start_ue);
|
||||
*cur_UE = -1; // mark end
|
||||
@@ -187,11 +212,12 @@ skip_ue:
|
||||
cur_UE = &UE_sched.head;
|
||||
while (*cur_UE >= 0 && max_num_ue > 0) {
|
||||
const int UE_id = *cur_UE;
|
||||
cur_UE = &UE_sched.next[UE_id]; // go to next
|
||||
const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0) {
|
||||
LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", UE_id);
|
||||
// SKIP this UE in the list by marking the next as the current
|
||||
*cur_UE = UE_sched.next[UE_id];
|
||||
continue;
|
||||
}
|
||||
UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx;
|
||||
@@ -200,6 +226,7 @@ skip_ue:
|
||||
const uint32_t B = UE_info->UE_template[CC_id][UE_id].dl_buffer_total;
|
||||
rb_required[UE_id] = find_nb_rb_DL(mcs, B, n_rbg_sched * RBGsize, RBGsize);
|
||||
max_num_ue--;
|
||||
cur_UE = &UE_sched.next[UE_id]; // go to next
|
||||
}
|
||||
*cur_UE = -1; // not all UEs might be allocated, mark end
|
||||
|
||||
@@ -284,56 +311,19 @@ int pf_wbcqi_dl_run(module_id_t Mod_id,
|
||||
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const uint8_t round = ue_ctrl->round[CC_id][harq_pid];
|
||||
if (round != 8) { // retransmission: allocate
|
||||
const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid];
|
||||
if (nb_rb == 0)
|
||||
continue;
|
||||
int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize;
|
||||
// needs more RBGs than we can allocate
|
||||
if (nb_rbg > n_rbg_sched) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs more RBGs (%d) than we have (%d)\n",
|
||||
UE_id, nb_rbg, n_rbg_sched);
|
||||
continue;
|
||||
if (round != 8) {
|
||||
bool r = try_allocate_harq_retransmission(Mod_id, CC_id, frame, subframe,
|
||||
UE_id, rbg, &n_rbg_sched,
|
||||
rbgalloc_mask);
|
||||
if (r) {
|
||||
/* if there are no more RBG to give, return */
|
||||
if (n_rbg_sched <= 0)
|
||||
return 0;
|
||||
max_num_ue--;
|
||||
if (max_num_ue == 0)
|
||||
return n_rbg_sched;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
}
|
||||
// ensure that the number of RBs can be contained by the RBGs (!), i.e.
|
||||
// if we allocate the last RBG this one should have the full RBGsize
|
||||
if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched
|
||||
&& rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n",
|
||||
UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize);
|
||||
continue;
|
||||
}
|
||||
const uint8_t cqi = ue_ctrl->dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0)
|
||||
continue; // cannot allocate CCE
|
||||
ue_ctrl->pre_dci_dl_pdu_idx = idx;
|
||||
// retransmissions: directly allocate
|
||||
n_rbg_sched -= nb_rbg;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb;
|
||||
for (; nb_rbg > 0; rbg++) {
|
||||
if (!rbgalloc_mask[rbg])
|
||||
continue;
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
nb_rbg--;
|
||||
}
|
||||
LOG_D(MAC,
|
||||
"%4d.%d n_rbg_sched %d after retransmission reservation for UE %d "
|
||||
"round %d retx nb_rb %d pre_nb_available_rbs %d\n",
|
||||
frame, subframe, n_rbg_sched, UE_id, round,
|
||||
UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid],
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id]);
|
||||
/* if there are no more RBG to give, return */
|
||||
if (n_rbg_sched <= 0)
|
||||
return 0;
|
||||
max_num_ue--;
|
||||
/* if there are no UEs that can be allocated anymore, return */
|
||||
if (max_num_ue == 0)
|
||||
return n_rbg_sched;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
} else {
|
||||
if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0)
|
||||
continue;
|
||||
@@ -436,56 +426,19 @@ int mt_wbcqi_dl_run(module_id_t Mod_id,
|
||||
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const uint8_t round = ue_ctrl->round[CC_id][harq_pid];
|
||||
if (round != 8) { // retransmission: allocate
|
||||
const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid];
|
||||
if (nb_rb == 0)
|
||||
continue;
|
||||
int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize;
|
||||
// needs more RBGs than we can allocate
|
||||
if (nb_rbg > n_rbg_sched) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs more RBGs (%d) than we have (%d)\n",
|
||||
UE_id, nb_rbg, n_rbg_sched);
|
||||
continue;
|
||||
if (round != 8) {
|
||||
bool r = try_allocate_harq_retransmission(Mod_id, CC_id, frame, subframe,
|
||||
UE_id, rbg, &n_rbg_sched,
|
||||
rbgalloc_mask);
|
||||
if (r) {
|
||||
/* if there are no more RBG to give, return */
|
||||
if (n_rbg_sched <= 0)
|
||||
return 0;
|
||||
max_num_ue--;
|
||||
if (max_num_ue == 0)
|
||||
return n_rbg_sched;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
}
|
||||
// ensure that the number of RBs can be contained by the RBGs (!), i.e.
|
||||
// if we allocate the last RBG this one should have the full RBGsize
|
||||
if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched
|
||||
&& rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n",
|
||||
UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize);
|
||||
continue;
|
||||
}
|
||||
const uint8_t cqi = ue_ctrl->dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0)
|
||||
continue; // cannot allocate CCE
|
||||
ue_ctrl->pre_dci_dl_pdu_idx = idx;
|
||||
// retransmissions: directly allocate
|
||||
n_rbg_sched -= nb_rbg;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb;
|
||||
for (; nb_rbg > 0; rbg++) {
|
||||
if (!rbgalloc_mask[rbg])
|
||||
continue;
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
nb_rbg--;
|
||||
}
|
||||
LOG_D(MAC,
|
||||
"%4d.%d n_rbg_sched %d after retransmission reservation for UE %d "
|
||||
"round %d retx nb_rb %d pre_nb_available_rbs %d\n",
|
||||
frame, subframe, n_rbg_sched, UE_id, round,
|
||||
UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid],
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id]);
|
||||
/* if there are no more RBG to give, return */
|
||||
if (n_rbg_sched <= 0)
|
||||
return 0;
|
||||
max_num_ue--;
|
||||
/* if there are no UEs that can be allocated anymore, return */
|
||||
if (max_num_ue == 0)
|
||||
return n_rbg_sched;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
} else {
|
||||
if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0)
|
||||
continue;
|
||||
@@ -942,7 +895,10 @@ int rr_ul_run(module_id_t Mod_id,
|
||||
&tx_power);
|
||||
|
||||
UE_template->pre_assigned_mcs_ul = mcs;
|
||||
rb_idx_required[UE_id] = rb_table_index;
|
||||
/* rb_idx_given >= 22: apparently the PHY cannot support more than 48
|
||||
* RBs in the uplink. Hence, we limit every UE to 48 RBs, which is at
|
||||
* index 22 */
|
||||
rb_idx_required[UE_id] = min(22, rb_table_index);
|
||||
//UE_template->pre_allocated_nb_rb_ul = rb_table[rb_table_index];
|
||||
/* only print log when PHR changed */
|
||||
static int phr = 0;
|
||||
|
||||
@@ -336,6 +336,8 @@ void static_dl(module_id_t mod_id,
|
||||
rbgalloc_slice_mask[rbg] = rbgalloc_mask[rbg];
|
||||
n_rbg_sched += rbgalloc_mask[rbg];
|
||||
}
|
||||
if (n_rbg_sched == 0) /* no free RBGs, e.g., taken by RA */
|
||||
continue;
|
||||
|
||||
s->s[i]->dl_algo.run(mod_id,
|
||||
CC_id,
|
||||
@@ -445,6 +447,8 @@ void static_ul(module_id_t mod_id,
|
||||
}
|
||||
if (!last_rb_blocked)
|
||||
rbs[n_contig - 1].length = p->posHigh - rbs[n_contig - 1].start + 1;
|
||||
if (n_contig == 1 && rbs[0].length == 0) /* no RBs, e.g., taken by RA */
|
||||
continue;
|
||||
|
||||
s->s[i]->ul_algo.run(mod_id,
|
||||
CC_id,
|
||||
|
||||
@@ -48,8 +48,7 @@ uint16_t NCS_restricted_TypeB_delta_f_RA_5[14] = {36,57,60,63,65,68,71,77,81,8
|
||||
// Table 6.3.3.1-7 (38.211) NCS for preamble formats with delta_f_RA = 15 * 2mu KHz where mu = {0,1,2,3}
|
||||
uint16_t NCS_unrestricted_delta_f_RA_15[16] = {0,2,4,6,8,10,12,13,15,17,19,23,27,34,46,69};
|
||||
|
||||
const char *prachfmt[]={"A1","A2","A3","B1","B2","B3","B4","C0","C2"};
|
||||
const char *prachfmt03[]={"0","1","2","3"};
|
||||
const char *prachfmt[]={"0","1","2","3", "A1","A2","A3","B1","B4","C0","C2","A1/B1","A2/B2","A3/B3"};
|
||||
|
||||
uint16_t get_NCS(uint8_t index, uint16_t format0, uint8_t restricted_set_config) {
|
||||
|
||||
@@ -86,7 +85,71 @@ uint16_t get_NCS(uint8_t index, uint16_t format0, uint8_t restricted_set_config)
|
||||
}
|
||||
}
|
||||
|
||||
//38.211 Table 6.3.3.2-1
|
||||
int16_t table_6_3_3_2_1[16][5] = {
|
||||
//Length_RA, delta_f_RA_PRACH, delta_f_PUSCH, N_RA_RB, kbar
|
||||
{ 839, 1.25, 15, 6, 7},
|
||||
{ 839, 1.25, 30, 3, 1},
|
||||
{ 839, 1.25, 60, 2, 133},
|
||||
{ 839, 5, 15, 24, 12},
|
||||
{ 839, 5, 30, 12, 10},
|
||||
{ 839, 5, 60, 6, 7},
|
||||
{ 139, 15, 15, 12, 2},
|
||||
{ 139, 15, 30, 6, 2},
|
||||
{ 139, 15, 60, 3, 2},
|
||||
{ 139, 30, 15, 24, 2},
|
||||
{ 139, 30, 30, 12, 2},
|
||||
{ 139, 30, 60, 6, 2},
|
||||
{ 139, 60, 60, 12, 2},
|
||||
{ 139, 60, 120, 6, 2},
|
||||
{ 139, 120, 60, 24, 2},
|
||||
{ 139, 120, 120, 12, 2}
|
||||
};
|
||||
|
||||
/* Function to get number of RBs required for prach occasion based on
|
||||
* 38.211 Table 6.3.3.2-1 */
|
||||
int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH) {
|
||||
|
||||
int8_t index = 0;
|
||||
switch(delta_f_RA_PRACH) {
|
||||
case 0 : index = 6;
|
||||
if (delta_f_PUSCH == 0)
|
||||
index += 0;
|
||||
else if(delta_f_PUSCH == 1)
|
||||
index += 1;
|
||||
else
|
||||
index += 2;
|
||||
break;
|
||||
|
||||
case 1 : index = 9;
|
||||
if (delta_f_PUSCH == 0)
|
||||
index += 0;
|
||||
else if(delta_f_PUSCH == 1)
|
||||
index += 1;
|
||||
else
|
||||
index += 2;
|
||||
break;
|
||||
|
||||
case 2 : index = 11;
|
||||
if (delta_f_PUSCH == 2)
|
||||
index += 0;
|
||||
else
|
||||
index += 1;
|
||||
break;
|
||||
|
||||
case 3: index = 13;
|
||||
if (delta_f_PUSCH == 2)
|
||||
index += 0;
|
||||
else
|
||||
index += 1;
|
||||
break;
|
||||
|
||||
default : index = 10;/*30khz prach scs and 30khz pusch scs*/
|
||||
|
||||
}
|
||||
|
||||
return table_6_3_3_2_1[index][3];
|
||||
}
|
||||
// Table 6.3.3.2-2: Random access configurations for FR1 and paired spectrum/supplementary uplink
|
||||
// the column 5, (SFN_nbr is a bitmap where we set bit to '1' in the position of the subframe where the RACH can be sent.
|
||||
// E.g. in row 4, and column 5 we have set value 512 ('1000000000') which means RACH can be sent at subframe 9.
|
||||
@@ -955,6 +1018,162 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss,
|
||||
}
|
||||
}
|
||||
|
||||
int get_nr_prach_occasion_info_from_index(uint8_t index,
|
||||
uint32_t pointa,
|
||||
uint8_t mu,
|
||||
uint8_t unpaired,
|
||||
uint16_t *format,
|
||||
uint8_t *start_symbol,
|
||||
uint8_t *N_t_slot,
|
||||
uint8_t *N_dur,
|
||||
uint8_t *N_RA_slot,
|
||||
uint16_t *N_RA_sfn,
|
||||
uint8_t *max_association_period) {
|
||||
|
||||
int x;
|
||||
int64_t s_map;
|
||||
uint8_t format2 = 0xff;
|
||||
if (pointa > 2016666) { //FR2
|
||||
x = table_6_3_3_2_4_prachConfig_Index[index][2];
|
||||
s_map = table_6_3_3_2_4_prachConfig_Index[index][5];
|
||||
for(int i = 0; i < 64 ;i++) {
|
||||
if ( (s_map >> i) & 0x01) {
|
||||
(*N_RA_sfn)++;
|
||||
}
|
||||
}
|
||||
*N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe
|
||||
*max_association_period = 160/(x * 10);
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
*start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6];//multiple prach occasions in diff slot
|
||||
*N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8];
|
||||
*N_dur = table_6_3_3_2_4_prachConfig_Index[index][9];
|
||||
if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1];
|
||||
|
||||
*format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_D(MAC,"Getting Total PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n",
|
||||
index,
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur,
|
||||
*N_RA_sfn);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
|
||||
if (unpaired) {
|
||||
x = table_6_3_3_2_3_prachConfig_Index[index][2];
|
||||
s_map = table_6_3_3_2_3_prachConfig_Index[index][4];
|
||||
for(int i = 0; i < 64 ;i++) {
|
||||
if ( (s_map >> i) & 0x01) {
|
||||
(*N_RA_sfn)++;
|
||||
}
|
||||
}
|
||||
*N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; // Number of RACH slots within a subframe
|
||||
*max_association_period = 160/(x * 10);
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
*start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5];
|
||||
*N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7];
|
||||
*N_dur = table_6_3_3_2_3_prachConfig_Index[index][8];
|
||||
if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1];
|
||||
*format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_I(MAC,"Getting Total PRACH info from index %d (col %lu ) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n",
|
||||
index, table_6_3_3_2_3_prachConfig_Index[index][6],
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur,
|
||||
*N_RA_sfn);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else { // FDD
|
||||
x = table_6_3_3_2_2_prachConfig_Index[index][2];
|
||||
s_map = table_6_3_3_2_2_prachConfig_Index[index][4];
|
||||
*N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6];
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
*start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5];
|
||||
*N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7];
|
||||
*N_dur = table_6_3_3_2_2_prachConfig_Index[index][8];
|
||||
if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[index][1];
|
||||
*format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_D(MAC,"Getting Total PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n",
|
||||
index,
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t get_nr_prach_duration(uint8_t prach_format){
|
||||
|
||||
switch(prach_format){
|
||||
|
||||
case 0: // format 0
|
||||
return 0;
|
||||
|
||||
case 1: // format 1
|
||||
return 0;
|
||||
|
||||
case 2: // format 2
|
||||
return 0;
|
||||
|
||||
case 3: // format 3
|
||||
return 0;
|
||||
|
||||
case 4: // format A1
|
||||
return 2;
|
||||
|
||||
case 5: // format A2
|
||||
return 4;
|
||||
|
||||
case 6: // format A3
|
||||
return 6;
|
||||
|
||||
case 7: // format B1
|
||||
return 2;
|
||||
|
||||
case 8: // format B4
|
||||
return 12;
|
||||
|
||||
case 9: // format C0
|
||||
return 2;
|
||||
|
||||
case 10: // format C2
|
||||
return 6;
|
||||
|
||||
case 11: // format A1/B1
|
||||
return 2;
|
||||
|
||||
case 12: // format A2/B2
|
||||
return 4;
|
||||
|
||||
case 13: // format A3/B3
|
||||
return 6;
|
||||
|
||||
default :
|
||||
AssertFatal(1==0,"Invalid Prach format\n");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int get_nr_prach_info_from_index(uint8_t index,
|
||||
int frame,
|
||||
int slot,
|
||||
@@ -964,7 +1183,10 @@ int get_nr_prach_info_from_index(uint8_t index,
|
||||
uint16_t *format,
|
||||
uint8_t *start_symbol,
|
||||
uint8_t *N_t_slot,
|
||||
uint8_t *N_dur) {
|
||||
uint8_t *N_dur,
|
||||
uint16_t *RA_sfn_index,
|
||||
uint8_t *N_RA_slot,
|
||||
uint8_t *config_period) {
|
||||
|
||||
int x,y;
|
||||
int64_t s_map;
|
||||
@@ -980,27 +1202,39 @@ int get_nr_prach_info_from_index(uint8_t index,
|
||||
if ( (frame%x)==y || (frame%x)==y2 ) {
|
||||
slot_60khz = slot >> (mu-2); // in table slots are numbered wrt 60kHz
|
||||
s_map = table_6_3_3_2_4_prachConfig_Index[index][5];
|
||||
if ((s_map >> slot_60khz) & 0x01 ) {
|
||||
for(int i = 0; i <= slot_60khz ;i++) {
|
||||
if ( (s_map >> i) & 0x01) {
|
||||
(*RA_sfn_index)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ((s_map>>slot_60khz)&0x01) ) {
|
||||
*N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe
|
||||
if (mu == 3) {
|
||||
if ( (table_6_3_3_2_4_prachConfig_Index[index][7] == 1) && (slot%2 == 0) )
|
||||
if ( (*N_RA_slot == 1) && (slot%2 == 0) )
|
||||
return 0; // no prach in even slots @ 120kHz for 1 prach per 60khz slot
|
||||
}
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
*config_period = x;
|
||||
*start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6];
|
||||
*N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8];
|
||||
*N_dur = table_6_3_3_2_4_prachConfig_Index[index][9];
|
||||
if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1];
|
||||
*format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame,
|
||||
slot,
|
||||
index,
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur);
|
||||
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u\n",
|
||||
frame,
|
||||
slot,
|
||||
index,
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur,
|
||||
*N_RA_slot,
|
||||
*RA_sfn_index);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -1018,27 +1252,40 @@ int get_nr_prach_info_from_index(uint8_t index,
|
||||
if ( (frame%x)==y ) {
|
||||
subframe = slot >> mu;
|
||||
s_map = table_6_3_3_2_3_prachConfig_Index[index][4];
|
||||
if ( (s_map>>subframe)&0x01 ) {
|
||||
if (mu == 1) {
|
||||
if ( (table_6_3_3_2_3_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) )
|
||||
return 0; // no prach in even slots @ 30kHz for 1 prach per subframe
|
||||
if ((s_map >> subframe) & 0x01 ) {
|
||||
for(int i = 0; i <= subframe ;i++) {
|
||||
if ( (s_map >> i) & 0x01) {
|
||||
(*RA_sfn_index)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( (s_map>>subframe)&0x01 ) {
|
||||
*N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; // Number of RACH slots within a subframe
|
||||
if (mu == 1) {
|
||||
if ( (*N_RA_slot <= 1) && (slot%2 == 0) )
|
||||
return 0; // no prach in even slots @ 30kHz for 1 prach per subframe
|
||||
}
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
*config_period = x;
|
||||
*start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5];
|
||||
*N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7];
|
||||
*N_dur = table_6_3_3_2_3_prachConfig_Index[index][8];
|
||||
if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1];
|
||||
*format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %ld) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame,
|
||||
slot,
|
||||
index, table_6_3_3_2_3_prachConfig_Index[index][6],
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur);
|
||||
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n",
|
||||
frame,
|
||||
slot,
|
||||
index,
|
||||
table_6_3_3_2_3_prachConfig_Index[index][6],
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur,
|
||||
*N_RA_slot,
|
||||
*RA_sfn_index);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -1066,15 +1313,16 @@ int get_nr_prach_info_from_index(uint8_t index,
|
||||
if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[index][1];
|
||||
*format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame,
|
||||
slot,
|
||||
index,
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur);
|
||||
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n",
|
||||
frame,
|
||||
slot,
|
||||
index,
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,24 @@ int get_nr_prach_info_from_index(uint8_t index,
|
||||
uint16_t *format,
|
||||
uint8_t *start_symbol,
|
||||
uint8_t *N_t_slot,
|
||||
uint8_t *N_dur);
|
||||
uint8_t *N_dur,
|
||||
uint16_t *RA_sfn_index,
|
||||
uint8_t *N_RA_slot,
|
||||
uint8_t *config_period);
|
||||
|
||||
int get_nr_prach_occasion_info_from_index(uint8_t index,
|
||||
uint32_t pointa,
|
||||
uint8_t mu,
|
||||
uint8_t unpaired,
|
||||
uint16_t *format,
|
||||
uint8_t *start_symbol,
|
||||
uint8_t *N_t_slot,
|
||||
uint8_t *N_dur,
|
||||
uint8_t *N_RA_slot,
|
||||
uint16_t *N_RA_sfn,
|
||||
uint8_t *max_association_period);
|
||||
|
||||
uint8_t get_nr_prach_duration(uint8_t prach_format);
|
||||
|
||||
uint8_t get_pusch_mcs_table(long *mcs_Table,
|
||||
int is_tp,
|
||||
@@ -125,4 +142,5 @@ int32_t get_l_prime(uint8_t duration_in_symbols, uint8_t mapping_type, pusch_dmr
|
||||
uint8_t get_L_ptrs(uint8_t mcs1, uint8_t mcs2, uint8_t mcs3, uint8_t I_mcs, uint8_t mcs_table);
|
||||
uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB);
|
||||
|
||||
int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH);
|
||||
#endif
|
||||
|
||||
@@ -54,13 +54,15 @@ void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pd
|
||||
|
||||
LOG_D(MAC,"Filling search candidates for DCI\n");
|
||||
|
||||
rel15->number_of_candidates=3;
|
||||
rel15->number_of_candidates=4;
|
||||
rel15->CCE[0]=0;
|
||||
rel15->L[0]=4;
|
||||
rel15->CCE[1]=4;
|
||||
rel15->L[1]=4;
|
||||
rel15->CCE[2]=8;
|
||||
rel15->L[2]=4;
|
||||
rel15->CCE[3]=12;
|
||||
rel15->L[3]=4;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1073,6 +1073,9 @@ void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) {
|
||||
|
||||
uint8_t config_index, mu, N_dur, N_t_slot, start_symbol;
|
||||
uint16_t RA_sfn_index;
|
||||
uint8_t N_RA_slot;
|
||||
uint8_t config_period;
|
||||
uint16_t format, format0, format1, ncs;
|
||||
int msg1_FDM, is_nr_prach_slot, fdm;
|
||||
|
||||
@@ -1109,7 +1112,10 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur);
|
||||
&N_dur,
|
||||
&RA_sfn_index,
|
||||
&N_RA_slot,
|
||||
&config_period);
|
||||
|
||||
if (is_nr_prach_slot && mac->ra_state == RA_UE_IDLE) {
|
||||
|
||||
@@ -1156,57 +1162,51 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
|
||||
if (format1 != 0xff) {
|
||||
switch(format0) { // dual PRACH format
|
||||
case 0xa1:
|
||||
prach_config_pdu->prach_format = 9;
|
||||
prach_config_pdu->prach_format = 11;
|
||||
break;
|
||||
case 0xa2:
|
||||
prach_config_pdu->prach_format = 10;
|
||||
prach_config_pdu->prach_format = 12;
|
||||
break;
|
||||
case 0xa3:
|
||||
prach_config_pdu->prach_format = 11;
|
||||
prach_config_pdu->prach_format = 13;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
|
||||
}
|
||||
} else {
|
||||
switch(format0) { // single PRACH format
|
||||
case 0xa1:
|
||||
case 0:
|
||||
prach_config_pdu->prach_format = 0;
|
||||
break;
|
||||
case 0xa2:
|
||||
case 1:
|
||||
prach_config_pdu->prach_format = 1;
|
||||
break;
|
||||
case 0xa3:
|
||||
case 2:
|
||||
prach_config_pdu->prach_format = 2;
|
||||
break;
|
||||
case 0xb1:
|
||||
case 3:
|
||||
prach_config_pdu->prach_format = 3;
|
||||
break;
|
||||
case 0xb2:
|
||||
case 0xa1:
|
||||
prach_config_pdu->prach_format = 4;
|
||||
break;
|
||||
case 0xb3:
|
||||
case 0xa2:
|
||||
prach_config_pdu->prach_format = 5;
|
||||
break;
|
||||
case 0xb4:
|
||||
case 0xa3:
|
||||
prach_config_pdu->prach_format = 6;
|
||||
break;
|
||||
case 0xc0:
|
||||
case 0xb1:
|
||||
prach_config_pdu->prach_format = 7;
|
||||
break;
|
||||
case 0xc2:
|
||||
case 0xb4:
|
||||
prach_config_pdu->prach_format = 8;
|
||||
break;
|
||||
case 0:
|
||||
// long formats are handled @ PHY
|
||||
case 0xc0:
|
||||
prach_config_pdu->prach_format = 9;
|
||||
break;
|
||||
case 1:
|
||||
// long formats are handled @ PHY
|
||||
break;
|
||||
case 2:
|
||||
// long formats are handled @ PHY
|
||||
break;
|
||||
case 3:
|
||||
// long formats are handled @ PHY
|
||||
case 0xc2:
|
||||
prach_config_pdu->prach_format = 10;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Invalid PRACH format");
|
||||
|
||||
@@ -150,6 +150,10 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
|
||||
cfg->ssb_config.ss_pbch_power.tl.tag = NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG;
|
||||
cfg->num_tlv++;
|
||||
|
||||
cfg->ssb_config.bch_payload.value = 1;
|
||||
cfg->ssb_config.bch_payload.tl.tag = NFAPI_NR_CONFIG_BCH_PAYLOAD_TAG;
|
||||
cfg->num_tlv++;
|
||||
|
||||
cfg->ssb_config.scs_common.value = *scc->ssbSubcarrierSpacing;
|
||||
cfg->ssb_config.scs_common.tl.tag = NFAPI_NR_CONFIG_SCS_COMMON_TAG;
|
||||
cfg->num_tlv++;
|
||||
@@ -173,6 +177,9 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
|
||||
cfg->prach_config.restricted_set_config.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig;
|
||||
cfg->prach_config.restricted_set_config.tl.tag = NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG;
|
||||
cfg->num_tlv++;
|
||||
cfg->prach_config.prach_ConfigurationIndex.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
cfg->prach_config.prach_ConfigurationIndex.tl.tag = NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG;
|
||||
cfg->num_tlv++;
|
||||
|
||||
switch (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM) {
|
||||
case 0 :
|
||||
@@ -193,26 +200,30 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
|
||||
cfg->prach_config.num_prach_fd_occasions.tl.tag = NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG;
|
||||
cfg->num_tlv++;
|
||||
|
||||
cfg->prach_config.prach_ConfigurationIndex.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
cfg->prach_config.prach_ConfigurationIndex.tl.tag = NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG;
|
||||
cfg->num_tlv++;
|
||||
|
||||
cfg->prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *) malloc(cfg->prach_config.num_prach_fd_occasions.value*sizeof(nfapi_nr_num_prach_fd_occasions_t));
|
||||
for (i=0; i<cfg->prach_config.num_prach_fd_occasions.value; i++) {
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].num_prach_fd_occasions = i;
|
||||
// cfg->prach_config.num_prach_fd_occasions_list[i].num_prach_fd_occasions = i;
|
||||
if (cfg->prach_config.prach_sequence_length.value)
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139;
|
||||
else
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l839;
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index.tl.tag = NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG;
|
||||
cfg->num_tlv++;
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].k1.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart;
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].k1.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart + (get_N_RA_RB( cfg->prach_config.prach_sub_c_spacing.value, scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing ) * i);
|
||||
//k1= msg1_FrequencyStart + 12 (no. of FDM)(RB for PRACH occasion);
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].k1.tl.tag = NFAPI_NR_CONFIG_K1_TAG;
|
||||
cfg->num_tlv++;
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig;
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf.tl.tag = NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG;
|
||||
cfg->num_tlv++;
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences.value = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup,
|
||||
nb_preambles, frame_type);
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences.value = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup,nb_preambles, frame_type);
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences.tl.tag = NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG;
|
||||
cfg->num_tlv++;
|
||||
//cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences.value = ???
|
||||
cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences.value = 1;
|
||||
}
|
||||
|
||||
cfg->prach_config.ssb_per_rach.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present-1;
|
||||
@@ -344,7 +355,10 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
|
||||
phycfg.cfg->ssb_table.ssb_subcarrier_offset.tl.tag = NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG;
|
||||
phycfg.cfg->num_tlv++;
|
||||
|
||||
if (RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req) RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req(&phycfg);
|
||||
if (RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req) RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req(&phycfg);
|
||||
|
||||
find_SSB_and_RO_available(Mod_idP);
|
||||
|
||||
}
|
||||
|
||||
if (secondaryCellGroup) {
|
||||
@@ -367,12 +381,18 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
|
||||
NR_RA_t *ra = &RC.nrmac[Mod_idP]->common_channels[CC_id].ra[0];
|
||||
ra->state = RA_IDLE;
|
||||
ra->secondaryCellGroup = secondaryCellGroup;
|
||||
ra->crnti = rnti;
|
||||
uint8_t num_preamble = secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list.count;
|
||||
ra->preambles.num_preambles = num_preamble;
|
||||
ra->preambles.preamble_list = (uint8_t *) malloc(num_preamble*sizeof(uint8_t));
|
||||
for (int i = 0; i < num_preamble; i++)
|
||||
ra->preambles.preamble_list[i] = secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list.array[i]->ra_PreambleIndex;
|
||||
if (secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated!=NULL) {
|
||||
if (secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra != NULL) {
|
||||
ra->cfra = true;
|
||||
ra->rnti = rnti;
|
||||
struct NR_CFRA cfra = *secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra;
|
||||
uint8_t num_preamble = cfra.resources.choice.ssb->ssb_ResourceList.list.count;
|
||||
ra->preambles.num_preambles = num_preamble;
|
||||
ra->preambles.preamble_list = (uint8_t *) malloc(num_preamble*sizeof(uint8_t));
|
||||
for (int i = 0; i < num_preamble; i++)
|
||||
ra->preambles.preamble_list[i] = cfra.resources.choice.ssb->ssb_ResourceList.list.array[i]->ra_PreambleIndex;
|
||||
}
|
||||
}
|
||||
LOG_I(PHY,"Added new RA process for UE RNTI %04x with initial secondaryCellGroup\n", rnti);
|
||||
} else { // secondaryCellGroup has been updated
|
||||
const int UE_id = find_nr_UE_id(Mod_idP,rnti);
|
||||
|
||||
@@ -435,11 +435,13 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
|
||||
}
|
||||
|
||||
const uint64_t dlsch_in_slot_bitmap = (1 << 1);
|
||||
const uint64_t dlsch_in_slot_bitmap = (1 << 1) | (1 << 2);
|
||||
const uint64_t ulsch_in_slot_bitmap = (1 << 8);
|
||||
|
||||
memset(RC.nrmac[module_idP]->cce_list[bwp_id][0],0,MAX_NUM_CCE*sizeof(int)); // coreset0
|
||||
memset(RC.nrmac[module_idP]->cce_list[bwp_id][1],0,MAX_NUM_CCE*sizeof(int)); // coresetid 1
|
||||
for (int i=0; i<MAX_NUM_CORESET; i++)
|
||||
RC.nrmac[module_idP]->UE_info.num_pdcch_cand[UE_id][i] = 0;
|
||||
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
//mbsfn_status[CC_id] = 0;
|
||||
|
||||
@@ -469,6 +471,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
|
||||
// This schedule RA procedure if not in phy_test mode
|
||||
// Otherwise already consider 5G already connected
|
||||
RC.nrmac[module_idP]->current_slot=slot;
|
||||
if (get_softmodem_params()->phy_test == 0) {
|
||||
nr_schedule_RA(module_idP, frame, slot);
|
||||
nr_schedule_reception_msg3(module_idP, 0, frame, slot);
|
||||
@@ -497,7 +500,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
|
||||
if (UE_info->active[UE_id]
|
||||
&& (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot % num_slots_per_tdd))
|
||||
&& (!get_softmodem_params()->phy_test || slot == 1)
|
||||
&& slot < 10) {
|
||||
ue_sched_ctl->current_harq_pid = slot % num_slots_per_tdd;
|
||||
//int pucch_sched;
|
||||
|
||||
@@ -46,121 +46,295 @@ extern const uint8_t nr_slots_per_frame[5];
|
||||
|
||||
uint8_t DELTA[4]= {2,3,4,6};
|
||||
|
||||
#define MAX_NUMBER_OF_SSB 64
|
||||
float ssb_per_rach_occasion[8] = {0.125,0.25,0.5,1,2,4,8};
|
||||
|
||||
int16_t ssb_index_from_prach(module_id_t module_idP,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP,
|
||||
uint16_t preamble_index,
|
||||
uint8_t freq_index,
|
||||
uint8_t symbol) {
|
||||
|
||||
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
|
||||
NR_COMMON_channels_t *cc = &gNB->common_channels[0];
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
|
||||
|
||||
uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
|
||||
|
||||
uint8_t total_RApreambles = 64;
|
||||
if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL)
|
||||
total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles;
|
||||
|
||||
float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];
|
||||
uint16_t start_symbol_index = 0;
|
||||
uint8_t mu,N_dur,N_t_slot,start_symbol = 0, temp_start_symbol = 0, N_RA_slot;
|
||||
uint16_t format,RA_sfn_index = -1;
|
||||
uint8_t config_period = 1;
|
||||
uint16_t prach_occasion_id = -1;
|
||||
uint8_t num_active_ssb = cc->num_active_ssb;
|
||||
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
|
||||
mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
|
||||
else
|
||||
mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
|
||||
get_nr_prach_info_from_index(config_index,
|
||||
(int)frameP,
|
||||
(int)slotP,
|
||||
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
|
||||
mu,
|
||||
cc->frame_type,
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur,
|
||||
&RA_sfn_index,
|
||||
&N_RA_slot,
|
||||
&config_period);
|
||||
uint8_t index = 0,slot_index = 0;
|
||||
for (slot_index = 0;slot_index < N_RA_slot; slot_index++) {
|
||||
if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
|
||||
if((mu == 1) || (mu == 3))
|
||||
slot_index = 1; //For scs = 30khz and 120khz
|
||||
}
|
||||
for (int i=0; i< N_t_slot; i++) {
|
||||
temp_start_symbol = (start_symbol + i * N_dur + 14 * slot_index) % 14;
|
||||
if(symbol == temp_start_symbol) {
|
||||
start_symbol_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
|
||||
if((mu == 1) || (mu == 3))
|
||||
slot_index = 0; //For scs = 30khz and 120khz
|
||||
}
|
||||
|
||||
// prach_occasion_id = subframe_index * N_t_slot * N_RA_slot * fdm + N_RA_slot_index * N_t_slot * fdm + freq_index + fdm * start_symbol_index;
|
||||
prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period)*cc->total_prach_occasions_per_config_period) + (RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index;
|
||||
//one RO is shared by one or more SSB
|
||||
if(num_ssb_per_RO <= 1 )
|
||||
index = (int) (prach_occasion_id / (int)(1/num_ssb_per_RO)) % num_active_ssb;
|
||||
//one SSB have more than one continuous RO
|
||||
else if ( num_ssb_per_RO > 1) {
|
||||
index = (prach_occasion_id * (int)num_ssb_per_RO)% num_active_ssb ;
|
||||
for(int j = 0;j < num_ssb_per_RO;j++) {
|
||||
if(preamble_index < (((j+1) * total_RApreambles) / num_ssb_per_RO))
|
||||
index = index + j;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(MAC, "Frame %d, Slot %d: Prach Occasion id = %d ssb per RO = %f number of active SSB %u index = %d fdm %u symbol index %u freq_index %u total_RApreambles %u\n", frameP, slotP, prach_occasion_id, num_ssb_per_RO, num_active_ssb, index, fdm, start_symbol_index, freq_index, total_RApreambles);
|
||||
return index;
|
||||
}
|
||||
//Compute Total active SSBs and RO available
|
||||
void find_SSB_and_RO_available(module_id_t module_idP) {
|
||||
|
||||
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
|
||||
NR_COMMON_channels_t *cc = &gNB->common_channels[0];
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
|
||||
|
||||
uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
uint8_t mu,N_dur,N_t_slot,start_symbol,N_RA_slot = 0;
|
||||
uint16_t format,N_RA_sfn = 0,unused_RA_occasion,repetition = 0;
|
||||
uint8_t num_active_ssb = 0;
|
||||
uint8_t max_association_period = 1;
|
||||
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
|
||||
mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
|
||||
else
|
||||
mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
|
||||
// prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4
|
||||
get_nr_prach_occasion_info_from_index(config_index,
|
||||
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
|
||||
mu,
|
||||
cc->frame_type,
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur,
|
||||
&N_RA_slot,
|
||||
&N_RA_sfn,
|
||||
&max_association_period);
|
||||
|
||||
float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];
|
||||
uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
|
||||
uint64_t L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value)<<32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value ;
|
||||
uint32_t total_RA_occasions = N_RA_sfn * N_t_slot * N_RA_slot * fdm;
|
||||
|
||||
for(int i = 0;i < 64;i++) {
|
||||
if ((L_ssb >> (63-i)) & 0x01) { // only if the bit of L_ssb at current ssb index is 1
|
||||
cc->ssb_index[num_active_ssb] = i;
|
||||
num_active_ssb++;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 1; (1 << (i-1)) <= max_association_period;i++) {
|
||||
if(total_RA_occasions >= (int) (num_active_ssb/num_ssb_per_RO)) {
|
||||
repetition = (uint16_t)((total_RA_occasions * num_ssb_per_RO )/num_active_ssb);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
total_RA_occasions = total_RA_occasions * i;
|
||||
cc->max_association_period = i;
|
||||
}
|
||||
}
|
||||
if(cc->max_association_period == 0)
|
||||
cc->max_association_period = 1;
|
||||
|
||||
unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition)/num_ssb_per_RO);
|
||||
cc->total_prach_occasions = total_RA_occasions - unused_RA_occasion;
|
||||
cc->num_active_ssb = num_active_ssb;
|
||||
|
||||
LOG_I(MAC, "Total available RO %d, num of active SSB %d: unused RO = %d max_association_period %u N_RA_sfn %u \n", cc->total_prach_occasions, cc->num_active_ssb, unused_RA_occasion, max_association_period, N_RA_sfn);
|
||||
|
||||
}
|
||||
|
||||
void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) {
|
||||
|
||||
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
|
||||
NR_COMMON_channels_t *cc = gNB->common_channels;
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req[0];
|
||||
nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
|
||||
|
||||
if (is_nr_UL_slot(scc,slotP)) {
|
||||
uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
uint8_t mu,N_dur,N_t_slot,start_symbol = 0,N_RA_slot;
|
||||
uint16_t RA_sfn_index = -1;
|
||||
uint8_t config_period = 1;
|
||||
uint16_t format;
|
||||
int slot_index = 0;
|
||||
uint16_t prach_occasion_id = -1;
|
||||
|
||||
uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
uint8_t mu,N_dur,N_t_slot,start_symbol;
|
||||
uint16_t format;
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
|
||||
mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
|
||||
else
|
||||
mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
|
||||
mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
|
||||
else
|
||||
mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
|
||||
// prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4
|
||||
if ( get_nr_prach_info_from_index(config_index,
|
||||
(int)frameP,
|
||||
(int)slotP,
|
||||
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
|
||||
mu,
|
||||
cc->frame_type,
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur,
|
||||
&RA_sfn_index,
|
||||
&N_RA_slot,
|
||||
&config_period) ) {
|
||||
uint16_t format0 = format&0xff; // first column of format from table
|
||||
uint16_t format1 = (format>>8)&0xff; // second column of format from table
|
||||
|
||||
// prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4
|
||||
if ( get_nr_prach_info_from_index(config_index,
|
||||
(int)frameP,
|
||||
(int)slotP,
|
||||
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
|
||||
mu,
|
||||
cc->frame_type,
|
||||
&format,
|
||||
&start_symbol,
|
||||
&N_t_slot,
|
||||
&N_dur) ) {
|
||||
if (N_RA_slot > 1) { //more than 1 PRACH slot in a subframe
|
||||
if (slotP%2 == 1){
|
||||
slot_index = 1;
|
||||
}
|
||||
else {
|
||||
slot_index = 0;
|
||||
}
|
||||
}else if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
|
||||
slot_index = 0;
|
||||
}
|
||||
|
||||
int fdm = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM;
|
||||
uint16_t format0 = format&0xff; // first column of format from table
|
||||
uint16_t format1 = (format>>8)&0xff; // second column of format from table
|
||||
|
||||
UL_tti_req->SFN = frameP;
|
||||
UL_tti_req->Slot = slotP;
|
||||
for (int n=0; n<(1<<fdm); n++) { // one structure per frequency domain occasion
|
||||
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE;
|
||||
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_prach_pdu_t);
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].prach_pdu;
|
||||
memset(prach_pdu,0,sizeof(nfapi_nr_prach_pdu_t));
|
||||
UL_tti_req->n_pdus+=1;
|
||||
UL_tti_req->SFN = frameP;
|
||||
UL_tti_req->Slot = slotP;
|
||||
for (int fdm_index=0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion
|
||||
for (int td_index=0; td_index<N_t_slot; td_index++) {
|
||||
|
||||
// filling the prach fapi structure
|
||||
prach_pdu->phys_cell_id = *scc->physCellId;
|
||||
prach_pdu->num_prach_ocas = N_t_slot;
|
||||
prach_pdu->prach_start_symbol = start_symbol;
|
||||
prach_pdu->num_ra = n;
|
||||
prach_pdu->num_cs = get_NCS(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig,
|
||||
format0,
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig);
|
||||
// SCF PRACH PDU format field does not consider A1/B1 etc. possibilities
|
||||
// We added 9 = A1/B1 10 = A2/B2 11 A3/B3
|
||||
if (format1!=0xff) {
|
||||
switch(format0) {
|
||||
case 0xa1:
|
||||
prach_pdu->prach_format = 9;
|
||||
break;
|
||||
case 0xa2:
|
||||
prach_pdu->prach_format = 10;
|
||||
break;
|
||||
case 0xa3:
|
||||
prach_pdu->prach_format = 11;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
|
||||
}
|
||||
}
|
||||
else{
|
||||
switch(format0) {
|
||||
case 0xa1:
|
||||
prach_pdu->prach_format = 0;
|
||||
break;
|
||||
case 0xa2:
|
||||
prach_pdu->prach_format = 1;
|
||||
break;
|
||||
case 0xa3:
|
||||
prach_pdu->prach_format = 2;
|
||||
break;
|
||||
case 0xb1:
|
||||
prach_pdu->prach_format = 3;
|
||||
break;
|
||||
case 0xb2:
|
||||
prach_pdu->prach_format = 4;
|
||||
break;
|
||||
case 0xb3:
|
||||
prach_pdu->prach_format = 5;
|
||||
break;
|
||||
case 0xb4:
|
||||
prach_pdu->prach_format = 6;
|
||||
break;
|
||||
case 0xc0:
|
||||
prach_pdu->prach_format = 7;
|
||||
break;
|
||||
case 0xc2:
|
||||
prach_pdu->prach_format = 8;
|
||||
break;
|
||||
case 0:
|
||||
// long formats are handled @ PHY
|
||||
break;
|
||||
case 1:
|
||||
// long formats are handled @ PHY
|
||||
break;
|
||||
case 2:
|
||||
// long formats are handled @ PHY
|
||||
break;
|
||||
case 3:
|
||||
// long formats are handled @ PHY
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid PRACH format");
|
||||
}
|
||||
prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) + (RA_sfn_index + slot_index) * N_t_slot * fdm + td_index * fdm + fdm_index;
|
||||
if((prach_occasion_id < cc->total_prach_occasions) && (td_index == 0)){
|
||||
|
||||
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE;
|
||||
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_prach_pdu_t);
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].prach_pdu;
|
||||
memset(prach_pdu,0,sizeof(nfapi_nr_prach_pdu_t));
|
||||
UL_tti_req->n_pdus+=1;
|
||||
|
||||
// filling the prach fapi structure
|
||||
prach_pdu->phys_cell_id = *scc->physCellId;
|
||||
prach_pdu->num_prach_ocas = N_t_slot;
|
||||
prach_pdu->prach_start_symbol = start_symbol;
|
||||
prach_pdu->num_ra = fdm_index;
|
||||
prach_pdu->num_cs = get_NCS(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig,
|
||||
format0,
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig);
|
||||
|
||||
LOG_D(MAC, "Frame %d, Slot %d: Prach Occasion id = %u fdm index = %u start symbol = %u slot index = %u subframe index = %u \n",
|
||||
frameP, slotP,
|
||||
prach_occasion_id, prach_pdu->num_ra,
|
||||
prach_pdu->prach_start_symbol,
|
||||
slot_index, RA_sfn_index);
|
||||
// SCF PRACH PDU format field does not consider A1/B1 etc. possibilities
|
||||
// We added 9 = A1/B1 10 = A2/B2 11 A3/B3
|
||||
if (format1!=0xff) {
|
||||
switch(format0) {
|
||||
case 0xa1:
|
||||
prach_pdu->prach_format = 11;
|
||||
break;
|
||||
case 0xa2:
|
||||
prach_pdu->prach_format = 12;
|
||||
break;
|
||||
case 0xa3:
|
||||
prach_pdu->prach_format = 13;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
|
||||
}
|
||||
}
|
||||
else{
|
||||
switch(format0) {
|
||||
case 0:
|
||||
prach_pdu->prach_format = 0;
|
||||
break;
|
||||
case 1:
|
||||
prach_pdu->prach_format = 1;
|
||||
break;
|
||||
case 2:
|
||||
prach_pdu->prach_format = 2;
|
||||
break;
|
||||
case 3:
|
||||
prach_pdu->prach_format = 3;
|
||||
break;
|
||||
case 0xa1:
|
||||
prach_pdu->prach_format = 4;
|
||||
break;
|
||||
case 0xa2:
|
||||
prach_pdu->prach_format = 5;
|
||||
break;
|
||||
case 0xa3:
|
||||
prach_pdu->prach_format = 6;
|
||||
break;
|
||||
case 0xb1:
|
||||
prach_pdu->prach_format = 7;
|
||||
break;
|
||||
case 0xb4:
|
||||
prach_pdu->prach_format = 8;
|
||||
break;
|
||||
case 0xc0:
|
||||
prach_pdu->prach_format = 9;
|
||||
break;
|
||||
case 0xc2:
|
||||
prach_pdu->prach_format = 10;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid PRACH format");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +342,7 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot,
|
||||
uint16_t *msg2_frame, uint16_t *msg2_slot,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
uint16_t monitoring_slot_period,
|
||||
uint16_t monitoring_offset){
|
||||
uint16_t monitoring_offset,uint8_t index,uint8_t num_active_ssb){
|
||||
|
||||
// preferentially we schedule the msg2 in the mixed slot or in the last dl slot
|
||||
// if they are allowed by search space configuration
|
||||
@@ -189,7 +363,7 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot,
|
||||
uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame[mu];
|
||||
*msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot
|
||||
*msg2_frame = (*msg2_slot>(rach_slot))? rach_frame : (rach_frame +1);
|
||||
|
||||
|
||||
switch(response_window){
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1:
|
||||
slot_window = 1;
|
||||
@@ -255,7 +429,6 @@ void nr_initiate_ra_proc(module_id_t module_idP,
|
||||
NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_RA_t *ra = &cc->ra[0];
|
||||
|
||||
// if the preamble received correspond to one of the listed
|
||||
// the UE sent a RACH either for starting RA procedure or RA procedure failed and UE retries
|
||||
int pr_found=0;
|
||||
@@ -270,7 +443,6 @@ void nr_initiate_ra_proc(module_id_t module_idP,
|
||||
module_idP, preamble_index);
|
||||
return; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc
|
||||
}
|
||||
|
||||
// This should be handled differently when we use the initialBWP for RA
|
||||
ra->bwp_id=1;
|
||||
NR_BWP_Downlink_t *bwp=ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1];
|
||||
@@ -280,6 +452,13 @@ void nr_initiate_ra_proc(module_id_t module_idP,
|
||||
LOG_I(MAC, "[gNB %d][RAPROC] CC_id %d Frame %d, Slot %d Initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, slotP, preamble_index);
|
||||
|
||||
if (ra->state == RA_IDLE) {
|
||||
|
||||
uint8_t beam_index = ssb_index_from_prach(module_idP,
|
||||
frameP,
|
||||
slotP,
|
||||
preamble_index,
|
||||
freq_index,
|
||||
symbol);
|
||||
int loop = 0;
|
||||
LOG_D(MAC, "Frame %d, Slot %d: Activating RA process \n", frameP, slotP);
|
||||
ra->state = Msg2;
|
||||
@@ -301,33 +480,35 @@ void nr_initiate_ra_proc(module_id_t module_idP,
|
||||
&monitoring_slot_period,
|
||||
&monitoring_offset);
|
||||
|
||||
nr_schedule_msg2(frameP, slotP, &msg2_frame, &msg2_slot, scc, monitoring_slot_period, monitoring_offset);
|
||||
nr_schedule_msg2(frameP, slotP, &msg2_frame, &msg2_slot, scc, monitoring_slot_period, monitoring_offset,beam_index,cc->num_active_ssb);
|
||||
|
||||
ra->Msg2_frame = msg2_frame;
|
||||
ra->Msg2_slot = msg2_slot;
|
||||
|
||||
LOG_D(MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP);
|
||||
|
||||
do {
|
||||
ra->rnti = (taus() % 65518) + 1;
|
||||
loop++;
|
||||
LOG_I(MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP);
|
||||
if (!ra->cfra) {
|
||||
do {
|
||||
ra->rnti = (taus() % 65518) + 1;
|
||||
loop++;
|
||||
}
|
||||
while (loop != 100 && !((find_nr_UE_id(module_idP, ra->rnti) == -1) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1) && ra->rnti >= 1 && ra->rnti <= 65519));
|
||||
if (loop == 100) {
|
||||
LOG_E(MAC,"%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
while (loop != 100 && !(find_nr_UE_id(module_idP, ra->rnti) == -1 && ra->rnti >= 1 && ra->rnti <= 65519));
|
||||
if (loop == 100) {
|
||||
LOG_E(MAC,"%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
abort();
|
||||
}
|
||||
|
||||
ra->RA_rnti = ra_rnti;
|
||||
ra->preamble_index = preamble_index;
|
||||
ra->beam_id = beam_index;
|
||||
|
||||
LOG_I(MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x\n",
|
||||
LOG_I(MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x SSB index %u\n",
|
||||
module_idP,
|
||||
CC_id,
|
||||
frameP,
|
||||
ra->Msg2_frame,
|
||||
ra->Msg2_slot,
|
||||
ra->RA_rnti);
|
||||
ra->RA_rnti,
|
||||
cc->ssb_index[beam_index]);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -342,26 +523,31 @@ void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){
|
||||
int CC_id = 0;
|
||||
gNB_MAC_INST *mac = RC.nrmac[module_idP];
|
||||
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
|
||||
NR_RA_t *ra = &cc->ra[0];
|
||||
|
||||
start_meas(&mac->schedule_ra);
|
||||
|
||||
//for (i = 0; i < NR_NB_RA_PROC_MAX; i++) {
|
||||
// for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
// for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
|
||||
|
||||
// NR_RA_t *ra = &cc->ra[i];
|
||||
NR_RA_t *ra = &cc->ra[0];
|
||||
|
||||
LOG_D(MAC,"RA[state:%d]\n",ra->state);
|
||||
switch (ra->state){
|
||||
case Msg2:
|
||||
nr_generate_Msg2(module_idP, CC_id, frameP, slotP);
|
||||
break;
|
||||
case Msg4:
|
||||
//generate_Msg4(module_idP, CC_id, frameP, slotP, ra);
|
||||
//generate_Msg4(module_idP, CC_id, frameP, slotP);
|
||||
break;
|
||||
case WAIT_Msg4_ACK:
|
||||
//check_Msg4_retransmission(module_idP, CC_id, frameP, slotP, ra);
|
||||
//check_Msg4_retransmission(module_idP, CC_id, frameP, slotP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//}
|
||||
// }
|
||||
// }
|
||||
stop_meas(&mac->schedule_ra);
|
||||
}
|
||||
|
||||
@@ -398,6 +584,7 @@ void nr_get_Msg3alloc(NR_ServingCellConfigCommon_t *scc,
|
||||
else
|
||||
ra->Msg3_frame = current_frame + (temp_slot/nr_slots_per_frame[mu]);
|
||||
|
||||
LOG_I(MAC, "[RAPROC] Msg3 slot %d: current slot %u Msg3 frame %u k2 %u Msg3_tda_id %u start symbol index %u\n", ra->Msg3_slot, current_slot, ra->Msg3_frame, k2,ra->Msg3_tda_id, StartSymbolIndex);
|
||||
ra->msg3_nb_rb = 18;
|
||||
ra->msg3_first_rb = 0;
|
||||
}
|
||||
@@ -433,7 +620,7 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_D(MAC, "[gNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", module_idP, frameP, slotP, CC_id, ra->Msg3_frame, ra->Msg3_slot);
|
||||
LOG_I(MAC, "[gNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", module_idP, frameP, slotP, CC_id, ra->Msg3_frame, ra->Msg3_slot);
|
||||
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu = &ra->pusch_pdu;
|
||||
memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t));
|
||||
@@ -530,13 +717,14 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t
|
||||
void nr_generate_Msg2(module_id_t module_idP,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP){
|
||||
sub_frame_t slotP)
|
||||
{
|
||||
|
||||
int dci_formats[2], rnti_types[2], mcsIndex;
|
||||
int startSymbolAndLength = 0, StartSymbolIndex = -1, NrOfSymbols = 14, StartSymbolIndex_tmp, NrOfSymbols_tmp, x_Overhead, time_domain_assignment = 0;
|
||||
gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
|
||||
NR_COMMON_channels_t *cc = &nr_mac->common_channels[0];
|
||||
NR_RA_t *ra = &cc->ra[0];
|
||||
NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
|
||||
NR_RA_t *ra = &cc->ra[CC_id];
|
||||
NR_SearchSpace_t *ss = ra->ra_ss;
|
||||
|
||||
uint16_t RA_rnti = ra->RA_rnti;
|
||||
@@ -593,7 +781,7 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
NR_BWP_Downlink_t *bwp = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1];
|
||||
NR_BWP_Uplink_t *ubwp=ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id-1];
|
||||
|
||||
LOG_D(MAC, "[RAPROC] Scheduling common search space DCI type 1 dlBWP BW %d\n", dci10_bw);
|
||||
LOG_I(MAC, "[RAPROC] Scheduling common search space DCI type 1 dlBWP BW %d\n", dci10_bw);
|
||||
|
||||
// Qm>2 not allowed for RAR
|
||||
if (get_softmodem_params()->do_ra)
|
||||
@@ -674,13 +862,13 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
uint8_t nr_of_candidates, aggregation_level;
|
||||
find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss);
|
||||
NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 0 /* common */);
|
||||
int CCEIndex = allocate_nr_CCEs(
|
||||
nr_mac,
|
||||
bwp,
|
||||
coreset,
|
||||
aggregation_level,
|
||||
0, /* n_RNTI 0: common search space */
|
||||
0); // m
|
||||
int CCEIndex = allocate_nr_CCEs(nr_mac,
|
||||
bwp,
|
||||
coreset,
|
||||
aggregation_level,
|
||||
0, // Y
|
||||
0, // m
|
||||
nr_of_candidates);
|
||||
|
||||
if (CCEIndex < 0) {
|
||||
LOG_E(MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti);
|
||||
@@ -701,7 +889,7 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
dci_formats[0] = NR_DL_DCI_FORMAT_1_0;
|
||||
rnti_types[0] = NR_RNTI_RA;
|
||||
|
||||
LOG_D(MAC, "[RAPROC] DCI params: rnti %d, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n",
|
||||
LOG_I(MAC, "[RAPROC] DCI params: rnti %d, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n",
|
||||
pdcch_pdu_rel15->dci_pdu.RNTI[0],
|
||||
rnti_types[0],
|
||||
dci_formats[0],
|
||||
@@ -718,7 +906,7 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
LOG_I(MAC, "Frame %d, Subframe %d: Setting Msg3 reception for Frame %d Subframe %d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot);
|
||||
nr_add_msg3(module_idP, CC_id, frameP, slotP);
|
||||
ra->state = WAIT_Msg3;
|
||||
LOG_D(MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state);
|
||||
LOG_I(MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state);
|
||||
|
||||
x_Overhead = 0;
|
||||
nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_pdu_rel15[0].tb_scaling);
|
||||
@@ -741,6 +929,7 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
}
|
||||
|
||||
void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP){
|
||||
|
||||
NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[0];
|
||||
LOG_D(MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Clear Random access information rnti %x\n", module_idP, CC_id, frameP, ra->rnti);
|
||||
ra->state = IDLE;
|
||||
@@ -786,7 +975,7 @@ void nr_fill_rar(uint8_t Mod_idP,
|
||||
uint8_t * dlsch_buffer,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu){
|
||||
|
||||
LOG_D(MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d ", ra->Msg2_frame, ra-> Msg2_slot);
|
||||
LOG_I(MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u", ra->Msg2_frame, ra-> Msg2_slot, ra->preamble_index);
|
||||
NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer;
|
||||
NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1);
|
||||
unsigned char csi_req = 0, tpc_command;
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "common/ran_context.h"
|
||||
|
||||
extern RAN_CONTEXT_t RC;
|
||||
extern uint8_t SSB_Table[38];
|
||||
|
||||
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){
|
||||
|
||||
@@ -66,15 +67,24 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){
|
||||
|
||||
int mib_sdu_length;
|
||||
int CC_id;
|
||||
|
||||
AssertFatal(slotP == 0, "Subframe must be 0\n");
|
||||
AssertFatal((frameP & 7) == 0, "Frame must be a multiple of 8\n");
|
||||
|
||||
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
|
||||
nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
|
||||
dl_tti_request = &gNB->DL_req[CC_id];
|
||||
dl_req = &dl_tti_request->dl_tti_request_body;
|
||||
cc = &gNB->common_channels[CC_id];
|
||||
#if 0
|
||||
//SSB is transmitted based on SSB periodicity
|
||||
if((frameP % cfg->ssb_table.ssb_period.value) == 0) {
|
||||
uint64_t L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value)<<32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value ;
|
||||
uint32_t ssb_index = -1;
|
||||
for (int i=0; i<2; i++) { // max two SSB per slot
|
||||
ssb_index = i + SSB_Table[slotP]; // computing the ssb_index
|
||||
if ((ssb_index<64) && ((L_ssb >> (63-ssb_index)) & 0x01)) { // generating the ssb only if the bit of L_ssb at current ssb index is 1
|
||||
#endif
|
||||
|
||||
mib_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, MIBCH, 1, &cc->MIB_pdu.payload[0]); // not used in this case
|
||||
|
||||
@@ -96,7 +106,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){
|
||||
AssertFatal(cc->ServingCellConfigCommon->physCellId!=NULL,"cc->ServingCellConfigCommon->physCellId is null\n");
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.PhysCellId = *cc->ServingCellConfigCommon->physCellId;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.BetaPss = 0;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;//ssb_index ;//SSB index for each SSB
|
||||
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon!=NULL,"scc->downlinkConfigCommonL is null\n");
|
||||
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL is null\n");
|
||||
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB is null\n");
|
||||
@@ -132,8 +142,8 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){
|
||||
default:
|
||||
AssertFatal(1==0,"SCS %ld not allowed for SSB \n", *cc->ServingCellConfigCommon->ssbSubcarrierSpacing);
|
||||
}
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = 0; //kSSB
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = ssb_offset0/(ratio*12) - 10; // absoluteFrequencySSB is the center of SSB
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = cfg->ssb_table.ssb_subcarrier_offset.value; //kSSB
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = ssb_offset0/(ratio*12) - 10;/*cfg->ssb_table.ssb_offset_point_a.value;*/ // absoluteFrequencySSB is the center of SSB
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag = 1;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload = (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1);
|
||||
dl_req->nPDUs++;
|
||||
|
||||
@@ -488,16 +488,21 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
|
||||
sched_ctrl->search_space);
|
||||
sched_ctrl->coreset = get_coreset(
|
||||
sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
|
||||
int cid = sched_ctrl->coreset->controlResourceSetId;
|
||||
const uint16_t Y = UE_info->Y[UE_id][cid][slot];
|
||||
const int m = UE_info->num_pdcch_cand[UE_id][cid];
|
||||
sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id],
|
||||
sched_ctrl->active_bwp,
|
||||
sched_ctrl->coreset,
|
||||
sched_ctrl->aggregation_level,
|
||||
UE_info->rnti[UE_id],
|
||||
0); // m
|
||||
sched_ctrl->active_bwp,
|
||||
sched_ctrl->coreset,
|
||||
sched_ctrl->aggregation_level,
|
||||
Y,
|
||||
m,
|
||||
nr_of_candidates);
|
||||
if (sched_ctrl->cce_index < 0) {
|
||||
LOG_E(MAC, "%s(): could not find CCE for UE %d\n", __func__, UE_id);
|
||||
return;
|
||||
}
|
||||
UE_info->num_pdcch_cand[UE_id][cid]++;
|
||||
|
||||
/* Find PUCCH occasion */
|
||||
nr_update_pucch_scheduling(
|
||||
|
||||
@@ -417,18 +417,23 @@ int configure_fapi_dl_pdu_phytest(int Mod_idP,
|
||||
uint8_t nr_of_candidates, aggregation_level;
|
||||
find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss);
|
||||
NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 1 /* dedicated */);
|
||||
int CCEIndex = allocate_nr_CCEs(
|
||||
nr_mac,
|
||||
bwp,
|
||||
coreset,
|
||||
aggregation_level,
|
||||
UE_info->rnti[UE_id],
|
||||
0); // m
|
||||
const int cid = coreset->controlResourceSetId;
|
||||
const uint16_t Y = UE_info->Y[UE_id][cid][nr_mac->current_slot];
|
||||
const int m = UE_info->num_pdcch_cand[UE_id][cid];
|
||||
int CCEIndex = allocate_nr_CCEs(nr_mac,
|
||||
bwp,
|
||||
coreset,
|
||||
aggregation_level,
|
||||
Y,
|
||||
m,
|
||||
nr_of_candidates);
|
||||
if (CCEIndex < 0) {
|
||||
LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PDSCH\n", __func__);
|
||||
free(dci_pdu_rel15);
|
||||
return 0;
|
||||
}
|
||||
UE_info->num_pdcch_cand[UE_id][cid]++;
|
||||
|
||||
nr_configure_pdcch(nr_mac,
|
||||
pdcch_pdu_rel15,
|
||||
UE_info->rnti[UE_id],
|
||||
@@ -864,7 +869,8 @@ void schedule_fapi_ul_pdu(int Mod_idP,
|
||||
* conditions might exclude each other and never be true */
|
||||
const int slot_idx = (slotP + K2) % num_slots_per_tdd;
|
||||
if (is_xlsch_in_slot(ulsch_in_slot_bitmap, slot_idx)
|
||||
&& (!get_softmodem_params()->phy_test || slot_idx == 8)) {
|
||||
&& (!get_softmodem_params()->phy_test || slot_idx == 8)) {
|
||||
|
||||
nfapi_nr_ul_dci_request_t *UL_dci_req = &RC.nrmac[Mod_idP]->UL_dci_req[0];
|
||||
UL_dci_req->SFN = frameP;
|
||||
UL_dci_req->Slot = slotP;
|
||||
@@ -1126,19 +1132,23 @@ void schedule_fapi_ul_pdu(int Mod_idP,
|
||||
uint8_t nr_of_candidates, aggregation_level;
|
||||
find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss);
|
||||
NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 1 /* dedicated */);
|
||||
int CCEIndex = allocate_nr_CCEs(
|
||||
nr_mac,
|
||||
bwp,
|
||||
coreset,
|
||||
aggregation_level,
|
||||
UE_info->rnti[UE_id],
|
||||
0); // m
|
||||
const int cid = coreset->controlResourceSetId;
|
||||
const uint16_t Y = UE_info->Y[UE_id][cid][nr_mac->current_slot];
|
||||
const int m = UE_info->num_pdcch_cand[UE_id][cid];
|
||||
int CCEIndex = allocate_nr_CCEs(nr_mac,
|
||||
bwp,
|
||||
coreset,
|
||||
aggregation_level,
|
||||
Y,
|
||||
m,
|
||||
nr_of_candidates);
|
||||
if (CCEIndex < 0) {
|
||||
LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__);
|
||||
pusch_sched->active = false;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
UE_info->num_pdcch_cand[UE_id][cid]++;
|
||||
nr_configure_pdcch(nr_mac,
|
||||
pdcch_pdu_rel15,
|
||||
UE_info->rnti[UE_id],
|
||||
|
||||
@@ -172,8 +172,9 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac,
|
||||
NR_BWP_Downlink_t *bwp,
|
||||
NR_ControlResourceSet_t *coreset,
|
||||
int aggregation,
|
||||
uint16_t n_RNTI,
|
||||
int m) {
|
||||
uint16_t Y,
|
||||
int m,
|
||||
int nr_of_candidates) {
|
||||
// uncomment these when we allocate for common search space
|
||||
// NR_COMMON_channels_t *cc = nr_mac->common_channels;
|
||||
// NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
@@ -189,15 +190,19 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac,
|
||||
n_rb*=6;
|
||||
|
||||
uint16_t N_reg = n_rb * coreset->duration;
|
||||
uint16_t n_CI=0;
|
||||
const uint32_t A[3]={39827,39829,39839};
|
||||
/* if n_RNTI is zero, this results in zero, too! */
|
||||
uint16_t Y = (A[0]*n_RNTI)%65537; // Candidate 0, antenna port 0
|
||||
uint16_t n_CI = 0;
|
||||
|
||||
uint16_t N_cce = N_reg / NR_NB_REG_PER_CCE;
|
||||
const uint16_t N_cce = N_reg / NR_NB_REG_PER_CCE;
|
||||
const uint16_t M_s_max = nr_of_candidates;
|
||||
|
||||
uint16_t M_s_max = (aggregation==4)?4:(aggregation==8)?2:1;
|
||||
int first_cce = aggregation * (( Y + (m*N_cce)/(aggregation*M_s_max) + n_CI ) % CEILIDIV(N_cce,aggregation));
|
||||
AssertFatal(m < nr_of_candidates,
|
||||
"PDCCH candidate index %d in CORESET %d exceeds the maximum "
|
||||
"number of PDCCH candidates (%d)\n",
|
||||
m,
|
||||
coreset_id,
|
||||
nr_of_candidates);
|
||||
|
||||
int first_cce = aggregation * (( Y + CEILIDIV((m*N_cce),(aggregation*M_s_max)) + n_CI ) % CEILIDIV(N_cce,aggregation));
|
||||
|
||||
for (int i=0;i<aggregation;i++)
|
||||
if (cce_list[first_cce+i] != 0) return(-1);
|
||||
@@ -1526,6 +1531,7 @@ void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc,
|
||||
pos+=1;
|
||||
*dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val&0x1)<<(dci_size-pos);
|
||||
}
|
||||
LOG_D(MAC, "DCI index %d has %d bits and the payload is %lx\n", d, dci_size, *dci_pdu);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1619,6 +1625,40 @@ int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void set_Y(int Y[3][160], rnti_t rnti) {
|
||||
const int A[3] = {39827, 39829, 39839};
|
||||
const int D = 65537;
|
||||
|
||||
Y[0][0] = (A[0] * rnti) % D;
|
||||
Y[1][0] = (A[1] * rnti) % D;
|
||||
Y[2][0] = (A[2] * rnti) % D;
|
||||
|
||||
for (int s = 1; s < 160; s++) {
|
||||
Y[0][s] = (A[0] * Y[0][s - 1]) % D;
|
||||
Y[1][s] = (A[1] * Y[1][s - 1]) % D;
|
||||
Y[2][s] = (A[2] * Y[2][s - 1]) % D;
|
||||
}
|
||||
}
|
||||
|
||||
int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP) {
|
||||
//------------------------------------------------------------------------------
|
||||
int RA_id;
|
||||
RA_t *ra = (RA_t *) &RC.nrmac[mod_idP]->common_channels[CC_idP].ra[0];
|
||||
|
||||
for (RA_id = 0; RA_id < NB_RA_PROC_MAX; RA_id++) {
|
||||
LOG_D(MAC, "Checking RA_id %d for %x : state %d\n",
|
||||
RA_id,
|
||||
rntiP,
|
||||
ra[RA_id].state);
|
||||
|
||||
if (ra[RA_id].state != IDLE && ra[RA_id].rnti == rntiP)
|
||||
return RA_id;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){
|
||||
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[mod_idP]->UE_info;
|
||||
@@ -1642,6 +1682,7 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){
|
||||
UE_info->active[UE_id] = true;
|
||||
UE_info->rnti[UE_id] = rntiP;
|
||||
add_nr_ue_list(&UE_info->list, UE_id);
|
||||
set_Y(UE_info->Y[UE_id], rntiP);
|
||||
memset((void *) &UE_info->UE_sched_ctrl[UE_id],
|
||||
0,
|
||||
sizeof(NR_UE_sched_ctrl_t));
|
||||
@@ -1684,6 +1725,7 @@ void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti)
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
||||
|
||||
for (i = 0; i < MAX_MOBILES_PER_GNB; i++) {
|
||||
|
||||
if (UE_info->active[i] != TRUE)
|
||||
continue;
|
||||
if (UE_info->rnti[i] != rnti)
|
||||
|
||||
@@ -322,6 +322,42 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
UE_info = &gNB_mac->UE_info;
|
||||
int target_snrx10 = gNB_mac->pusch_target_snrx10;
|
||||
|
||||
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[0];
|
||||
|
||||
// random access pusch with TC-RNTI
|
||||
if (ra->state == WAIT_Msg3) {
|
||||
if (sduP != NULL) { // if the CRC passed
|
||||
|
||||
if (ra->rnti != current_rnti) {
|
||||
LOG_E(MAC,
|
||||
"expected TC-RNTI %04x to match current RNTI %04x\n",
|
||||
ra->rnti,
|
||||
current_rnti);
|
||||
return;
|
||||
}
|
||||
free(ra->preambles.preamble_list);
|
||||
ra->state = RA_IDLE;
|
||||
LOG_I(MAC, "reset RA state information for RA-RNTI %04x\n", ra->rnti);
|
||||
const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti);
|
||||
UE_info->secondaryCellGroup[UE_id] = ra->secondaryCellGroup;
|
||||
UE_info->UE_beam_index[UE_id] = ra->beam_id;
|
||||
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
|
||||
AssertFatal(bwpList->list.count == 1,
|
||||
"downlinkBWP_ToAddModList has %d BWP!\n",
|
||||
bwpList->list.count);
|
||||
const int bwp_id = 1;
|
||||
UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1];
|
||||
LOG_I(MAC,
|
||||
"[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, "
|
||||
"adding UE MAC Context UE_id %d/RNTI %04x\n",
|
||||
gnb_mod_idP,
|
||||
current_rnti,
|
||||
UE_id,
|
||||
ra->rnti);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (UE_id != -1) {
|
||||
UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]);
|
||||
|
||||
@@ -366,44 +402,5 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
|
||||
}
|
||||
}
|
||||
else if (sduP != NULL) { // if the CRC passed
|
||||
// random access pusch with TC-RNTI
|
||||
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[0];
|
||||
if (ra->state != WAIT_Msg3) {
|
||||
LOG_E(MAC,
|
||||
"expected RA state WAIT_Msg3/%d (but is %d) for RA-RNTI %04x\n",
|
||||
WAIT_Msg3,
|
||||
ra->state,
|
||||
ra->rnti);
|
||||
return;
|
||||
}
|
||||
if (ra->rnti != current_rnti) {
|
||||
LOG_E(MAC,
|
||||
"expected RA-RNTI %04x (C-RNTI %04x) to match current RNTI %04x\n",
|
||||
ra->rnti,
|
||||
ra->crnti,
|
||||
current_rnti);
|
||||
return;
|
||||
}
|
||||
free(ra->preambles.preamble_list);
|
||||
ra->state = RA_IDLE;
|
||||
LOG_I(MAC, "reset RA state information for RA-RNTI %04x\n", ra->rnti);
|
||||
const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->crnti);
|
||||
UE_info->secondaryCellGroup[UE_id] = ra->secondaryCellGroup;
|
||||
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList =
|
||||
ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
|
||||
AssertFatal(bwpList->list.count == 1,
|
||||
"downlinkBWP_ToAddModList has %d BWP!\n",
|
||||
bwpList->list.count);
|
||||
const int bwp_id = 1;
|
||||
UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1];
|
||||
LOG_W(MAC,
|
||||
"[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, "
|
||||
"adding UE MAC Context UE_id %d/RNTI %04x\n",
|
||||
gnb_mod_idP,
|
||||
current_rnti,
|
||||
UE_id,
|
||||
ra->crnti);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -306,6 +306,8 @@ void add_nr_ue_list(NR_UE_list_t *listP, int UE_id);
|
||||
|
||||
int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP);
|
||||
|
||||
int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP);
|
||||
|
||||
int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP);
|
||||
|
||||
void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti);
|
||||
@@ -314,8 +316,9 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac,
|
||||
NR_BWP_Downlink_t *bwp,
|
||||
NR_ControlResourceSet_t *coreset,
|
||||
int aggregation,
|
||||
uint16_t n_RNTI,
|
||||
int m);
|
||||
uint16_t Y,
|
||||
int m,
|
||||
int nr_of_candidates);
|
||||
|
||||
int get_dlscs(nfapi_nr_config_request_t *cfg);
|
||||
|
||||
@@ -386,5 +389,14 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
|
||||
void handle_nr_ul_harq(uint16_t slot, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, nfapi_nr_crc_t crc_pdu);
|
||||
|
||||
int16_t ssb_index_from_prach(module_id_t module_idP,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP,
|
||||
uint16_t preamble_index,
|
||||
uint8_t freq_index,
|
||||
uint8_t symbol);
|
||||
|
||||
void find_SSB_and_RO_available(module_id_t module_idP);
|
||||
|
||||
void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, int target_snrx10);
|
||||
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
#define MAX_NUM_CCE 90
|
||||
/*!\brief Maximum number of random access process */
|
||||
#define NR_NB_RA_PROC_MAX 4
|
||||
#define MAX_NUM_OF_SSB 64
|
||||
|
||||
typedef enum {
|
||||
RA_IDLE = 0,
|
||||
@@ -146,12 +147,16 @@ typedef struct {
|
||||
int msg4_mcs;
|
||||
/// RA search space
|
||||
NR_SearchSpace_t *ra_ss;
|
||||
// Beam index
|
||||
uint8_t beam_id;
|
||||
/// secondaryCellGroup for UE in NSA that is to come
|
||||
NR_CellGroupConfig_t *secondaryCellGroup;
|
||||
/// Preambles for contention-free access
|
||||
NR_preamble_ue_t preambles;
|
||||
/// NSA: the UEs C-RNTI to use
|
||||
rnti_t crnti;
|
||||
/// CFRA flag
|
||||
bool cfra;
|
||||
} NR_RA_t;
|
||||
|
||||
/*! \brief gNB common channels */
|
||||
@@ -188,6 +193,16 @@ typedef struct {
|
||||
uint8_t vrb_map_UL[275];
|
||||
/// number of subframe allocation pattern available for MBSFN sync area
|
||||
uint8_t num_sf_allocation_pattern;
|
||||
///Number of active SSBs
|
||||
uint8_t num_active_ssb;
|
||||
//Total available prach occasions per configuration period
|
||||
uint32_t total_prach_occasions_per_config_period;
|
||||
//Total available prach occasions
|
||||
uint32_t total_prach_occasions;
|
||||
//Max Association period
|
||||
uint8_t max_association_period;
|
||||
//SSB index
|
||||
uint8_t ssb_index[MAX_NUM_OF_SSB];
|
||||
} NR_COMMON_channels_t;
|
||||
|
||||
|
||||
@@ -380,6 +395,12 @@ typedef struct {
|
||||
bool active[MAX_MOBILES_PER_GNB];
|
||||
rnti_t rnti[MAX_MOBILES_PER_GNB];
|
||||
NR_CellGroupConfig_t *secondaryCellGroup[MAX_MOBILES_PER_GNB];
|
||||
/// CCE indexing
|
||||
int Y[MAX_MOBILES_PER_GNB][3][160];
|
||||
int m[MAX_MOBILES_PER_GNB];
|
||||
int num_pdcch_cand[MAX_MOBILES_PER_GNB][MAX_NUM_CORESET];
|
||||
// UE selected beam index
|
||||
uint8_t UE_beam_index[MAX_MOBILES_PER_GNB];
|
||||
} NR_UE_info_t;
|
||||
|
||||
/*! \brief top level eNB MAC structure */
|
||||
@@ -442,6 +463,8 @@ typedef struct gNB_MAC_INST_s {
|
||||
time_stats_t schedule_pch;
|
||||
/// CCE lists
|
||||
int cce_list[MAX_NUM_BWP][MAX_NUM_CORESET][MAX_NUM_CCE];
|
||||
/// current slot
|
||||
int current_slot;
|
||||
} gNB_MAC_INST;
|
||||
|
||||
#endif /*__LAYER2_NR_MAC_GNB_H__ */
|
||||
|
||||
@@ -56,24 +56,25 @@ extern uint16_t sf_ahead;
|
||||
extern uint16_t sl_ahead;
|
||||
|
||||
void handle_nr_rach(NR_UL_IND_t *UL_info) {
|
||||
|
||||
if (UL_info->rach_ind.number_of_pdus>0) {
|
||||
AssertFatal(UL_info->rach_ind.number_of_pdus==1,"More than 1 RACH pdu not supported\n");
|
||||
UL_info->rach_ind.number_of_pdus=0;
|
||||
LOG_D(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot);
|
||||
|
||||
if (UL_info->rach_ind.pdu_list[0].num_preamble>0)
|
||||
AssertFatal(UL_info->rach_ind.pdu_list[0].num_preamble==1,
|
||||
"More than 1 preamble not supported\n");
|
||||
LOG_I(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot);
|
||||
int npdus = UL_info->rach_ind.number_of_pdus;
|
||||
for(int i = 0; i < npdus; i++) {
|
||||
UL_info->rach_ind.number_of_pdus--;
|
||||
if (UL_info->rach_ind.pdu_list[i].num_preamble>0)
|
||||
AssertFatal(UL_info->rach_ind.pdu_list[i].num_preamble==1,
|
||||
"More than 1 preamble not supported\n");
|
||||
|
||||
nr_initiate_ra_proc(UL_info->module_id,
|
||||
UL_info->CC_id,
|
||||
UL_info->rach_ind.sfn,
|
||||
UL_info->rach_ind.slot,
|
||||
UL_info->rach_ind.pdu_list[0].preamble_list[0].preamble_index,
|
||||
UL_info->rach_ind.pdu_list[0].freq_index,
|
||||
UL_info->rach_ind.pdu_list[0].symbol_index,
|
||||
UL_info->rach_ind.pdu_list[0].preamble_list[0].timing_advance);
|
||||
|
||||
nr_initiate_ra_proc(UL_info->module_id,
|
||||
UL_info->CC_id,
|
||||
UL_info->rach_ind.sfn,
|
||||
UL_info->rach_ind.slot,
|
||||
UL_info->rach_ind.pdu_list[i].preamble_list[0].preamble_index,
|
||||
UL_info->rach_ind.pdu_list[i].freq_index,
|
||||
UL_info->rach_ind.pdu_list[i].symbol_index,
|
||||
UL_info->rach_ind.pdu_list[i].preamble_list[0].timing_advance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -203,17 +203,6 @@ typedef struct IF_Module_s{
|
||||
pthread_mutex_t if_mutex;
|
||||
} IF_Module_t;
|
||||
|
||||
// These mutex is used for multiple UEs L2 FAPI simulator.
|
||||
// Each UEs set these value in UL and UL_INFO is shared in all UE's thread.
|
||||
typedef struct {
|
||||
pthread_mutex_t rx_mutex;
|
||||
pthread_mutex_t crc_mutex;
|
||||
pthread_mutex_t sr_mutex;
|
||||
pthread_mutex_t harq_mutex;
|
||||
pthread_mutex_t cqi_mutex;
|
||||
pthread_mutex_t rach_mutex;
|
||||
} FILL_UL_INFO_MUTEX_t;
|
||||
|
||||
/*Initial */
|
||||
IF_Module_t *IF_Module_init(int Mod_id);
|
||||
void IF_Module_kill(int Mod_id);
|
||||
|
||||
@@ -64,8 +64,6 @@ void fill_rx_indication_UE_MAC(module_id_t Mod_id,
|
||||
nfapi_rx_indication_pdu_t *pdu;
|
||||
int timing_advance_update;
|
||||
|
||||
pthread_mutex_lock(&fill_ul_mutex.rx_mutex);
|
||||
|
||||
UL_INFO->rx_ind.sfn_sf = frame << 4 | subframe;
|
||||
UL_INFO->rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG;
|
||||
UL_INFO->rx_ind.vendor_extension = ul_config_req->vendor_extension;
|
||||
@@ -101,7 +99,6 @@ void fill_rx_indication_UE_MAC(module_id_t Mod_id,
|
||||
|
||||
UL_INFO->rx_ind.rx_indication_body.number_of_pdus++;
|
||||
UL_INFO->rx_ind.sfn_sf = frame << 4 | subframe;
|
||||
pthread_mutex_unlock(&fill_ul_mutex.rx_mutex);
|
||||
}
|
||||
|
||||
void fill_sr_indication_UE_MAC(int Mod_id,
|
||||
@@ -109,8 +106,6 @@ void fill_sr_indication_UE_MAC(int Mod_id,
|
||||
int subframe,
|
||||
UL_IND_t *UL_INFO,
|
||||
uint16_t rnti) {
|
||||
pthread_mutex_lock(&fill_ul_mutex.sr_mutex);
|
||||
|
||||
nfapi_sr_indication_t *sr_ind = &UL_INFO->sr_ind;
|
||||
nfapi_sr_indication_body_t *sr_ind_body = &sr_ind->sr_indication_body;
|
||||
nfapi_sr_indication_pdu_t *pdu = &sr_ind_body->sr_pdu_list[sr_ind_body->number_of_srs];
|
||||
@@ -139,7 +134,6 @@ void fill_sr_indication_UE_MAC(int Mod_id,
|
||||
|
||||
// UL_INFO->rx_ind.rx_indication_body.number_of_pdus++;
|
||||
sr_ind_body->number_of_srs++;
|
||||
pthread_mutex_unlock(&fill_ul_mutex.sr_mutex);
|
||||
}
|
||||
|
||||
void fill_crc_indication_UE_MAC(int Mod_id,
|
||||
@@ -149,8 +143,6 @@ void fill_crc_indication_UE_MAC(int Mod_id,
|
||||
uint8_t crc_flag,
|
||||
int index,
|
||||
uint16_t rnti) {
|
||||
pthread_mutex_lock(&fill_ul_mutex.crc_mutex);
|
||||
|
||||
nfapi_crc_indication_pdu_t *pdu =
|
||||
&UL_INFO->crc_ind.crc_indication_body
|
||||
.crc_pdu_list[UL_INFO->crc_ind.crc_indication_body.number_of_crcs];
|
||||
@@ -174,8 +166,6 @@ void fill_crc_indication_UE_MAC(int Mod_id,
|
||||
__FUNCTION__,
|
||||
pdu->rx_ue_information.rnti,
|
||||
UL_INFO->crc_ind.crc_indication_body.number_of_crcs);
|
||||
|
||||
pthread_mutex_unlock(&fill_ul_mutex.crc_mutex);
|
||||
}
|
||||
|
||||
void fill_rach_indication_UE_MAC(int Mod_id,
|
||||
@@ -184,10 +174,6 @@ void fill_rach_indication_UE_MAC(int Mod_id,
|
||||
UL_IND_t *UL_INFO,
|
||||
uint8_t ra_PreambleIndex,
|
||||
uint16_t ra_RNTI) {
|
||||
LOG_D(MAC, "fill_rach_indication_UE_MAC 1 \n");
|
||||
|
||||
pthread_mutex_lock(&fill_ul_mutex.rach_mutex);
|
||||
|
||||
UL_INFO->rach_ind.rach_indication_body.number_of_preambles = 1;
|
||||
|
||||
UL_INFO->rach_ind.header.message_id = NFAPI_RACH_INDICATION;
|
||||
@@ -232,8 +218,6 @@ void fill_rach_indication_UE_MAC(int Mod_id,
|
||||
// should call it when we merge with that branch.
|
||||
oai_nfapi_rach_ind(&UL_INFO->rach_ind);
|
||||
free(UL_INFO->rach_ind.rach_indication_body.preamble_list);
|
||||
|
||||
pthread_mutex_unlock(&fill_ul_mutex.rach_mutex);
|
||||
}
|
||||
|
||||
void fill_ulsch_cqi_indication_UE_MAC(int Mod_id,
|
||||
@@ -241,7 +225,6 @@ void fill_ulsch_cqi_indication_UE_MAC(int Mod_id,
|
||||
uint8_t subframe,
|
||||
UL_IND_t *UL_INFO,
|
||||
uint16_t rnti) {
|
||||
pthread_mutex_lock(&fill_ul_mutex.cqi_mutex);
|
||||
nfapi_cqi_indication_pdu_t *pdu =
|
||||
&UL_INFO->cqi_ind.cqi_indication_body
|
||||
.cqi_pdu_list[UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis];
|
||||
@@ -275,7 +258,6 @@ void fill_ulsch_cqi_indication_UE_MAC(int Mod_id,
|
||||
raw_pdu->pdu[0] = cqi << 4;
|
||||
|
||||
UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis++;
|
||||
pthread_mutex_unlock(&fill_ul_mutex.cqi_mutex);
|
||||
}
|
||||
|
||||
void fill_ulsch_harq_indication_UE_MAC(
|
||||
@@ -285,8 +267,6 @@ void fill_ulsch_harq_indication_UE_MAC(
|
||||
UL_IND_t *UL_INFO,
|
||||
nfapi_ul_config_ulsch_harq_information *harq_information,
|
||||
uint16_t rnti) {
|
||||
pthread_mutex_lock(&fill_ul_mutex.harq_mutex);
|
||||
|
||||
nfapi_harq_indication_pdu_t *pdu =
|
||||
&UL_INFO->harq_ind.harq_indication_body.harq_pdu_list
|
||||
[UL_INFO->harq_ind.harq_indication_body.number_of_harqs];
|
||||
@@ -318,7 +298,6 @@ void fill_ulsch_harq_indication_UE_MAC(
|
||||
}
|
||||
|
||||
UL_INFO->harq_ind.harq_indication_body.number_of_harqs++;
|
||||
pthread_mutex_unlock(&fill_ul_mutex.harq_mutex);
|
||||
}
|
||||
|
||||
void fill_uci_harq_indication_UE_MAC(int Mod_id,
|
||||
@@ -327,8 +306,6 @@ void fill_uci_harq_indication_UE_MAC(int Mod_id,
|
||||
UL_IND_t *UL_INFO,
|
||||
nfapi_ul_config_harq_information *harq_information,
|
||||
uint16_t rnti) {
|
||||
pthread_mutex_lock(&fill_ul_mutex.harq_mutex);
|
||||
|
||||
nfapi_harq_indication_t *ind = &UL_INFO->harq_ind;
|
||||
nfapi_harq_indication_body_t *body = &ind->harq_indication_body;
|
||||
nfapi_harq_indication_pdu_t *pdu =
|
||||
@@ -410,7 +387,6 @@ void fill_uci_harq_indication_UE_MAC(int Mod_id,
|
||||
LOG_D(PHY,
|
||||
"Incremented eNB->UL_INFO.harq_ind.number_of_harqs:%d\n",
|
||||
UL_INFO->harq_ind.harq_indication_body.number_of_harqs);
|
||||
pthread_mutex_unlock(&fill_ul_mutex.harq_mutex);
|
||||
}
|
||||
|
||||
void handle_nfapi_ul_pdu_UE_MAC(module_id_t Mod_id,
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
//#include "openair1/PHY/defs.h"
|
||||
//#include "openair1/PHY/LTE_TRANSPORT/defs.h"
|
||||
|
||||
// this mutex is used to set multiple UE's UL value in L2 FAPI simulator.
|
||||
FILL_UL_INFO_MUTEX_t fill_ul_mutex;
|
||||
//below 2 difinitions move to phy_stub_UE.c to add initialization when difinition.
|
||||
extern UL_IND_t *UL_INFO;
|
||||
extern nfapi_tx_request_pdu_t* tx_request_pdu_list;
|
||||
|
||||
@@ -174,10 +174,41 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.present = NR_CFRA__resources_PR_ssb;
|
||||
secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb = calloc(1,sizeof(struct NR_CFRA__resources__ssb));
|
||||
secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ra_ssb_OccasionMaskIndex = 0;
|
||||
struct NR_CFRA_SSB_Resource *ssbElem = calloc(1,sizeof(struct NR_CFRA_SSB_Resource));
|
||||
ssbElem->ssb = 0;
|
||||
ssbElem->ra_PreambleIndex= 63;
|
||||
ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem);
|
||||
struct NR_CFRA_SSB_Resource *ssbElem[8];
|
||||
ssbElem[0] = calloc(1,sizeof(struct NR_CFRA_SSB_Resource));
|
||||
ssbElem[0]->ssb = 0;
|
||||
ssbElem[0]->ra_PreambleIndex = 63;
|
||||
ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem[0]);
|
||||
#if 0
|
||||
ssbElem[1] = calloc(1,sizeof(struct NR_CFRA_SSB_Resource));
|
||||
ssbElem[1]->ssb = 1;
|
||||
ssbElem[1]->ra_PreambleIndex = 62;
|
||||
ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem[1]);
|
||||
ssbElem[2] = calloc(1,sizeof(struct NR_CFRA_SSB_Resource));
|
||||
ssbElem[2]->ssb = 2;
|
||||
ssbElem[2]->ra_PreambleIndex = 63;
|
||||
ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem[2]);
|
||||
ssbElem[3] = calloc(1,sizeof(struct NR_CFRA_SSB_Resource));
|
||||
ssbElem[3]->ssb = 3;
|
||||
ssbElem[3]->ra_PreambleIndex = 63;
|
||||
ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem[3]);
|
||||
ssbElem[4] = calloc(1,sizeof(struct NR_CFRA_SSB_Resource));
|
||||
ssbElem[4]->ssb = 4;
|
||||
ssbElem[4]->ra_PreambleIndex = 63;
|
||||
ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem[4]);
|
||||
ssbElem[5] = calloc(1,sizeof(struct NR_CFRA_SSB_Resource));
|
||||
ssbElem[5]->ssb = 5;
|
||||
ssbElem[5]->ra_PreambleIndex = 63;
|
||||
ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem[5]);
|
||||
ssbElem[6] = calloc(1,sizeof(struct NR_CFRA_SSB_Resource));
|
||||
ssbElem[6]->ssb = 6;
|
||||
ssbElem[6]->ra_PreambleIndex = 63;
|
||||
ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem[6]);
|
||||
ssbElem[7] = calloc(1,sizeof(struct NR_CFRA_SSB_Resource));
|
||||
ssbElem[7]->ssb = 7;
|
||||
ssbElem[7]->ra_PreambleIndex = 63;
|
||||
ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem[7]);
|
||||
#endif
|
||||
secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->ext1 = NULL;
|
||||
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants));
|
||||
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->present = NR_SetupRelease_RLF_TimersAndConstants_PR_setup;
|
||||
|
||||
@@ -1177,7 +1177,7 @@ void init_eNB_afterRU(void) {
|
||||
|
||||
for (i=0; i<eNB->RU_list[ru_id]->nb_rx; aa++,i++) {
|
||||
LOG_I(PHY,"Attaching RU %d antenna %d to eNB antenna %d\n",eNB->RU_list[ru_id]->idx,i,aa);
|
||||
eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[ru_id]->prach_rxsigF[i];
|
||||
eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[ru_id]->prach_rxsigF[0][i];
|
||||
|
||||
for (int ce_level=0; ce_level<4; ce_level++)
|
||||
eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[ru_id]->prach_rxsigF_br[ce_level][i];
|
||||
|
||||
Reference in New Issue
Block a user