Commit 80712639 authored by Xu Bo's avatar Xu Bo Committed by xubo

modify function for issue271

parent 088d4b2e
......@@ -605,6 +605,7 @@ add_boolean_option(MESSAGE_CHART_GENERATOR_RLC_MAC False "trace RLC-MAC exchange
add_boolean_option(MESSAGE_CHART_GENERATOR_PHY False "trace some PHY exchanges in sequence diagrams")
add_boolean_option(FLEXRAN_AGENT_SB_IF False "enable FlexRAN agent to inteface with a SDN controller")
add_boolean_option(UE_EXPANSION False "enable UE_EXPANSION with max 256 UE")
########################
# Include order
......
......@@ -43,6 +43,7 @@ conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf
MSC_GEN="False"
XFORMS="True"
FLEXRAN_AGENT_SB_IF="True"
UE_EXPANSION="False"
PRINT_STATS="False"
VCD_TIMING="False"
DEADLINE_SCHEDULER_FLAG_USER="False"
......@@ -210,6 +211,10 @@ function main() {
UE=1
echo_info "Will compile UE"
shift;;
--mu)
UE_EXPANSION="True"
echo_info "Will compile with UE_EXPANSION"
shift;;
--UE-conf-nvram)
conf_nvram_path=$(readlink -f "$1")
shift 2;;
......@@ -528,6 +533,7 @@ function main() {
if [ "$FLEXRAN_AGENT" = "1" ] ; then
echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )" >> $cmake_file
fi
echo "set ( UE_EXPANSION $UE_EXPANSION )" >> $cmake_file
echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
echo "set ( RF_BOARD \"${HW}\")" >> $cmake_file
......@@ -689,6 +695,7 @@ function main() {
if [ "$FLEXRAN_AGENT" = "1" ] ; then
echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )" >> $cmake_file
fi
echo "set ( UE_EXPANSION $UE_EXPANSION )" >> $cmake_file
echo "set ( PRINT_STATS $PRINT_STATS )" >> $cmake_file
echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
......@@ -772,6 +779,7 @@ function main() {
if [ "$FLEXRAN_AGENT" = "1" ] ; then
echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )" >> $cmake_file
fi
echo "set ( UE_EXPANSION $UE_EXPANSION )" >> $cmake_file
echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
......
......@@ -636,6 +636,7 @@ typedef struct {
struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[MAX_MBSFN_AREA];
uint32_t ue_multiple_max;
} LTE_DL_FRAME_PARMS;
typedef enum {
......
......@@ -166,6 +166,7 @@ typedef struct RrcConfigurationReq_s {
long ue_TimersAndConstants_n310[MAX_NUM_CCs];
long ue_TimersAndConstants_n311[MAX_NUM_CCs];
long ue_TransmissionMode[MAX_NUM_CCs];
long ue_multiple_max[MAX_NUM_CCs];
} RrcConfigurationReq;
// UE: NAS -> RRC messages
......
......@@ -438,6 +438,7 @@ int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc) {
int32_t ue_TimersAndConstants_n311 = 0;
int32_t ue_TransmissionMode = 0;
int32_t ue_multiple_max = 0;
int32_t srb1_timer_poll_retransmit = 0;
int32_t srb1_timer_reordering = 0;
......@@ -1717,6 +1718,36 @@ int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc) {
RC.config_file_name, i, ue_TransmissionMode);
break;
}
#ifdef UE_EXPANSION
RRC_CONFIGURATION_REQ (msg_p).ue_multiple_max[j] = ue_multiple_max;
switch (N_RB_DL) {
case 25:
if ((ue_multiple_max < 1) || (ue_multiple_max > 5))
AssertFatal (0,
"Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for ue_multiple_max choice: 1..5!\n",
RC.config_file_name, i, ue_multiple_max);
break;
case 50:
if ((ue_multiple_max < 1) || (ue_multiple_max > 10))
AssertFatal (0,
"Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for ue_multiple_max choice: 1..10!\n",
RC.config_file_name, i, ue_multiple_max);
break;
case 100:
if ((ue_multiple_max < 1) || (ue_multiple_max > 20))
AssertFatal (0,
"Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for ue_multiple_max choice: 1..20!\n",
RC.config_file_name, i, ue_multiple_max);
break;
default:
AssertFatal (0,
"Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for N_RB_DL choice: 25,50,100 !\n",
RC.config_file_name, i, N_RB_DL);
break;
}
#endif
}
}
char srb1path[MAX_OPTNAME_SIZE*2 + 8];
......
......@@ -371,6 +371,7 @@ static int DEFENBS[] = {0};
#define ENB_CONFIG_STRING_UETIMERS_N310 "ue_TimersAndConstants_n310"
#define ENB_CONFIG_STRING_UETIMERS_N311 "ue_TimersAndConstants_n311"
#define ENB_CONFIG_STRING_UE_TRANSMISSION_MODE "ue_TransmissionMode"
#define ENB_CONFIG_STRING_UE_MULTIPLE_MAX "ue_multiple_max"
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* component carriers configuration parameters */
......@@ -444,7 +445,8 @@ static int DEFENBS[] = {0};
{ENB_CONFIG_STRING_UETIMERS_T311, NULL, 0, iptr:&ue_TimersAndConstants_t311, defintval:10000, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_UETIMERS_N310, NULL, 0, iptr:&ue_TimersAndConstants_n310, defintval:20, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_UETIMERS_N311, NULL, 0, iptr:&ue_TimersAndConstants_n311, defintval:1, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_UE_TRANSMISSION_MODE, NULL, 0, iptr:&ue_TransmissionMode, defintval:1, TYPE_UINT, 0} \
{ENB_CONFIG_STRING_UE_TRANSMISSION_MODE, NULL, 0, iptr:&ue_TransmissionMode, defintval:1, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_UE_MULTIPLE_MAX, NULL, 0, iptr:&ue_multiple_max, defintval:5, TYPE_UINT, 0} \
}
/*------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
......
......@@ -1327,6 +1327,48 @@ typedef struct {
uint8_t n_adj_cells;
} neigh_cell_id_t;
#ifdef UE_EXPANSION
enum SCH_UE_PRIORITY {
SCH_PRIORITY_NONE,
SCH_DL_SI,
SCH_DL_PAGING,
SCH_DL_MSG2,
SCH_DL_MSG4,
SCH_UL_PRACH,
SCH_UL_MSG3,
SCH_DL_RETRANS,
SCH_UL_RETRANS,
SCH_DL_FIRST,
SCH_UL_FIRST,
SCH_UL_INACTIVE
};
typedef struct {
int UE_id;
enum SCH_UE_PRIORITY ue_priority;
rnti_t rnti;
uint16_t nb_rb;
} DLSCH_UE_INFO;
typedef struct {
uint16_t ue_num;
DLSCH_UE_INFO list[20];
} DLSCH_UE_SELECT;
typedef struct {
int UE_id;
enum SCH_UE_PRIORITY ue_priority;
uint8_t start_rb;
uint8_t nb_rb;
uint16_t ul_total_buffer;
} ULSCH_UE_INFO;
typedef struct {
uint8_t ue_num;
ULSCH_UE_INFO list[20];
} ULSCH_UE_SELECT;
#endif
#include "proto.h"
/*@}*/
#endif /*__LAYER2_MAC_DEFS_H__ */
......
......@@ -504,6 +504,10 @@ schedule_ue_spec(
}
}
#ifdef UE_EXPANSION
DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs];
memset(dlsch_ue_select, 0, sizeof(dlsch_ue_select));
#endif
//weight = get_ue_weight(module_idP,UE_id);
aggregation = 2;
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
......@@ -533,7 +537,11 @@ schedule_ue_spec(
frameP,
subframeP,
N_RBG,
mbsfn_flag);
mbsfn_flag
#ifdef UE_EXPANSION
, dlsch_ue_select
#endif
);
stop_meas(&eNB->schedule_dlsch_preprocessor);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT);
......@@ -545,7 +553,14 @@ schedule_ue_spec(
if (mbsfn_flag[CC_id]>0)
continue;
#ifdef UE_EXPANSION
for (i = 0; i < dlsch_ue_select[CC_id].ue_num; i++) {
UE_id = dlsch_ue_select[CC_id].list[i].UE_id;
#else
for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
#endif
continue_flag=0; // reset the flag to allow allocation for the remaining UEs
rnti = UE_RNTI(module_idP,UE_id);
eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
......@@ -1319,9 +1334,11 @@ schedule_ue_spec(
} // CC_id loop
#ifndef UE_EXPANSION
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_flag);
#else
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_flag,dlsch_ue_select);
#endif
stop_meas(&eNB->schedule_dlsch);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_OUT);
......@@ -1334,6 +1351,9 @@ fill_DLSCH_dci(
frame_t frameP,
sub_frame_t subframeP,
int* mbsfn_flagP
#ifdef UE_EXPANSION
, DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]
#endif
)
//------------------------------------------------------------------------------
{
......@@ -1370,7 +1390,12 @@ fill_DLSCH_dci(
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
// UE specific DCIs
#ifdef UE_EXPANSION
for (i = 0; i < dlsch_ue_select[CC_id].ue_num; i++) {
UE_id = dlsch_ue_select[CC_id].list[i].UE_id;
#else
for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
#endif
LOG_T(MAC,"CC_id %d, UE_id: %d => status %d\n",CC_id,UE_id,eNB_dlsch_info[module_idP][CC_id][UE_id].status);
if (eNB_dlsch_info[module_idP][CC_id][UE_id].status == S_DL_SCHEDULED) {
......
......@@ -731,7 +731,10 @@ void schedule_ulsch(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP)
{
uint16_t first_rb[MAX_NUM_CCs],i;
#ifndef UE_EXPANSION
uint16_t first_rb[MAX_NUM_CCs];
#endif
uint16_t i;
int CC_id;
eNB_MAC_INST *eNB=RC.mac[module_idP];
COMMON_channels_t *cc;
......@@ -793,6 +796,8 @@ void schedule_ulsch(module_id_t module_idP,
break;
}
}
#ifndef UE_EXPANSION
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
......@@ -828,10 +833,54 @@ void schedule_ulsch(module_id_t module_idP,
}
schedule_ulsch_rnti(module_idP, frameP, subframeP, sched_subframe,first_rb);
#else
ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs];
memset(ulsch_ue_select, 0, sizeof(ulsch_ue_select));
LTE_DL_FRAME_PARMS *frame_parms ;
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
cc = &eNB->common_channels[CC_id];
frame_parms= &RC.eNB[module_idP][CC_id]->frame_parms;
// output of scheduling, the UE numbers in RBs, where it is in the code???
// check if RA (Msg3) is active in this subframeP, if so skip the PRBs used for Msg3
// Msg3 is using 1 PRB so we need to increase first_rb accordingly
// not sure about the break (can there be more than 1 active RA procedure?)
for (i=0; i<NB_RA_PROC_MAX; i++) {
if ((cc->RA_template[i].RA_active == TRUE) &&
(cc->RA_template[i].generate_rar == 0) &&
(cc->RA_template[i].generate_Msg4 == 0) &&
(cc->RA_template[i].wait_ack_Msg4 == 0) &&
(cc->RA_template[i].Msg3_subframe == sched_subframe)) {
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_MSG3;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = 1;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].nb_rb = 1;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = -1;
ulsch_ue_select[CC_id].ue_num++;
break;
}
}
//PRACH
if (is_prach_subframe(frame_parms,frameP,subframeP)==1) {
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_PRACH;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = get_prach_prb_offset(
frame_parms,
frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex,
frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset,
0,//tdd_mapindex
frameP); //Nf
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].nb_rb = 6;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = -1;
ulsch_ue_select[CC_id].ue_num++;
}
}
schedule_ulsch_rnti(module_idP, frameP, subframeP, sched_subframe,ulsch_ue_select);
#endif
stop_meas(&eNB->schedule_ulsch);
}
#ifndef UE_EXPANSION
void schedule_ulsch_rnti(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP,
......@@ -1242,3 +1291,382 @@ abort();
} // loop over UE_id
} // loop of CC_id
}
#else
void schedule_ulsch_rnti(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP,
unsigned char sched_subframeP,
ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs])
{
int16_t UE_id;
uint8_t aggregation = 2;
uint16_t first_rb[MAX_NUM_CCs];
uint8_t ULSCH_first_end;
rnti_t rnti = -1;
uint8_t round = 0;
uint8_t harq_pid = 0;
uint8_t status = 0;
uint8_t rb_table_index = -1;
uint32_t cqi_req,cshift,ndi,tpc;
int32_t normalized_rx_power;
int32_t target_rx_power=-90;
static int32_t tpc_accumulated=0;
int CC_id,ulsch_ue_num;
int N_RB_UL;
eNB_MAC_INST *eNB = RC.mac[module_idP];
COMMON_channels_t *cc;
UE_list_t *UE_list=&eNB->UE_list;
UE_TEMPLATE *UE_template;
UE_sched_ctrl *UE_sched_ctrl;
int sched_frame=frameP;
int rvidx_tab[4] = {0,2,3,1};
if (sched_subframeP < subframeP) sched_frame++;
nfapi_hi_dci0_request_body_t *hi_dci0_req = &eNB->HI_DCI0_req[module_idP].hi_dci0_request_body;
nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu;
nfapi_ul_config_request_body_t *ul_req_tmp = &eNB->UL_req_tmp[module_idP][sched_subframeP].ul_config_request_body;
LOG_D(MAC,"entering ulsch preprocesor\n");
ulsch_scheduler_pre_processor(module_idP,
frameP,
subframeP,
ulsch_ue_select);
LOG_D(MAC,"exiting ulsch preprocesor\n");
eNB->HI_DCI0_req[module_idP].sfn_sf = (frameP<<4)+subframeP;
// loop over all active UEs
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
//leave out first RB for PUCCH
first_rb[CC_id] = 1;
ULSCH_first_end = 0;
cc = &eNB->common_channels[CC_id];
for ( ulsch_ue_num = 0; ulsch_ue_num < ulsch_ue_select[CC_id].ue_num; ulsch_ue_num++ ) {
// This is the actual CC_id in the list
N_RB_UL = to_prb(cc->ul_Bandwidth);
UE_id = ulsch_ue_select[CC_id].list[ulsch_ue_num].UE_id;
/* be sure that there are some free RBs */
if (first_rb[CC_id] >= N_RB_UL-1) {
LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n",
module_idP,frameP,subframeP,UE_id,rnti,CC_id);
break;
}
//MSG3
if (ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_MSG3) {
first_rb[CC_id] ++;
continue;
}
//PRACH
if (ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_PRACH) {
first_rb[CC_id] = ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb+ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb;
continue;
}
UE_template = &UE_list->UE_template[CC_id][UE_id];
UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
harq_pid = subframe2harqpid(cc,sched_frame,sched_subframeP);
rnti = UE_RNTI(CC_id,UE_id);
LOG_D(MAC,"[eNB %d] frame %d subframe %d,Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d, N_RB_UL %d\n",
module_idP,frameP,subframeP,harq_pid,UE_id,rnti,CC_id, aggregation,N_RB_UL);
RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP] = UE_template->ul_total_buffer;
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO,RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP]);
status = mac_eNB_get_rrc_status(module_idP,rnti);
if (status < RRC_CONNECTED)
cqi_req = 0;
else if (UE_sched_ctrl->cqi_req_timer>30) {
cqi_req = 1;
UE_sched_ctrl->cqi_req_timer=0;
}
else
cqi_req = 0;
//power control
//compute the expected ULSCH RX power (for the stats)
// this is the normalized RX power and this should be constant (regardless of mcs
normalized_rx_power = UE_sched_ctrl->pusch_snr[CC_id];
target_rx_power = 178;
// this assumes accumulated tpc
// make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
int32_t framex10psubframe = UE_template->pusch_tpc_tx_frame*10+UE_template->pusch_tpc_tx_subframe;
if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case
((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) //frame wrap-around
{
UE_template->pusch_tpc_tx_frame=frameP;
UE_template->pusch_tpc_tx_subframe=subframeP;
if (normalized_rx_power>(target_rx_power+4)) {
tpc = 0; //-1
tpc_accumulated--;
} else if (normalized_rx_power<(target_rx_power-4)) {
tpc = 2; //+1
tpc_accumulated++;
} else {
tpc = 1; //0
}
} else {
tpc = 1; //0
}
if (tpc!=1) {
LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
module_idP,frameP,subframeP,harq_pid,tpc,
tpc_accumulated,normalized_rx_power,target_rx_power);
}
// new transmission
if ((ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_FIRST) ||
(ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_INACTIVE)) {
LOG_D(MAC,"[eNB %d][PUSCH %d] Frame %d subframe %d Scheduling UE %d/%x (SR %d,UL_inactivity timer %d,UL_failure timer %d,cqi_req_timer %d)\n",
module_idP,harq_pid,frameP,subframeP,UE_id,rnti,UE_template->ul_SR,
UE_sched_ctrl->ul_inactivity_timer,
UE_sched_ctrl->ul_failure_timer,
UE_sched_ctrl->cqi_req_timer);
ndi = 1-UE_template->oldNDI_UL[harq_pid];
UE_template->oldNDI_UL[harq_pid]=ndi;
UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power;
UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power;
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul;
UE_template->mcs_UL[harq_pid] = UE_template->pre_assigned_mcs_ul;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS
if (UE_template->pre_allocated_rb_table_index_ul >=0) {
rb_table_index=UE_template->pre_allocated_rb_table_index_ul;
} else {
UE_template->mcs_UL[harq_pid]=10;//cmin (10, openair_daq_vars.target_ue_ul_mcs);
rb_table_index=5; // for PHR
}
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=UE_template->mcs_UL[harq_pid];
UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],rb_table[rb_table_index]);
UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=rb_table[rb_table_index];
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid];
T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP),
T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]),
T_INT(UE_template->TBS_UL[harq_pid]), T_INT(ndi));
if (mac_eNB_get_rrc_status(module_idP,rnti) < RRC_CONNECTED)
LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n",
module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,UE_template->mcs_UL[harq_pid],
first_rb[CC_id],rb_table[rb_table_index],
rb_table_index,UE_template->TBS_UL[harq_pid],harq_pid);
// bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB)
//store for possible retransmission
UE_template->nb_rb_ul[harq_pid] = rb_table[rb_table_index];
UE_template->first_rb_ul[harq_pid] = first_rb[CC_id];
UE_sched_ctrl->ul_scheduled |= (1<<harq_pid);
if (UE_id == UE_list->head)
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED,UE_sched_ctrl->ul_scheduled);
// adjust total UL buffer status by TBS, wait for UL sdus to do final update
LOG_D(MAC,"[eNB %d] CC_id %d UE %d/%x : adjusting ul_total_buffer, old %d, TBS %d\n", module_idP,CC_id,UE_id,rnti,UE_template->ul_total_buffer,UE_template->TBS_UL[harq_pid]);
if (UE_template->ul_total_buffer > UE_template->TBS_UL[harq_pid])
UE_template->ul_total_buffer -= UE_template->TBS_UL[harq_pid];
else
UE_template->ul_total_buffer = 0;
LOG_D(MAC,"ul_total_buffer, new %d\n", UE_template->ul_total_buffer);
// Cyclic shift for DM RS
cshift = 0;// values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1)
// save it for a potential retransmission
UE_template->cshift[harq_pid] = cshift;
hi_dci0_pdu = &hi_dci0_req->hi_dci0_pdu_list[eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci+eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_hi];
memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t));
hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE;
hi_dci0_pdu->pdu_size = 2+sizeof(nfapi_hi_dci0_dci_pdu);
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb[CC_id];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = rb_table[rb_table_index];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = UE_template->mcs_UL[harq_pid];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = ndi;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = cqi_req;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = UE_template->DAI_ul[sched_subframeP];
eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci++;
LOG_D(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n",
harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP);
// Add UL_config PDUs
fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus],
cqi_req,
cc,
UE_template->physicalConfigDedicated,
get_tmode(module_idP,CC_id,UE_id),
eNB->ul_handle,
rnti,
first_rb[CC_id], // resource_block_start
rb_table[rb_table_index], // number_of_resource_blocks
UE_template->mcs_UL[harq_pid],
cshift, // cyclic_shift_2_for_drms
0, // frequency_hopping_enabled_flag
0, // frequency_hopping_bits
ndi, // new_data_indication
0, // redundancy_version
harq_pid, // harq_process_number
0, // ul_tx_mode
0, // current_tx_nb
0, // n_srs
get_TBS_UL(UE_template->mcs_UL[harq_pid],
rb_table[rb_table_index])
);
#ifdef Rel14
if (UE_template->rach_resource_type>0) { // This is a BL/CE UE allocation
fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus],
UE_template->rach_resource_type>2 ? 2 : 1,
1, //total_number_of_repetitions
1, //repetition_number
(frameP*10)+subframeP);
}
#endif
ul_req_tmp->number_of_pdus++;
eNB->ul_handle++;
add_ue_ulsch_info(module_idP,
CC_id,
UE_id,
subframeP,
S_UL_SCHEDULED);
LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", module_idP,CC_id,frameP,subframeP,UE_id);
// increment first rb for next UE allocation
first_rb[CC_id]+=rb_table[rb_table_index];
if(ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_FIRST) {
if(ulsch_ue_select[CC_id].list[ulsch_ue_num].ul_total_buffer > 0){
if (UE_template->ul_total_buffer > UE_template->TBS_UL[harq_pid])
UE_template->ul_total_buffer -= UE_template->TBS_UL[harq_pid];
else
UE_template->ul_total_buffer = 0;
} else {
UE_template->ul_SR = 0;
}
}
if((ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_INACTIVE) && (ULSCH_first_end == 0)) {
ULSCH_first_end = 1;
last_ulsch_ue_id[CC_id] = ulsch_ue_select[CC_id].list[ulsch_ue_num-1].UE_id;
}
if((ulsch_ue_num == ulsch_ue_select[CC_id].ue_num-1) && (ULSCH_first_end == 0)) {
ULSCH_first_end = 1;
last_ulsch_ue_id[CC_id] = ulsch_ue_select[CC_id].list[ulsch_ue_num].UE_id;
}
}
else if (ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_RETRANS) { // round > 0 => retransmission
T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP),
T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]),
T_INT(round));
round = UE_sched_ctrl->round_UL[CC_id][harq_pid];
UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power;
UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power;
UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb);
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid];
if (mac_eNB_get_rrc_status(module_idP,rnti) < RRC_CONNECTED)
LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n",
module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,UE_template->mcs_UL[harq_pid],
first_rb[CC_id],rb_table[rb_table_index],
rb_table_index,UE_template->TBS_UL[harq_pid],harq_pid);
// bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB)
//store for possible retransmission
UE_template->nb_rb_ul[harq_pid] = ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb;
UE_template->first_rb_ul[harq_pid] = ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb;
UE_sched_ctrl->ul_scheduled |= (1<<harq_pid);
// Cyclic shift for DM RS
cshift = 0;// values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1)
hi_dci0_pdu = &hi_dci0_req->hi_dci0_pdu_list[eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci+eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_hi];
memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t));
hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE;
hi_dci0_pdu->pdu_size = 2+sizeof(nfapi_hi_dci0_dci_pdu);
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = UE_template->mcs_UL[harq_pid];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = UE_template->oldNDI_UL[harq_pid];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = cqi_req;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = UE_template->DAI_ul[sched_subframeP];
eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci++;
// fill in NAK information
hi_dci0_pdu = &hi_dci0_req->hi_dci0_pdu_list[hi_dci0_req->number_of_dci+hi_dci0_req->number_of_hi];
memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t));
hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE;
hi_dci0_pdu->pdu_size = 2+sizeof(nfapi_hi_dci0_hi_pdu);
hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start = ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb;
hi_dci0_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = UE_template->cshift[harq_pid];
hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value = 0;
hi_dci0_req->number_of_hi++;
LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled (PHICH) UE %d (mcs %d, first rb %d, nb_rb %d, TBS %d, round %d)\n",
module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,UE_template->mcs_UL[harq_pid],
ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb, ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb,
UE_template->TBS_UL[harq_pid],round);
// Add UL_config PDUs
LOG_D(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n",
harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP);
fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus],
cqi_req,
cc,
UE_template->physicalConfigDedicated,
get_tmode(module_idP,CC_id,UE_id),
eNB->ul_handle,
rnti,
ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb, // resource_block_start
ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb, // number_of_resource_blocks
UE_template->mcs_UL[harq_pid],
cshift, // cyclic_shift_2_for_drms
0, // frequency_hopping_enabled_flag
0, // frequency_hopping_bits
UE_template->oldNDI_UL[harq_pid], // new_data_indication
rvidx_tab[round&3], // redundancy_version
harq_pid, // harq_process_number
0, // ul_tx_mode
0, // current_tx_nb
0, // n_srs
get_TBS_UL(UE_template->mcs_UL[harq_pid],
ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb)
);
#ifdef Rel14
if (UE_template->rach_resource_type>0) { // This is a BL/CE UE allocation
fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus],
UE_template->rach_resource_type>2 ? 2 : 1,
1, //total_number_of_repetitions
1, //repetition_number
(frameP*10)+subframeP);
}
#endif
ul_req_tmp->number_of_pdus++;
eNB->ul_handle++;
LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0(round >0)\n", module_idP,CC_id,frameP,subframeP,UE_id);
// increment first rb for next UE allocation
first_rb[CC_id]+=ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb;
}
} // loop over UE_id
} // loop of CC_id
}
#endif
......@@ -101,6 +101,11 @@ extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu1;
extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu2;
extern DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu1E;
#ifdef UE_EXPANSION
extern int last_dlsch_ue_id[MAX_NUM_CCs];
extern int last_ulsch_ue_id[MAX_NUM_CCs];
#endif
#endif //DEF_H
......@@ -481,7 +481,365 @@ void sort_UEs (module_id_t Mod_idP,
#endif
}
#ifdef UE_EXPANSION
void dlsch_scheduler_pre_ue_select(
module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP,
int* mbsfn_flag,
uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs])
{
uint8_t CC_id;
int UE_id;
// uint16_t nb_rb;
unsigned char round = 0;
unsigned char harq_pid = 0;
eNB_MAC_INST *eNB = RC.mac[module_idP];
COMMON_channels_t *cc = eNB->common_channels;
UE_list_t *UE_list = &eNB->UE_list;
UE_sched_ctrl *ue_sched_ctl;
rnti_t rnti;
unsigned char aggregation;
// int i;
// int N_RB_DL[MAX_NUM_CCs];
uint16_t used_dlsch_rbs_num[MAX_NUM_CCs] = {0};
uint16_t available_dlsch_rbs_num[MAX_NUM_CCs] = {0};
uint16_t dl_ue_max_num[MAX_NUM_CCs] = {0};
uint16_t dlsch_ue_max_num[MAX_NUM_CCs] = {0};
int format_flag;
nfapi_dl_config_request_body_t *DL_req;
nfapi_dl_config_request_pdu_t *dl_config_pdu;
uint16_t saved_dlsch_dci[MAX_NUM_CCs] = {0};
int continue_flag = 0;
int old_last_dlsch_ue_id[MAX_NUM_CCs];
// Initialization
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
// get maximum UE number of DLSCH
dl_ue_max_num[CC_id] = NUMBER_OF_UE_MAX;
dlsch_ue_max_num[CC_id] = (uint16_t)RC.rrc[module_idP]->configuration.ue_multiple_max[CC_id];
// save origin DL PDU number
DL_req = &eNB->DL_req[CC_id].dl_config_request_body;
saved_dlsch_dci[CC_id] = DL_req->number_pdu;
// set available_dlsch_rbs
available_dlsch_rbs_num[CC_id] = eNB->eNB_stats[CC_id].available_prbs;
// get last DLSCH ue_id
old_last_dlsch_ue_id[CC_id] = last_dlsch_ue_id[CC_id];
}
// Insert DLSCH(retransmission) UE into selected UE list
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
if (mbsfn_flag[CC_id]>0) {
continue;
}
DL_req = &eNB->DL_req[CC_id].dl_config_request_body;
for (UE_id = 0; UE_id < dl_ue_max_num[CC_id] /*NUMBER_OF_UE_MAX*/; UE_id++) {
if (UE_list->active[UE_id] == FALSE) {
continue;
}
rnti = UE_RNTI(module_idP, UE_id);
if (rnti == NOT_A_RNTI) {
continue;
}
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
if (ue_sched_ctl->ul_out_of_sync == 1) {
continue;
}
if (nb_rbs_required[CC_id][UE_id] == 0) {
continue;
}
if (cc[CC_id].tdd_Config) harq_pid = ((frameP*10)+subframeP)%10;
else harq_pid = ((frameP*10)+subframeP)&7;
round = ue_sched_ctl->round[CC_id][harq_pid];
if (round != 8) { // retransmission
switch (get_tmode(module_idP, CC_id, UE_id)) {
case 1:
case 2:
case 7:
aggregation = get_aggregation(get_bw_index(module_idP, CC_id),
ue_sched_ctl->dl_cqi[CC_id],
format1);
break;
case 3:
aggregation = get_aggregation(get_bw_index(module_idP,CC_id),
ue_sched_ctl->dl_cqi[CC_id],
format2A);
break;
default:
LOG_W(MAC,"Unsupported transmission mode %d\n", get_tmode(module_idP,CC_id,UE_id));
aggregation = 2;
}
format_flag = 1;
if (!CCE_allocation_infeasible(module_idP,
CC_id,
format_flag,
subframeP,
aggregation,
rnti)) {
dl_config_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu];
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = (format_flag == 0)?2:1;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation;
DL_req->number_pdu++;
nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
// Insert DLSCH(retransmission) UE into selected UE list
dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].UE_id = UE_id;
dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].ue_priority = SCH_DL_RETRANS;
dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].rnti = rnti;
dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].nb_rb = nb_rbs_required[CC_id][UE_id];
dlsch_ue_select[CC_id].ue_num++;
used_dlsch_rbs_num[CC_id] += nb_rbs_required[CC_id][UE_id];
if (dlsch_ue_select[CC_id].ue_num == dlsch_ue_max_num[CC_id]) {
break;
}
if (used_dlsch_rbs_num[CC_id] > available_dlsch_rbs_num[CC_id]) {
dlsch_ue_select[CC_id].ue_num--; // roll back
break;
}
} else {
if (cc[CC_id].tdd_Config != NULL) { //TDD
set_ue_dai (subframeP,
UE_id,
CC_id,
cc[CC_id].tdd_Config->subframeAssignment,
UE_list);
// update UL DAI after DLSCH scheduling
set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP);
}
add_ue_dlsch_info(module_idP,
CC_id,
UE_id,
subframeP,
S_DL_NONE);
}
}
}
}
// Insert DLSCH(first transmission) UE into selected UE list (UE_id > last_dlsch_ue_id[CC_id])
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
if (mbsfn_flag[CC_id]>0) {
continue;
}
if (dlsch_ue_select[CC_id].ue_num < dlsch_ue_max_num[CC_id] &&
used_dlsch_rbs_num[CC_id] < available_dlsch_rbs_num[CC_id]) {
DL_req = &eNB->DL_req[CC_id].dl_config_request_body;
for (UE_id = (old_last_dlsch_ue_id[CC_id]+1); UE_id < dl_ue_max_num[CC_id]; UE_id++) {
if (dlsch_ue_select[CC_id].ue_num >= dlsch_ue_max_num[CC_id]) {
break;
}
if (UE_list->active[UE_id] == FALSE) {
continue;
}
rnti = UE_RNTI(module_idP,UE_id);
if (rnti == NOT_A_RNTI)
continue;
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
if (ue_sched_ctl->ul_out_of_sync == 1) {
continue;
}
continue_flag = 0;
if (nb_rbs_required[CC_id][UE_id] == 0) {
continue_flag = 1;
} else {
if (cc[CC_id].tdd_Config) harq_pid = ((frameP*10)+subframeP)%10;
else harq_pid = ((frameP*10)+subframeP)&7;
round = ue_sched_ctl->round[CC_id][harq_pid];
if (round == 8) {
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
switch (get_tmode(module_idP, CC_id, UE_id)) {
case 1:
case 2:
case 7:
aggregation = get_aggregation(get_bw_index(module_idP, CC_id),
ue_sched_ctl->dl_cqi[CC_id],
format1);
break;
case 3:
aggregation = get_aggregation(get_bw_index(module_idP,CC_id),
ue_sched_ctl->dl_cqi[CC_id],
format2A);
break;
default:
LOG_W(MAC,"Unsupported transmission mode %d\n", get_tmode(module_idP,CC_id,UE_id));
aggregation = 2;
}
format_flag = 1;
if (!CCE_allocation_infeasible(module_idP,
CC_id,
format_flag,
subframeP,
aggregation,
rnti)) {
dl_config_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu];
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = (format_flag == 0)?2:1;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation;
DL_req->number_pdu++;
// Insert DLSCH(first transmission) UE into selected selected UE list
dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].ue_priority = SCH_DL_FIRST;
dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].nb_rb = nb_rbs_required[CC_id][UE_id];
dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].UE_id = UE_id;
dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].rnti = rnti;
dlsch_ue_select[CC_id].ue_num++;
last_dlsch_ue_id[CC_id] = UE_id;
} else {
continue_flag = 1;
}
}
}
if (continue_flag == 1) {
if (cc[CC_id].tdd_Config != NULL) { //TDD
set_ue_dai (subframeP,
UE_id,
CC_id,
cc[CC_id].tdd_Config->subframeAssignment,
UE_list);
// update UL DAI after DLSCH scheduling
set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP);
}
add_ue_dlsch_info(module_idP,
CC_id,
UE_id,
subframeP,
S_DL_NONE);
}
}
}
}
// Insert DLSCH(first transmission) UE into selected UE list (UE_id <= last_dlsch_ue_id[CC_id])
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
if (mbsfn_flag[CC_id]>0) {
continue;
}
if (dlsch_ue_select[CC_id].ue_num < dlsch_ue_max_num[CC_id] &&
used_dlsch_rbs_num[CC_id] < available_dlsch_rbs_num[CC_id]) {
DL_req = &eNB->DL_req[CC_id].dl_config_request_body;
for (UE_id = 0; UE_id <= old_last_dlsch_ue_id[CC_id]; UE_id++) {
if (dlsch_ue_select[CC_id].ue_num >= dlsch_ue_max_num[CC_id]) {
break;
}
if (UE_list->active[UE_id] == FALSE) {
continue;
}
rnti = UE_RNTI(module_idP,UE_id);
if (rnti == NOT_A_RNTI)
continue;
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
if (ue_sched_ctl->ul_out_of_sync == 1) {
continue;
}
continue_flag = 0;
if (nb_rbs_required[CC_id][UE_id] == 0) {
continue_flag = 1;
} else {
if (cc[CC_id].tdd_Config) harq_pid = ((frameP*10)+subframeP)%10;
else harq_pid = ((frameP*10)+subframeP)&7;
round = ue_sched_ctl->round[CC_id][harq_pid];
if (round == 8) {
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
switch (get_tmode(module_idP, CC_id, UE_id)) {
case 1:
case 2:
case 7:
aggregation = get_aggregation(get_bw_index(module_idP, CC_id),
ue_sched_ctl->dl_cqi[CC_id],
format1);
break;
case 3:
aggregation = get_aggregation(get_bw_index(module_idP,CC_id),
ue_sched_ctl->dl_cqi[CC_id],
format2A);
break;
default:
LOG_W(MAC,"Unsupported transmission mode %d\n", get_tmode(module_idP,CC_id,UE_id));
aggregation = 2;
}
format_flag = 1;
if (!CCE_allocation_infeasible(module_idP,
CC_id,
format_flag,
subframeP,
aggregation,
rnti)) {
dl_config_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu];
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = (format_flag == 0)?2:1;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation;
DL_req->number_pdu++;
// Insert DLSCH(first transmission) UE into selected selected UE list
dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].ue_priority = SCH_DL_FIRST;
dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].nb_rb = nb_rbs_required[CC_id][UE_id];
dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].UE_id = UE_id;
dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].rnti = rnti;
dlsch_ue_select[CC_id].ue_num++;
last_dlsch_ue_id[CC_id] = UE_id;
} else {
continue_flag = 1;
}
}
}
if (continue_flag == 1) {
if (cc[CC_id].tdd_Config != NULL) { //TDD
set_ue_dai (subframeP,
UE_id,
CC_id,
cc[CC_id].tdd_Config->subframeAssignment,
UE_list);
// update UL DAI after DLSCH scheduling
set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP);
}
add_ue_dlsch_info(module_idP,
CC_id,
UE_id,
subframeP,
S_DL_NONE);
}
}
}
}
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
DL_req = &eNB->DL_req[CC_id].dl_config_request_body;
DL_req->number_pdu = saved_dlsch_dci[CC_id];
}
}
#endif
// This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done
......@@ -489,20 +847,32 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id,
frame_t frameP,
sub_frame_t subframeP,
int N_RBG[MAX_NUM_CCs],
int *mbsfn_flag)
int *mbsfn_flag
#ifdef UE_EXPANSION
, DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]
#endif
)
{
#ifndef UE_EXPANSION
unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],harq_pid=0,round=0,total_ue_count;
uint16_t ii;
uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
uint16_t r1=0;
// int rrc_status = RRC_IDLE;
#else
unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],harq_pid=0,Round=0;
#endif
unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX];
int UE_id, i;
uint16_t ii,j;
uint16_t j;
uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
// uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
uint16_t average_rbs_per_user[MAX_NUM_CCs] = {0};
rnti_t rnti;
int min_rb_unit[MAX_NUM_CCs];
uint16_t r1=0;
// uint16_t r1=0;
uint8_t CC_id;
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
......@@ -523,6 +893,11 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id,
UE_sched_ctrl *ue_sched_ctl1,*ue_sched_ctl2;
#endif
#ifdef UE_EXPANSION
uint16_t temp_total_rbs_count;
unsigned char temp_total_ue_count;
#endif
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
if (mbsfn_flag[CC_id]>0) // If this CC is allocated for MBSFN skip it here
......@@ -564,13 +939,89 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id,
assign_rbs_required (Mod_id,frameP,subframeP,nb_rbs_required,min_rb_unit);
#ifdef UE_EXPANSION
dlsch_scheduler_pre_ue_select(Mod_id,frameP,subframeP, mbsfn_flag,nb_rbs_required,dlsch_ue_select);
#else
// Sorts the user on the basis of dlsch logical channel buffer and CQI
sort_UEs (Mod_id,frameP,subframeP);
total_ue_count =0;
#endif
//total_ue_count =0;
#ifdef UE_EXPANSION
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
average_rbs_per_user[CC_id] = 0;
cc = &RC.mac[Mod_id]->common_channels[CC_id];
// Get total available RBS count and total UE count
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
temp_total_rbs_count = RC.mac[Mod_id]->eNB_stats[CC_id].available_prbs;
temp_total_ue_count = dlsch_ue_select[CC_id].ue_num;
for (i = 0; i < dlsch_ue_select[CC_id].ue_num; i++) {
UE_id = dlsch_ue_select[CC_id].list[i].UE_id;
nb_rbs_required[CC_id][UE_id] = dlsch_ue_select[CC_id].list[i].nb_rb;
if( (min_rb_unit[CC_id] * temp_total_ue_count) <= temp_total_rbs_count ) {
//average_rbs_per_user[CC_id] = ((uint16_t)round((double)temp_total_rbs_count/(double)(temp_total_ue_count*min_rb_unit[CC_id])))*min_rb_unit[CC_id];
average_rbs_per_user[CC_id] = (uint16_t)round((double)temp_total_rbs_count/(double)temp_total_ue_count);
} else {
average_rbs_per_user[CC_id] = min_rb_unit[CC_id]; // consider the total number of use that can be scheduled UE
}
rnti = dlsch_ue_select[CC_id].list[i].rnti;
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
if (cc->tdd_Config) harq_pid = ((frameP*10)+subframeP)%10;
else harq_pid = ((frameP*10)+subframeP)&7;
Round = ue_sched_ctl->round[CC_id][harq_pid];
//if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED || round > 0) {
if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED || Round != 8) { // FIXME
nb_rbs_required_remaining[CC_id][UE_id] = dlsch_ue_select[CC_id].list[i].nb_rb;
} else {
nb_rbs_required_remaining[CC_id][UE_id] = cmin(average_rbs_per_user[CC_id], dlsch_ue_select[CC_id].list[i].nb_rb);
}
transmission_mode = get_tmode(Mod_id,CC_id,UE_id);
LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n ");
dlsch_scheduler_pre_processor_allocate (Mod_id,
UE_id,
CC_id,
N_RBG[CC_id],
transmission_mode,
min_rb_unit[CC_id],
N_RB_DL,
nb_rbs_required,
nb_rbs_required_remaining,
rballoc_sub,
MIMO_mode_indicator);
if (ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) {
last_dlsch_ue_id[CC_id] = dlsch_ue_select[CC_id].list[i-1].UE_id;
dlsch_ue_select[CC_id].ue_num = i;
break;
}
temp_total_rbs_count -= ue_sched_ctl->pre_nb_available_rbs[CC_id];
temp_total_ue_count--;
if (temp_total_rbs_count == 0) {
last_dlsch_ue_id[CC_id] = UE_id;
dlsch_ue_select[CC_id].ue_num = i+1;
break;
}
#ifdef TM5
// TODO: data channel TM5: to be re-visited
#endif
}
}
#else
// loop over all active UEs
for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
......@@ -802,6 +1253,7 @@ if (nb_rbs_required_remaining[CC_id][i]<0) abort();
}
} // total_ue_count
} // end of for for r1 and r2
#endif // end of #ifndef UE_EXPANSION
#ifdef TM5
......@@ -838,13 +1290,19 @@ if (nb_rbs_required_remaining[CC_id][i]<0) abort();
}
#endif
#ifdef UE_EXPANSION
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
for (i = 0; i < dlsch_ue_select[CC_id].ue_num; i++) {
UE_id = dlsch_ue_select[CC_id].list[i].UE_id;
ue_sched_ctl = &RC.mac[Mod_id]->UE_list.UE_sched_ctrl[UE_id];
#else
for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
UE_id = i;
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
CC_id = UE_list->ordered_CCids[ii][UE_id];
#endif
//PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id];
if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0 ) {
......@@ -1082,7 +1540,7 @@ void dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id,
/// ULSCH PRE_PROCESSOR
#ifndef UE_EXPANSION
void ulsch_scheduler_pre_processor(module_id_t module_idP,
int frameP,
sub_frame_t subframeP,
......@@ -1259,7 +1717,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP,
}
}
}
#endif
void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subframeP, uint16_t *first_rb)
{
......@@ -1532,3 +1990,416 @@ void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP)
}
#endif
}
#ifdef UE_EXPANSION
int ulsch_cc_id_end(uint8_t *cc_id_flag )
{
int end_flag = 1;
for (int CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
if (cc_id_flag[CC_id]==0) {
end_flag = 0;
break;
}
}
return end_flag;
}
void ulsch_scheduler_pre_ue_select(
module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP,
ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs])
{
eNB_MAC_INST *eNB=RC.mac[module_idP];
COMMON_channels_t *cc;
int CC_id,UE_id;
int ret;
uint8_t ue_first_num[MAX_NUM_CCs];
uint8_t first_ue_total[MAX_NUM_CCs][20];
uint8_t first_ue_id[MAX_NUM_CCs][20];
uint8_t ul_inactivity_num[MAX_NUM_CCs];
uint8_t ul_inactivity_id[MAX_NUM_CCs][20];
// LTE_DL_FRAME_PARMS *frame_parms;
uint8_t ulsch_ue_max_num[MAX_NUM_CCs];
uint16_t saved_ulsch_dci[MAX_NUM_CCs];
rnti_t rnti;
UE_sched_ctrl *UE_sched_ctl = NULL;
uint8_t cc_id_flag[MAX_NUM_CCs];
uint8_t harq_pid = 0,round = 0;
UE_list_t *UE_list= &eNB->UE_list;
uint8_t aggregation = 4;
int format_flag;
nfapi_hi_dci0_request_body_t *HI_DCI0_req;
nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu;
for ( CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++ ) {
//save ulsch dci number
saved_ulsch_dci[CC_id] = eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci;
// maximum multiplicity number
ulsch_ue_max_num[CC_id] =RC.rrc[module_idP]->configuration.ue_multiple_max[CC_id];
cc_id_flag[CC_id] = 0;
ue_first_num[CC_id] = 0;
ul_inactivity_num[CC_id] = 0;
}
// UE round >0
for ( UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++ ) {
rnti = UE_RNTI(module_idP,UE_id);
CC_id = UE_PCCID(module_idP,UE_id);
if (rnti ==NOT_A_RNTI)
continue;
if (UE_list->UE_template[CC_id][UE_id].configured == FALSE)
continue;
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1)
continue;
// UL DCI
HI_DCI0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body;
if ( (ulsch_ue_select[CC_id].ue_num >= ulsch_ue_max_num[CC_id]) || (cc_id_flag[CC_id] == 1) ) {
cc_id_flag[CC_id] = 1;
HI_DCI0_req->number_of_dci = saved_ulsch_dci[CC_id];
ret = ulsch_cc_id_end(cc_id_flag);
if ( ret == 0 ) {
continue;
}
if ( ret == 1 ) {
return;
}
}
cc = &eNB->common_channels[CC_id];
//harq_pid
harq_pid = subframe2harqpid(cc,frameP,subframeP);
//round
round = UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid];
if ( round > 0 ) {
hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi];
format_flag = 2;
if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) {
cc_id_flag[CC_id] = 1;
continue;
} else {
hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation;
HI_DCI0_req->number_of_dci++;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_RETRANS;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = eNB->UE_list.UE_template[CC_id][UE_id].first_rb_ul[harq_pid];
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].nb_rb = eNB->UE_list.UE_template[CC_id][UE_id].nb_rb_ul[harq_pid];
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = UE_id;
ulsch_ue_select[CC_id].ue_num++;
continue;
}
}
//
if ( UE_id > last_ulsch_ue_id[CC_id] && ((ulsch_ue_select[CC_id].ue_num+ue_first_num[CC_id]) < ulsch_ue_max_num[CC_id]) ) {
if ( UE_list->UE_template[CC_id][UE_id].ul_total_buffer > 0 ) {
first_ue_id[CC_id][ue_first_num[CC_id]]= UE_id;
first_ue_total[CC_id][ue_first_num[CC_id]] = UE_list->UE_template[CC_id][UE_id].ul_total_buffer;
ue_first_num[CC_id]++;
continue;
}
if ( UE_list->UE_template[CC_id][UE_id].ul_SR > 0 ) {
first_ue_id[CC_id][ue_first_num[CC_id]]= UE_id;
first_ue_total[CC_id] [ue_first_num[CC_id]] = 0;
ue_first_num[CC_id]++;
continue;
}
if ( (ulsch_ue_select[CC_id].ue_num+ul_inactivity_num[CC_id] ) < ulsch_ue_max_num[CC_id] ) {
UE_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
if ( ((UE_sched_ctl->ul_inactivity_timer>20)&&(UE_sched_ctl->ul_scheduled==0)) ||
((UE_sched_ctl->ul_inactivity_timer>10)&&(UE_sched_ctl->ul_scheduled==0)&&(mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED))) {
ul_inactivity_id[CC_id][ul_inactivity_num[CC_id]]= UE_id;
ul_inactivity_num[CC_id] ++;
continue;
}
}
}
}
for ( CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++ ) {
HI_DCI0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body;
for ( int temp = 0; temp < ue_first_num[CC_id]; temp++ ) {
if ( (ulsch_ue_select[CC_id].ue_num >= ulsch_ue_max_num[CC_id]) || (cc_id_flag[CC_id] == 1) ) {
cc_id_flag[CC_id] = 1;
HI_DCI0_req->number_of_dci = saved_ulsch_dci[CC_id];
break;
}
hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi];
format_flag = 2;
rnti = UE_RNTI(module_idP,UE_id);
if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) {
cc_id_flag[CC_id] = 1;
break;
} else {
hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation;
HI_DCI0_req->number_of_dci++;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_FIRST;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ul_total_buffer = first_ue_total[CC_id][temp];
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = first_ue_id[CC_id][temp];
ulsch_ue_select[CC_id].ue_num++;
}
}
}
for ( UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++ ) {
rnti = UE_RNTI(module_idP,UE_id);
CC_id = UE_PCCID(module_idP,UE_id);
if (rnti ==NOT_A_RNTI)
continue;
if (UE_list->UE_template[CC_id][UE_id].configured == FALSE)
continue;
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1)
continue;
if ( (ulsch_ue_select[CC_id].ue_num >= ulsch_ue_max_num[CC_id]) || (cc_id_flag[CC_id] == 1) ) {
cc_id_flag[CC_id] = 1;
HI_DCI0_req->number_of_dci = saved_ulsch_dci[CC_id];
ret = ulsch_cc_id_end(cc_id_flag);
if ( ret == 0 ) {
continue;
}
if ( ret == 1 ) {
return;
}
}
if (UE_id > last_ulsch_ue_id[CC_id])
continue;
HI_DCI0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body;
//SR BSR
if ( (UE_list->UE_template[CC_id][UE_id].ul_total_buffer > 0) || (UE_list->UE_template[CC_id][UE_id].ul_SR > 0) ) {
hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi];
format_flag = 2;
if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) {
cc_id_flag[CC_id] = 1;
continue;
} else {
hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation;
HI_DCI0_req->number_of_dci++;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_FIRST;
if(UE_list->UE_template[CC_id][UE_id].ul_total_buffer > 0)
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ul_total_buffer = UE_list->UE_template[CC_id][UE_id].ul_total_buffer;
else if(UE_list->UE_template[CC_id][UE_id].ul_SR > 0)
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ul_total_buffer = 0;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = UE_id;
ulsch_ue_select[CC_id].ue_num++;
continue;
}
}
//inactivity UE
if ( (ulsch_ue_select[CC_id].ue_num+ul_inactivity_num[CC_id]) < ulsch_ue_max_num[CC_id] ) {
UE_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
if ( ((UE_sched_ctl->ul_inactivity_timer>20)&&(UE_sched_ctl->ul_scheduled==0)) ||
((UE_sched_ctl->ul_inactivity_timer>10)&&(UE_sched_ctl->ul_scheduled==0)&&(mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED))) {
ul_inactivity_id[CC_id][ul_inactivity_num[CC_id]]= UE_id;
ul_inactivity_num[CC_id]++;
continue;
}
}
}
for ( CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++ ) {
HI_DCI0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body;
for ( int temp = 0; temp < ue_first_num[CC_id]; temp++ ) {
if ( (ulsch_ue_select[CC_id].ue_num >= ulsch_ue_max_num[CC_id]) || (cc_id_flag[CC_id] == 1) ) {
HI_DCI0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body;
cc_id_flag[CC_id] = 1;
break;
}
hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi];
format_flag = 2;
rnti = UE_RNTI(module_idP,UE_id);
if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) {
cc_id_flag[CC_id] = 1;
return;
} else {
hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation;
HI_DCI0_req->number_of_dci++;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_INACTIVE;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ul_total_buffer = 0;
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = ul_inactivity_id[CC_id][temp];
ulsch_ue_select[CC_id].ue_num++;
}
}
HI_DCI0_req->number_of_dci = saved_ulsch_dci[CC_id];
}
return;
}
uint8_t find_rb_table_index(uint8_t average_rbs)
{
int i;
for ( i = 0; i < 34; i++ ) {
if ( rb_table[i] > average_rbs ) {
return (i-1);
}
}
return i;
}
void ulsch_scheduler_pre_processor(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP,
ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs])
{
int CC_id,ulsch_ue_num;
eNB_MAC_INST *eNB = RC.mac[module_idP];
UE_list_t *UE_list= &eNB->UE_list;
UE_TEMPLATE *UE_template = NULL;
LTE_DL_FRAME_PARMS *frame_parms = NULL;
uint8_t ue_num_temp;
uint8_t total_rbs=0;
uint8_t average_rbs;
uint16_t first_rb[MAX_NUM_CCs];
uint8_t mcs;
uint8_t rb_table_index;
uint32_t tbs;
int16_t tx_power;
int UE_id;
rnti_t rnti;
LOG_D(MAC,"In ulsch_preprocessor: ulsch ue select\n");
//ue select
ulsch_scheduler_pre_ue_select(module_idP,frameP,subframeP,ulsch_ue_select);
// MCS and RB assgin
for ( CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++ ) {
frame_parms = &(RC.eNB[module_idP][CC_id]->frame_parms);
first_rb[CC_id] = 1;
ue_num_temp = ulsch_ue_select[CC_id].ue_num;
for ( ulsch_ue_num = 0; ulsch_ue_num < ulsch_ue_select[CC_id].ue_num; ulsch_ue_num++ ) {
UE_id = ulsch_ue_select[CC_id].list[ulsch_ue_num].UE_id;
rnti = UE_RNTI(CC_id,UE_id);
if (ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_MSG3) {
first_rb[CC_id] ++;
ue_num_temp--;
continue;
}
if (ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_PRACH) {
first_rb[CC_id] = ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb+ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb;
ue_num_temp--;
continue;
}
if ( first_rb[CC_id] >= frame_parms->N_RB_UL-1 ) {
LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n",
module_idP,frameP,subframeP,UE_id,rnti,CC_id);
break;
}
// calculate the average rb ( remain UE)
total_rbs = frame_parms->N_RB_UL-1-first_rb[CC_id];
average_rbs = (int)round((double)total_rbs/(double)ue_num_temp);
if ( average_rbs < 3 ) {
ue_num_temp--;
ulsch_ue_num--;
ulsch_ue_select[CC_id].ue_num--;
continue;
}
if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_RETRANS ) {
if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb <= average_rbs ) {
// assigne RBS(nb_rb)
ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb = first_rb[CC_id];
first_rb[CC_id] = first_rb[CC_id] + ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb;
}
if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb > average_rbs ) {
if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb <= total_rbs ) {
// assigne RBS(average_rbs)
ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb = first_rb[CC_id];
first_rb[CC_id] = first_rb[CC_id] + ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb;
} else {
// assigne RBS(remain rbs)
ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb = first_rb[CC_id];
first_rb[CC_id] = first_rb[CC_id] + total_rbs;
ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb = first_rb[CC_id]-ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb;
}
}
}else{
UE_template = &UE_list->UE_template[CC_id][ulsch_ue_select[CC_id].list[ulsch_ue_num].UE_id];
if ( UE_list->UE_sched_ctrl[ulsch_ue_select[CC_id].list[ulsch_ue_num].UE_id].phr_received == 1 ) {
mcs = 20;
} else {
mcs = 10;
}
if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_FIRST ) {
if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ul_total_buffer > 0 ) {
rb_table_index = 2;
tbs = get_TBS_UL(mcs,rb_table[rb_table_index])<<3;
tx_power= estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,frame_parms->Ncp,0);
while ( (((UE_template->phr_info - tx_power) < 0 ) || (tbs > UE_template->ul_total_buffer)) && (mcs > 3) ) {
mcs--;
tbs = get_TBS_UL(mcs,rb_table[rb_table_index])<<3;
tx_power= estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,frame_parms->Ncp,0);
}
while ( (tbs < UE_template->ul_total_buffer) && (rb_table[rb_table_index]<(frame_parms->N_RB_UL-first_rb[CC_id])) &&
((UE_template->phr_info - tx_power) > 0) && (rb_table_index < 32 )) {
rb_table_index++;
tbs = get_TBS_UL(mcs,rb_table[rb_table_index])<<3;
tx_power= estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,frame_parms->Ncp,0);
}
if ( rb_table[rb_table_index]<3 ) {
rb_table_index=2;
}
if ( rb_table[rb_table_index] <= average_rbs ) {
// assigne RBS( nb_rb)
first_rb[CC_id] = first_rb[CC_id] + rb_table[rb_table_index];
UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = rb_table[rb_table_index];
UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index;
UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs;
}
if ( rb_table[rb_table_index] > average_rbs ) {
// assigne RBS(average_rbs)
rb_table_index = find_rb_table_index(average_rbs);
if (rb_table_index>=34){
LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: average RBs %d > 100\n",
module_idP,frameP,subframeP,UE_id,rnti,CC_id,average_rbs);
break;
}
first_rb[CC_id] = first_rb[CC_id] + rb_table[rb_table_index];
UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = rb_table[rb_table_index];
UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index;
UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs;
}
}else {
// assigne RBS( 3 RBs)
first_rb[CC_id] = first_rb[CC_id] + 3;
UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = 3;
UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2;
UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs;
}
}else if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_INACTIVE ) {
// assigne RBS( 3 RBs)
first_rb[CC_id] = first_rb[CC_id] + 3;
UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = 3;
UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2;
UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs;
}
}
ue_num_temp--;
}
}
}
#endif
......@@ -100,7 +100,11 @@ void schedule_ulsch(module_id_t module_idP,frame_t frameP,sub_frame_t subframe);
@param subframe Subframe number on which to act
@param sched_subframe Subframe number where PUSCH is transmitted (for DAI lookup)
*/
#ifndef UE_EXPANSION
void schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, sub_frame_t subframe, unsigned char sched_subframe, uint16_t *first_rb);
#else
void schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, sub_frame_t subframe, unsigned char sched_subframe, ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]);
#endif
/** \brief Second stage of DLSCH scheduling, after schedule_SI, schedule_RA and schedule_dlsch have been called. This routine first allocates random frequency assignments for SI and RA SDUs using distributed VRB allocations and adds the corresponding DCI SDU to the DCI buffer for PHY. It then loops over the UE specific DCIs previously allocated and fills in the remaining DCI fields related to frequency allocation. It assumes localized allocation of type 0 (DCI.rah=0). The allocation is done for tranmission modes 1,2,4.
@param Mod_id Instance of eNB
......@@ -108,7 +112,11 @@ void schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, sub_frame_t sub
@param subframe Index of subframe
@param mbsfn_flag Indicates that this subframe is for MCH/MCCH
*/
#ifndef UE_EXPANSION
void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag);
#else
void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag, DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]);
#endif
/** \brief UE specific DLSCH scheduling. Retrieves next ue to be schduled from round-robin scheduler and gets the appropriate harq_pid for the subframe from PHY. If the process is active and requires a retransmission, it schedules the retransmission with the same PRB count and MCS as the first transmission. Otherwise it consults RLC for DCCH/DTCH SDUs (status with maximum number of available PRBS), builds the MAC header (timing advance sent by default) and copies
@param Mod_id Instance ID of eNB
......@@ -188,7 +196,11 @@ void dlsch_scheduler_pre_processor (module_id_t module_idP,
frame_t frameP,
sub_frame_t subframe,
int N_RBG[MAX_NUM_CCs],
int *mbsfn_flag);
int *mbsfn_flag
#ifdef UE_EXPANSION
, DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]
#endif
);
void dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id,
......@@ -579,9 +591,22 @@ void dump_ue_list(UE_list_t *listP, int ul_flag);
int UE_num_active_CC(UE_list_t *listP,int ue_idP);
int UE_PCCID(module_id_t mod_idP,int ue_idP);
rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP);
uint8_t find_rb_table_index(uint8_t average_rbs);
#ifndef UE_EXPANSION
void ulsch_scheduler_pre_processor(module_id_t module_idP, int frameP, sub_frame_t subframeP, uint16_t *first_rb);
#else
void ulsch_scheduler_pre_processor(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]);
void ulsch_scheduler_pre_ue_select(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP,ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]);
#endif
void
set_ul_DAI(
int module_idP,
int UE_idP,
int CC_idP,
int frameP,
int subframeP
);
void store_ulsch_buffer(module_id_t module_idP, int frameP, sub_frame_t subframeP);
void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP);
void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subframeP,uint16_t *first_rb);
......
......@@ -136,6 +136,10 @@ DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu2;
DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu1E;
#ifdef UE_EXPANSION
int last_dlsch_ue_id[MAX_NUM_CCs] = {-1};
int last_ulsch_ue_id[MAX_NUM_CCs] = {-1};
#endif
#endif
......@@ -1555,7 +1555,11 @@ do_RRCConnectionSetup(
// SchedulingRequestConfig
physicalConfigDedicated2->schedulingRequestConfig->present = SchedulingRequestConfig_PR_setup;
#ifdef UE_EXPANSION
physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex = 31 - ue_context_pP->local_uid/10;//ue_context_pP->local_uid;
#else
physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex = 71 - ue_context_pP->local_uid/10;//ue_context_pP->local_uid;
#endif
if (carrier->sib1->tdd_Config == NULL) { // FDD
physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 5+(ue_context_pP->local_uid%10); // Isr = 5 (every 10 subframes, offset=2+UE_id mod3)
......
Active_eNBs = ( "eNB_Eurecom_LTEBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
eNBs =
(
{
////////// Identification parameters:
eNB_ID = 0xe00;
cell_type = "CELL_MACRO_ENB";
eNB_name = "eNB_Eurecom_LTEBox";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = "1";
mobile_country_code = "208";
mobile_network_code = "93";
tr_s_preference = "local_mac"
////////// Physical parameters:
component_carriers = (
{
node_function = "3GPP_eNODEB";
node_timing = "synch_to_ext_device";
node_synch_ref = 0;
frame_type = "FDD";
tdd_config = 3;
tdd_config_s = 0;
prefix_type = "NORMAL";
eutra_band = 7;
downlink_frequency = 2685000000L;
uplink_frequency_offset = -120000000;
Nid_cell = 0;
N_RB_DL = 50;
Nid_cell_mbsfn = 0;
nb_antenna_ports = 1;
nb_antennas_tx = 1;
nb_antennas_rx = 1;
tx_gain = 90;
rx_gain = 125;
pbch_repetition = "FALSE";
prach_root = 0;
prach_config_index = 0;
prach_high_speed = "DISABLE";
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -27;
pdsch_p_b = 0;
pusch_n_SB = 1;
pusch_enable64QAM = "DISABLE";
pusch_hoppingMode = "interSubFrame";
pusch_hoppingOffset = 0;
pusch_groupHoppingEnabled = "ENABLE";
pusch_groupAssignment = 0;
pusch_sequenceHoppingEnabled = "DISABLE";
pusch_nDMRS1 = 1;
phich_duration = "NORMAL";
phich_resource = "ONE";
srs_enable = "DISABLE";
/* srs_BandwidthConfig =;
srs_SubframeConfig =;
srs_ackNackST =;
srs_MaxUpPts =;*/
pusch_p0_Nominal = -96;
pusch_alpha = "AL1";
pucch_p0_Nominal = -104;
msg3_delta_Preamble = 6;
pucch_deltaF_Format1 = "deltaF2";
pucch_deltaF_Format1b = "deltaF3";
pucch_deltaF_Format2 = "deltaF0";
pucch_deltaF_Format2a = "deltaF0";
pucch_deltaF_Format2b = "deltaF0";
rach_numberOfRA_Preambles = 64;
rach_preamblesGroupAConfig = "DISABLE";
/*
rach_sizeOfRA_PreamblesGroupA = ;
rach_messageSizeGroupA = ;
rach_messagePowerOffsetGroupB = ;
*/
rach_powerRampingStep = 4;
rach_preambleInitialReceivedTargetPower = -108;
rach_preambleTransMax = 10;
rach_raResponseWindowSize = 10;
rach_macContentionResolutionTimer = 48;
rach_maxHARQ_Msg3Tx = 4;
pcch_default_PagingCycle = 128;
pcch_nB = "oneT";
bcch_modificationPeriodCoeff = 2;
ue_TimersAndConstants_t300 = 1000;
ue_TimersAndConstants_t301 = 1000;
ue_TimersAndConstants_t310 = 1000;
ue_TimersAndConstants_t311 = 10000;
ue_TimersAndConstants_n310 = 20;
ue_TimersAndConstants_n311 = 1;
ue_TransmissionMode = 1;
ue_multiple_max = 20;
}
);
srb1_parameters :
{
# timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
timer_poll_retransmit = 80;
# timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
timer_reordering = 35;
# timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
timer_status_prohibit = 0;
# poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
poll_pdu = 4;
# poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
poll_byte = 99999;
# max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
max_retx_threshold = 4;
}
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// MME parameters:
mme_ip_address = ( { ipv4 = "192.168.12.26";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.19/24";
ENB_INTERFACE_NAME_FOR_S1U = "eth0";
ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.19/24";
ENB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
}
);
RUs = (
{
local_rf = "yes"
nb_tx = 1
nb_rx = 1
att_tx = 0
att_rx = 0;
bands = [7];
max_pdschReferenceSignalPower = -27;
max_rxgain = 125;
eNB_instances = [0];
}
);
log_config :
{
global_log_level ="info";
global_log_verbosity ="medium";
hw_log_level ="info";
hw_log_verbosity ="medium";
phy_log_level ="info";
phy_log_verbosity ="medium";
mac_log_level ="info";
mac_log_verbosity ="high";
rlc_log_level ="info";
rlc_log_verbosity ="medium";
pdcp_log_level ="info";
pdcp_log_verbosity ="medium";
rrc_log_level ="info";
rrc_log_verbosity ="medium";
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment