Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
常顺宇
OpenXG-RAN
Commits
99301f43
Commit
99301f43
authored
Jan 16, 2020
by
Robert Schmidt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Call schedule_ue_spec() once for each CC
parent
81fb7628
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
953 additions
and
964 deletions
+953
-964
openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
+948
-962
openair2/LAYER2/MAC/mac_proto.h
openair2/LAYER2/MAC/mac_proto.h
+5
-2
No files found.
openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
View file @
99301f43
...
...
@@ -420,17 +420,8 @@ set_ul_DAI(int module_idP,
//------------------------------------------------------------------------------
void
schedule_dlsch
(
module_id_t
module_idP
,
frame_t
frameP
,
sub_frame_t
subframeP
,
int
*
mbsfn_flag
)
{
int
i
=
0
;
slice_info_t
*
sli
=
&
RC
.
mac
[
module_idP
]
->
slice_info
;
memset
(
sli
->
rballoc_sub
,
0
,
sizeof
(
sli
->
rballoc_sub
));
for
(
i
=
0
;
i
<
sli
->
n_dl
;
i
++
)
{
// Run each enabled slice-specific schedulers one by one
sli
->
dl
[
i
].
sched_cb
(
module_idP
,
i
,
frameP
,
subframeP
,
mbsfn_flag
/*, dl_info*/
);
for
(
int
CC_id
=
0
;
CC_id
<
RC
.
nb_mac_CC
[
module_idP
];
CC_id
++
)
{
schedule_ue_spec
(
module_idP
,
CC_id
,
frameP
,
subframeP
,
mbsfn_flag
);
}
}
...
...
@@ -454,13 +445,12 @@ void getRepetition(UE_TEMPLATE *pue_template,unsigned int *maxRep, unsigned int
*/
void
schedule_ue_spec
(
module_id_t
module_idP
,
int
slice_idxP
,
int
CC_id
,
frame_t
frameP
,
sub_frame_t
subframeP
,
int
*
mbsfn_flag
)
//------------------------------------------------------------------------------
{
int
CC_id
;
int
UE_id
;
int
aggregation
;
mac_rlc_status_resp_t
rlc_status
;
...
...
@@ -478,7 +468,6 @@ schedule_ue_spec(module_id_t module_idP,
uint8_t
ra_ii
;
eNB_UE_STATS
*
eNB_UE_stats
=
NULL
;
UE_TEMPLATE
*
ue_template
=
NULL
;
eNB_STATS
*
eNB_stats
=
NULL
;
RRC_release_ctrl_t
*
release_ctrl
=
NULL
;
DLSCH_PDU
*
dlsch_pdu
=
NULL
;
RA_t
*
ra
=
NULL
;
...
...
@@ -491,11 +480,11 @@ schedule_ue_spec(module_id_t module_idP,
int
tpc
=
1
;
UE_sched_ctrl_t
*
ue_sched_ctrl
;
int
mcs
;
int
i
;
int
min_rb_unit
[
NFAPI_CC_MAX
]
;
int
N_RB_DL
[
NFAPI_CC_MAX
]
;
int
total_nb_available_rb
[
NFAPI_CC_MAX
]
;
int
N_RBG
[
NFAPI_CC_MAX
]
;
const
int
min_rb_unit
=
get_min_rb_unit
(
module_idP
,
CC_id
)
;
const
int
dl_Bandwidth
=
cc
[
CC_id
].
mib
->
message
.
dl_Bandwidth
;
const
int
N_RB_DL
=
to_prb
(
dl_Bandwidth
)
;
const
int
N_RBG
=
to_rbg
(
dl_Bandwidth
)
;
int
total_nb_available_rb
=
N_RB_DL
;
nfapi_dl_config_request_body_t
*
dl_req
;
nfapi_dl_config_request_pdu_t
*
dl_config_pdu
;
int
tdd_sfa
;
...
...
@@ -503,22 +492,19 @@ schedule_ue_spec(module_id_t module_idP,
int
header_length_last
;
int
header_length_total
;
rrc_eNB_ue_context_t
*
ue_contextP
=
NULL
;
int
nb_mac_CC
=
RC
.
nb_mac_CC
[
module_idP
];
long
dl_Bandwidth
;
if
(
is_pmch_subframe
(
frameP
,
subframeP
,
&
RC
.
eNB
[
module_idP
][
0
]
->
frame_parms
)){
//LOG_E(MAC,"Frame[%d] SF:%d This SF should not be allocated\n",frameP,subframeP);
return
;
}
start_meas
(
&
eNB
->
schedule_dlsch
);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH
,
VCD_FUNCTION_IN
);
// for TDD: check that we have to act here, otherwise return
if
(
cc
[
0
].
tdd_Config
)
{
tdd_sfa
=
cc
[
0
].
tdd_Config
->
subframeAssignment
;
if
(
cc
[
CC_id
].
tdd_Config
)
{
tdd_sfa
=
cc
[
CC_id
].
tdd_Config
->
subframeAssignment
;
switch
(
subframeP
)
{
case
0
:
...
...
@@ -567,33 +553,25 @@ schedule_ue_spec(module_id_t module_idP,
aggregation
=
2
;
for
(
CC_id
=
0
,
eNB_stats
=
&
eNB
->
eNB_stats
[
0
];
CC_id
<
nb_mac_CC
;
CC_id
++
,
eNB_stats
++
)
{
dl_Bandwidth
=
cc
[
CC_id
].
mib
->
message
.
dl_Bandwidth
;
N_RB_DL
[
CC_id
]
=
to_prb
(
dl_Bandwidth
);
min_rb_unit
[
CC_id
]
=
get_min_rb_unit
(
module_idP
,
CC_id
);
// get number of PRBs less those used by common channels
total_nb_available_rb
[
CC_id
]
=
N_RB_DL
[
CC_id
];
for
(
i
=
0
;
i
<
N_RB_DL
[
CC_id
];
i
++
)
if
(
cc
[
CC_id
].
vrb_map
[
i
]
!=
0
)
total_nb_available_rb
[
CC_id
]
--
;
N_RBG
[
CC_id
]
=
to_rbg
(
dl_Bandwidth
);
// store the global enb stats:
eNB_stats
->
num_dlactive_UEs
=
UE_list
->
num_UEs
;
eNB_stats
->
available_prbs
=
total_nb_available_rb
[
CC_id
];
eNB_stats
->
total_available_prbs
+=
total_nb_available_rb
[
CC_id
];
eNB_stats
->
dlsch_bytes_tx
=
0
;
eNB_stats
->
dlsch_pdus_tx
=
0
;
}
for
(
int
i
=
0
;
i
<
N_RB_DL
;
i
++
)
if
(
cc
[
CC_id
].
vrb_map
[
i
]
!=
0
)
total_nb_available_rb
--
;
// store the global enb stats:
eNB
->
eNB_stats
[
CC_id
].
num_dlactive_UEs
=
UE_list
->
num_UEs
;
eNB
->
eNB_stats
[
CC_id
].
available_prbs
=
total_nb_available_rb
;
eNB
->
eNB_stats
[
CC_id
].
total_available_prbs
+=
total_nb_available_rb
;
eNB
->
eNB_stats
[
CC_id
].
dlsch_bytes_tx
=
0
;
eNB
->
eNB_stats
[
CC_id
].
dlsch_pdus_tx
=
0
;
// CALLING Pre_Processor for downlink scheduling
// (Returns estimation of RBs required by each UE and the allocation on sub-band)
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR
,
VCD_FUNCTION_IN
);
start_meas
(
&
eNB
->
schedule_dlsch_preprocessor
);
memset
(
eNB
->
slice_info
.
rballoc_sub
,
0
,
sizeof
(
eNB
->
slice_info
.
rballoc_sub
));
dlsch_scheduler_pre_processor
(
module_idP
,
slice_idxP
,
0
,
//
slice_idxP,
frameP
,
subframeP
,
mbsfn_flag
,
...
...
@@ -610,372 +588,587 @@ schedule_ue_spec(module_id_t module_idP,
/* the interslice multiplexing re-sorts the UE_list for the slices it tries
* to multiplex, so we need to sort it for the current slice again */
sort_UEs
(
module_idP
,
slice_idxP
,
0
,
//
slice_idxP,
frameP
,
subframeP
);
}
for
(
CC_id
=
0
;
CC_id
<
nb_mac_CC
;
CC_id
++
)
{
LOG_D
(
MAC
,
"doing schedule_ue_spec for CC_id %d
\n
"
,
CC_id
);
dl_req
=
&
eNB
->
DL_req
[
CC_id
].
dl_config_request_body
;
LOG_D
(
MAC
,
"doing schedule_ue_spec for CC_id %d
\n
"
,
CC_id
);
dl_req
=
&
eNB
->
DL_req
[
CC_id
].
dl_config_request_body
;
if
(
mbsfn_flag
[
CC_id
]
>
0
)
continue
;
//
if (mbsfn_flag[CC_id] > 0)
// return
;
for
(
UE_id
=
UE_list
->
head
;
UE_id
>=
0
;
UE_id
=
UE_list
->
next
[
UE_id
])
{
LOG_D
(
MAC
,
"doing schedule_ue_spec for CC_id %d UE %d
\n
"
,
CC_id
,
UE_id
);
continue_flag
=
0
;
// reset the flag to allow allocation for the remaining UEs
rnti
=
UE_RNTI
(
module_idP
,
UE_id
);
ue_sched_ctrl
=
&
UE_list
->
UE_sched_ctrl
[
UE_id
];
ue_template
=
&
UE_list
->
UE_template
[
CC_id
][
UE_id
];
if
(
ue_template
->
rach_resource_type
>
0
)
{
continue_flag
=
1
;
}
for
(
UE_id
=
UE_list
->
head
;
UE_id
>=
0
;
UE_id
=
UE_list
->
next
[
UE_id
])
{
LOG_D
(
MAC
,
"doing schedule_ue_spec for CC_id %d UE %d
\n
"
,
CC_id
,
UE_id
);
continue_flag
=
0
;
// reset the flag to allow allocation for the remaining UEs
rnti
=
UE_RNTI
(
module_idP
,
UE_id
);
ue_sched_ctrl
=
&
UE_list
->
UE_sched_ctrl
[
UE_id
];
ue_template
=
&
UE_list
->
UE_template
[
CC_id
][
UE_id
];
if
(
&
(
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
])
==
NULL
)
{
LOG_D
(
MAC
,
"[eNB] Cannot find eNB_UE_stats
\n
"
);
continue_flag
=
1
;
}
else
{
eNB_UE_stats
=
&
(
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
]);
}
if
(
ue_template
->
rach_resource_type
>
0
)
{
continue_flag
=
1
;
}
if
(
continue_flag
!=
1
)
{
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_ctrl
->
dl_cqi
[
CC_id
],
format1
);
break
;
if
(
&
(
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
])
==
NULL
)
{
LOG_D
(
MAC
,
"[eNB] Cannot find eNB_UE_stats
\n
"
);
continue_flag
=
1
;
}
else
{
eNB_UE_stats
=
&
(
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
]);
}
case
3
:
aggregation
=
get_aggregation
(
get_bw_index
(
module_idP
,
CC_id
),
ue_sched_ctrl
->
dl_cqi
[
CC_id
],
format2A
);
break
;
if
(
continue_flag
!=
1
)
{
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_ctrl
->
dl_cqi
[
CC_id
],
format1
);
break
;
default
:
AssertFatal
(
1
==
0
,
"Unsupported transmission mode %d
\n
"
,
get_tmode
(
module_idP
,
CC_id
,
UE_id
));
aggregation
=
2
;
break
;
}
}
case
3
:
aggregation
=
get_aggregation
(
get_bw_index
(
module_idP
,
CC_id
),
ue_sched_ctrl
->
dl_cqi
[
CC_id
],
format2A
);
break
;
/* if (continue_flag != 1 */
if
(
ue_sched_ctrl
->
pre_nb_available_rbs
[
CC_id
]
==
0
||
// no RBs allocated
CCE_allocation_infeasible
(
module_idP
,
CC_id
,
1
,
subframeP
,
aggregation
,
rnti
))
{
LOG_D
(
MAC
,
"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue
\n
"
,
module_idP
,
frameP
,
UE_id
,
CC_id
);
continue_flag
=
1
;
//to next user (there might be rbs availiable for other UEs in TM5
default:
AssertFatal
(
1
==
0
,
"Unsupported transmission mode %d
\n
"
,
get_tmode
(
module_idP
,
CC_id
,
UE_id
));
aggregation
=
2
;
break
;
}
}
// If TDD
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
);
}
/* if (continue_flag != 1 */
if
(
ue_sched_ctrl
->
pre_nb_available_rbs
[
CC_id
]
==
0
||
// no RBs allocated
CCE_allocation_infeasible
(
module_idP
,
CC_id
,
1
,
subframeP
,
aggregation
,
rnti
))
{
LOG_D
(
MAC
,
"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue
\n
"
,
module_idP
,
frameP
,
UE_id
,
CC_id
);
continue_flag
=
1
;
//to next user (there might be rbs availiable for other UEs in TM5
}
if
(
continue_flag
==
1
)
{
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
S_DL_NONE
,
rnti
);
continue
;
}
// If TDD
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
);
}
nb_available_rb
=
ue_sched_ctrl
->
pre_nb_available_rbs
[
CC_id
];
harq_pid
=
frame_subframe2_dl_harq_pid
(
cc
->
tdd_Config
,
frameP
,
subframeP
);
round_DL
=
ue_sched_ctrl
->
round
[
CC_id
][
harq_pid
];
eNB_UE_stats
->
crnti
=
rnti
;
eNB_UE_stats
->
rrc_status
=
mac_eNB_get_rrc_status
(
module_idP
,
rnti
);
eNB_UE_stats
->
harq_pid
=
harq_pid
;
eNB_UE_stats
->
harq_round
=
round_DL
;
if
(
eNB_UE_stats
->
rrc_status
<
RRC_RECONFIGURED
)
{
ue_sched_ctrl
->
uplane_inactivity_timer
=
0
;
}
if
(
continue_flag
==
1
)
{
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
S_DL_NONE
,
rnti
);
continue
;
}
if
(
eNB_UE_stats
->
rrc_status
<
RRC_CONNECTED
)
{
LOG_D
(
MAC
,
"UE %d is not in RRC_CONNECTED
\n
"
,
UE_id
);
continue
;
}
nb_available_rb
=
ue_sched_ctrl
->
pre_nb_available_rbs
[
CC_id
];
harq_pid
=
frame_subframe2_dl_harq_pid
(
cc
->
tdd_Config
,
frameP
,
subframeP
);
round_DL
=
ue_sched_ctrl
->
round
[
CC_id
][
harq_pid
];
eNB_UE_stats
->
crnti
=
rnti
;
eNB_UE_stats
->
rrc_status
=
mac_eNB_get_rrc_status
(
module_idP
,
rnti
);
eNB_UE_stats
->
harq_pid
=
harq_pid
;
eNB_UE_stats
->
harq_round
=
round_DL
;
if
(
eNB_UE_stats
->
rrc_status
<
RRC_RECONFIGURED
)
{
ue_sched_ctrl
->
uplane_inactivity_timer
=
0
;
}
header_length_total
=
0
;
sdu_length_total
=
0
;
num_sdus
=
0
;
if
(
eNB_UE_stats
->
rrc_status
<
RRC_CONNECTED
)
{
LOG_D
(
MAC
,
"UE %d is not in RRC_CONNECTED
\n
"
,
UE_id
);
continue
;
}
/*
DevCheck(((eNB_UE_stats->dl_cqi < MIN_CQI_VALUE) ||
(eNB_UE_stats->dl_cqi > MAX_CQI_VALUE)),
eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE);
*/
if
(
NFAPI_MODE
!=
NFAPI_MONOLITHIC
)
{
eNB_UE_stats
->
dlsch_mcs1
=
cqi_to_mcs
[
ue_sched_ctrl
->
dl_cqi
[
CC_id
]];
}
else
{
// this operation is also done in the preprocessor
eNB_UE_stats
->
dlsch_mcs1
=
cmin
(
eNB_UE_stats
->
dlsch_mcs1
,
eNB
->
slice_info
.
dl
[
slice_idxP
].
maxmcs
);
// cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
}
header_length_total
=
0
;
sdu_length_total
=
0
;
num_sdus
=
0
;
/*
DevCheck(((eNB_UE_stats->dl_cqi < MIN_CQI_VALUE) ||
(eNB_UE_stats->dl_cqi > MAX_CQI_VALUE)),
eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE);
*/
if
(
NFAPI_MODE
!=
NFAPI_MONOLITHIC
)
{
eNB_UE_stats
->
dlsch_mcs1
=
cqi_to_mcs
[
ue_sched_ctrl
->
dl_cqi
[
CC_id
]];
}
else
{
// this operation is also done in the preprocessor
eNB_UE_stats
->
dlsch_mcs1
=
cmin
(
eNB_UE_stats
->
dlsch_mcs1
,
eNB
->
slice_info
.
dl
[
0
/*slice_idxP*/
].
maxmcs
);
// cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
}
// Store stats
// eNB_UE_stats->dl_cqi= eNB_UE_stats->dl_cqi;
// Store stats
// eNB_UE_stats->dl_cqi= eNB_UE_stats->dl_cqi;
// Initializing the rb allocation indicator for each UE
for
(
j
=
0
;
j
<
N_RBG
[
CC_id
]
;
j
++
)
{
ue_template
->
rballoc_subband
[
harq_pid
][
j
]
=
0
;
}
// Initializing the rb allocation indicator for each UE
for
(
j
=
0
;
j
<
N_RBG
;
j
++
)
{
ue_template
->
rballoc_subband
[
harq_pid
][
j
]
=
0
;
}
LOG_D
(
MAC
,
"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)
\n
"
,
module_idP
,
frameP
,
UE_id
,
CC_id
,
rnti
,
harq_pid
,
round_DL
,
nb_available_rb
,
ue_sched_ctrl
->
dl_cqi
[
CC_id
],
eNB_UE_stats
->
dlsch_mcs1
,
eNB_UE_stats
->
rrc_status
);
/* Process retransmission */
if
(
round_DL
!=
8
)
{
// get freq_allocation
nb_rb
=
ue_template
->
nb_rb
[
harq_pid
];
TBS
=
get_TBS_DL
(
ue_template
->
oldmcs1
[
harq_pid
],
nb_rb
);
LOG_D
(
MAC
,
"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)
\n
"
,
module_idP
,
frameP
,
UE_id
,
CC_id
,
rnti
,
harq_pid
,
round_DL
,
nb_available_rb
,
ue_sched_ctrl
->
dl_cqi
[
CC_id
],
eNB_UE_stats
->
dlsch_mcs1
,
eNB_UE_stats
->
rrc_status
);
/* Process retransmission */
if
(
round_DL
!=
8
)
{
// get freq_allocation
nb_rb
=
ue_template
->
nb_rb
[
harq_pid
];
TBS
=
get_TBS_DL
(
ue_template
->
oldmcs1
[
harq_pid
],
nb_rb
);
if
(
nb_rb
<=
nb_available_rb
)
{
/* CDRX */
ue_sched_ctrl
->
harq_rtt_timer
[
CC_id
][
harq_pid
]
=
1
;
// restart HARQ RTT timer
if
(
ue_sched_ctrl
->
cdrx_configured
)
{
ue_sched_ctrl
->
drx_retransmission_timer
[
harq_pid
]
=
0
;
// stop drx retransmission
/*
* Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop.
*/
if
(
harq_pid
==
0
)
{
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0
,
(
unsigned
long
)
ue_sched_ctrl
->
drx_retransmission_timer
[
0
]);
}
}
if
(
nb_rb
<=
nb_available_rb
)
{
/* CDRX */
ue_sched_ctrl
->
harq_rtt_timer
[
CC_id
][
harq_pid
]
=
1
;
// restart HARQ RTT timer
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
ue_template
->
DAI
++
;
update_ul_dci
(
module_idP
,
CC_id
,
rnti
,
ue_template
->
DAI
,
subframeP
);
LOG_D
(
MAC
,
"DAI update: CC_id %d subframeP %d: UE %d, DAI %d
\n
"
,
CC_id
,
subframeP
,
UE_id
,
ue_template
->
DAI
);
}
if
(
ue_sched_ctrl
->
cdrx_configured
)
{
ue_sched_ctrl
->
drx_retransmission_timer
[
harq_pid
]
=
0
;
// stop drx retransmission
if
(
nb_rb
==
ue_sched_ctrl
->
pre_nb_available_rbs
[
CC_id
])
{
for
(
j
=
0
;
j
<
N_RBG
;
j
++
)
{
// for indicating the rballoc for each sub-band
ue_template
->
rballoc_subband
[
harq_pid
][
j
]
=
ue_sched_ctrl
->
rballoc_sub_UE
[
CC_id
][
j
];
}
}
else
{
nb_rb_temp
=
nb_rb
;
j
=
0
;
/*
* Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop.
*/
if
(
harq_pid
==
0
)
{
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0
,
(
unsigned
long
)
ue_sched_ctrl
->
drx_retransmission_timer
[
0
]);
while
((
nb_rb_temp
>
0
)
&&
(
j
<
N_RBG
))
{
if
(
ue_sched_ctrl
->
rballoc_sub_UE
[
CC_id
][
j
]
==
1
)
{
if
(
ue_template
->
rballoc_subband
[
harq_pid
][
j
])
LOG_W
(
MAC
,
"WARN: rballoc_subband not free for retrans?
\n
"
);
ue_template
->
rballoc_subband
[
harq_pid
][
j
]
=
ue_sched_ctrl
->
rballoc_sub_UE
[
CC_id
][
j
];
nb_rb_temp
-=
min_rb_unit
;
if
((
j
==
N_RBG
-
1
)
&&
(
N_RB_DL
==
25
||
N_RB_DL
==
50
))
nb_rb_temp
++
;
}
}
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
ue_template
->
DAI
++
;
update_ul_dci
(
module_idP
,
CC_id
,
rnti
,
ue_template
->
DAI
,
subframeP
);
LOG_D
(
MAC
,
"DAI update: CC_id %d subframeP %d: UE %d, DAI %d
\n
"
,
CC_id
,
subframeP
,
UE_id
,
ue_template
->
DAI
);
j
++
;
}
}
if
(
nb_rb
==
ue_sched_ctrl
->
pre_nb_available_rbs
[
CC_id
])
{
for
(
j
=
0
;
j
<
N_RBG
[
CC_id
];
j
++
)
{
// for indicating the rballoc for each sub-band
ue_template
->
rballoc_subband
[
harq_pid
][
j
]
=
ue_sched_ctrl
->
rballoc_sub_UE
[
CC_id
][
j
];
nb_available_rb
-=
nb_rb
;
switch
(
get_tmode
(
module_idP
,
CC_id
,
UE_id
))
{
case
1
:
case
2
:
case
7
:
default:
LOG_D
(
MAC
,
"retransmission DL_REQ: rnti:%x
\n
"
,
rnti
);
dl_config_pdu
=
&
dl_req
->
dl_config_pdu_list
[
dl_req
->
number_pdu
];
memset
((
void
*
)
dl_config_pdu
,
0
,
sizeof
(
nfapi_dl_config_request_pdu_t
));
dl_config_pdu
->
pdu_type
=
NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE
;
dl_config_pdu
->
pdu_size
=
(
uint8_t
)
(
2
+
sizeof
(
nfapi_dl_config_dci_dl_pdu
));
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
tl
.
tag
=
NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
dci_format
=
NFAPI_DL_DCI_FORMAT_1
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
aggregation_level
=
get_aggregation
(
get_bw_index
(
module_idP
,
CC_id
),
ue_sched_ctrl
->
dl_cqi
[
CC_id
],
format1
);
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
rnti
=
rnti
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
rnti_type
=
1
;
// CRNTI: see Table 4-10 from SCF082 - nFAPI specifications
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
transmission_power
=
6000
;
// equal to RS power
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
harq_process
=
harq_pid
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
tpc
=
1
;
// Don't adjust power when retransmitting
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
new_data_indicator_1
=
ue_template
->
oldNDI
[
harq_pid
];
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
mcs_1
=
ue_template
->
oldmcs1
[
harq_pid
];
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
redundancy_version_1
=
round_DL
&
3
;
// TDD
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
downlink_assignment_index
=
(
ue_template
->
DAI
-
1
)
&
3
;
LOG_D
(
MAC
,
"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d
\n
"
,
module_idP
,
CC_id
,
harq_pid
,
round_DL
,
ue_template
->
DAI
-
1
,
ue_template
->
oldmcs1
[
harq_pid
]);
}
else
{
LOG_D
(
MAC
,
"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d
\n
"
,
module_idP
,
CC_id
,
harq_pid
,
round_DL
,
ue_template
->
oldmcs1
[
harq_pid
]);
}
}
else
{
nb_rb_temp
=
nb_rb
;
j
=
0
;
while
((
nb_rb_temp
>
0
)
&&
(
j
<
N_RBG
[
CC_id
]))
{
if
(
ue_sched_ctrl
->
rballoc_sub_UE
[
CC_id
][
j
]
==
1
)
{
if
(
ue_template
->
rballoc_subband
[
harq_pid
][
j
])
LOG_W
(
MAC
,
"WARN: rballoc_subband not free for retrans?
\n
"
);
if
(
!
CCE_allocation_infeasible
(
module_idP
,
CC_id
,
1
,
subframeP
,
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
aggregation_level
,
rnti
))
{
dl_req
->
number_dci
++
;
dl_req
->
number_pdu
++
;
dl_req
->
tl
.
tag
=
NFAPI_DL_CONFIG_REQUEST_BODY_TAG
;
eNB
->
DL_req
[
CC_id
].
sfn_sf
=
frameP
<<
4
|
subframeP
;
eNB
->
DL_req
[
CC_id
].
header
.
message_id
=
NFAPI_DL_CONFIG_REQUEST
;
fill_nfapi_dlsch_config
(
eNB
,
dl_req
,
TBS
,
-
1
,
// retransmission, no pdu_index
rnti
,
0
,
// type 0 allocation from 7.1.6 in 36.213
0
,
// virtual_resource_block_assignment_flag, unused here
0
,
// resource_block_coding, to be filled in later
getQm
(
ue_template
->
oldmcs1
[
harq_pid
]),
round_DL
&
3
,
// redundancy version
1
,
// transport blocks
0
,
// transport block to codeword swap flag
cc
[
CC_id
].
p_eNB
==
1
?
0
:
1
,
// transmission_scheme
1
,
// number of layers
1
,
// number of subbands
// uint8_t codebook_index,
4
,
// UE category capacity
ue_template
->
physicalConfigDedicated
->
pdsch_ConfigDedicated
->
p_a
,
0
,
// delta_power_offset for TM5
0
,
// ngap
0
,
// nprb
cc
[
CC_id
].
p_eNB
==
1
?
1
:
2
,
// transmission mode
0
,
//number of PRBs treated as one subband, not used here
0
);
// number of beamforming vectors, not used here
LOG_D
(
MAC
,
"Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d
\n
"
,
eNB
->
pdu_index
[
CC_id
],
round_DL
);
program_dlsch_acknak
(
module_idP
,
CC_id
,
UE_id
,
frameP
,
subframeP
,
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
cce_idx
);
// No TX request for retransmission (check if null request for FAPI)
}
else
{
LOG_W
(
MAC
,
"Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation
\n
"
,
frameP
,
subframeP
,
UE_id
,
rnti
);
}
}
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
S_DL_SCHEDULED
,
rnti
);
//eNB_UE_stats->dlsch_trials[round]++;
eNB_UE_stats
->
num_retransmission
+=
1
;
eNB_UE_stats
->
rbs_used_retx
=
nb_rb
;
eNB_UE_stats
->
total_rbs_used_retx
+=
nb_rb
;
eNB_UE_stats
->
dlsch_mcs2
=
eNB_UE_stats
->
dlsch_mcs1
;
}
else
{
LOG_D
(
MAC
,
"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have
\n
"
,
module_idP
,
frameP
,
CC_id
,
UE_id
);
}
}
else
{
/* This is a potentially new SDU opportunity */
rlc_status
.
bytes_in_buffer
=
0
;
// Now check RLC information to compute number of required RBs
// get maximum TBS size for RLC request
TBS
=
get_TBS_DL
(
eNB_UE_stats
->
dlsch_mcs1
,
nb_available_rb
);
// add the length for all the control elements (timing adv, drx, etc) : header + payload
ue_template
->
rballoc_subband
[
harq_pid
][
j
]
=
ue_sched_ctrl
->
rballoc_sub_UE
[
CC_id
][
j
];
nb_rb_temp
-=
min_rb_unit
[
CC_id
]
;
if
(
ue_sched_ctrl
->
ta_timer
==
0
)
{
ta_update
=
ue_sched_ctrl
->
ta_update
;
if
((
j
==
N_RBG
[
CC_id
]
-
1
)
&&
(
N_RB_DL
[
CC_id
]
==
25
||
N_RB_DL
[
CC_id
]
==
50
))
nb_rb_temp
++
;
}
/* if we send TA then set timer to not send it for a while */
if
(
ta_update
!=
31
)
{
ue_sched_ctrl
->
ta_timer
=
20
;
}
/* reset ta_update */
ue_sched_ctrl
->
ta_update
=
31
;
}
else
{
ta_update
=
31
;
}
ta_len
=
(
ta_update
!=
31
)
?
2
:
0
;
// RLC data on DCCH
if
(
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
>
0
)
{
rlc_status
=
mac_rlc_status_ind
(
module_idP
,
rnti
,
module_idP
,
frameP
,
subframeP
,
ENB_FLAG_YES
,
MBMS_FLAG_NO
,
DCCH
,
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
,
0
,
0
);
sdu_lengths
[
0
]
=
0
;
if
(
rlc_status
.
bytes_in_buffer
>
0
)
{
LOG_D
(
MAC
,
"[eNB %d] SFN/SF %d.%d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)
\n
"
,
module_idP
,
frameP
,
subframeP
,
CC_id
,
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
);
sdu_lengths
[
0
]
=
mac_rlc_data_req
(
module_idP
,
rnti
,
module_idP
,
frameP
,
ENB_FLAG_YES
,
MBMS_FLAG_NO
,
DCCH
,
TBS
,
//not used
(
char
*
)
&
dlsch_buffer
[
0
],
0
,
0
);
j
++
;
if
((
rrc_release_info
.
num_UEs
>
0
)
&&
(
rlc_am_mui
.
rrc_mui_num
>
0
))
{
while
(
pthread_mutex_trylock
(
&
rrc_release_freelist
))
{
/* spin... */
}
}
nb_available_rb
-=
nb_rb
;
uint16_t
release_total
=
0
;
switch
(
get_tmode
(
module_idP
,
CC_id
,
UE_id
))
{
case
1
:
case
2
:
case
7
:
default:
LOG_D
(
MAC
,
"retransmission DL_REQ: rnti:%x
\n
"
,
rnti
);
dl_config_pdu
=
&
dl_req
->
dl_config_pdu_list
[
dl_req
->
number_pdu
];
memset
((
void
*
)
dl_config_pdu
,
0
,
sizeof
(
nfapi_dl_config_request_pdu_t
));
dl_config_pdu
->
pdu_type
=
NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE
;
dl_config_pdu
->
pdu_size
=
(
uint8_t
)
(
2
+
sizeof
(
nfapi_dl_config_dci_dl_pdu
));
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
tl
.
tag
=
NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
dci_format
=
NFAPI_DL_DCI_FORMAT_1
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
aggregation_level
=
get_aggregation
(
get_bw_index
(
module_idP
,
CC_id
),
ue_sched_ctrl
->
dl_cqi
[
CC_id
],
format1
);
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
rnti
=
rnti
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
rnti_type
=
1
;
// CRNTI: see Table 4-10 from SCF082 - nFAPI specifications
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
transmission_power
=
6000
;
// equal to RS power
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
harq_process
=
harq_pid
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
tpc
=
1
;
// Don't adjust power when retransmitting
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
new_data_indicator_1
=
ue_template
->
oldNDI
[
harq_pid
];
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
mcs_1
=
ue_template
->
oldmcs1
[
harq_pid
];
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
redundancy_version_1
=
round_DL
&
3
;
// TDD
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
downlink_assignment_index
=
(
ue_template
->
DAI
-
1
)
&
3
;
LOG_D
(
MAC
,
"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d
\n
"
,
module_idP
,
CC_id
,
harq_pid
,
round_DL
,
ue_template
->
DAI
-
1
,
ue_template
->
oldmcs1
[
harq_pid
]);
for
(
release_num
=
0
,
release_ctrl
=
&
rrc_release_info
.
RRC_release_ctrl
[
0
];
release_num
<
NUMBER_OF_UE_MAX
;
release_num
++
,
release_ctrl
++
)
{
if
(
release_ctrl
->
flag
>
0
)
{
release_total
++
;
}
else
{
LOG_D
(
MAC
,
"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d
\n
"
,
module_idP
,
CC_id
,
harq_pid
,
round_DL
,
ue_template
->
oldmcs1
[
harq_pid
]);
continue
;
}
if
(
!
CCE_allocation_infeasible
(
module_idP
,
CC_id
,
1
,
subframeP
,
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
aggregation_level
,
rnti
))
{
dl_req
->
number_dci
++
;
dl_req
->
number_pdu
++
;
dl_req
->
tl
.
tag
=
NFAPI_DL_CONFIG_REQUEST_BODY_TAG
;
eNB
->
DL_req
[
CC_id
].
sfn_sf
=
frameP
<<
4
|
subframeP
;
eNB
->
DL_req
[
CC_id
].
header
.
message_id
=
NFAPI_DL_CONFIG_REQUEST
;
fill_nfapi_dlsch_config
(
eNB
,
dl_req
,
TBS
,
-
1
,
// retransmission, no pdu_index
rnti
,
0
,
// type 0 allocation from 7.1.6 in 36.213
0
,
// virtual_resource_block_assignment_flag, unused here
0
,
// resource_block_coding, to be filled in later
getQm
(
ue_template
->
oldmcs1
[
harq_pid
]),
round_DL
&
3
,
// redundancy version
1
,
// transport blocks
0
,
// transport block to codeword swap flag
cc
[
CC_id
].
p_eNB
==
1
?
0
:
1
,
// transmission_scheme
1
,
// number of layers
1
,
// number of subbands
// uint8_t codebook_index,
4
,
// UE category capacity
ue_template
->
physicalConfigDedicated
->
pdsch_ConfigDedicated
->
p_a
,
0
,
// delta_power_offset for TM5
0
,
// ngap
0
,
// nprb
cc
[
CC_id
].
p_eNB
==
1
?
1
:
2
,
// transmission mode
0
,
//number of PRBs treated as one subband, not used here
0
);
// number of beamforming vectors, not used here
LOG_D
(
MAC
,
"Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d
\n
"
,
eNB
->
pdu_index
[
CC_id
],
round_DL
);
program_dlsch_acknak
(
module_idP
,
CC_id
,
UE_id
,
frameP
,
subframeP
,
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
cce_idx
);
// No TX request for retransmission (check if null request for FAPI)
}
else
{
LOG_W
(
MAC
,
"Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation
\n
"
,
frameP
,
subframeP
,
UE_id
,
rnti
);
if
(
release_ctrl
->
flag
==
1
)
{
if
(
release_ctrl
->
rnti
==
rnti
)
{
for
(
uint16_t
mui_num
=
0
;
mui_num
<
rlc_am_mui
.
rrc_mui_num
;
mui_num
++
)
{
if
(
release_ctrl
->
rrc_eNB_mui
==
rlc_am_mui
.
rrc_mui
[
mui_num
])
{
release_ctrl
->
flag
=
3
;
LOG_D
(
MAC
,
"DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 1->3
\n
"
,
release_num
,
rnti
,
rlc_am_mui
.
rrc_mui
[
mui_num
],
mui_num
);
break
;
}
}
}
}
if
(
release_ctrl
->
flag
==
2
)
{
if
(
release_ctrl
->
rnti
==
rnti
)
{
for
(
uint16_t
mui_num
=
0
;
mui_num
<
rlc_am_mui
.
rrc_mui_num
;
mui_num
++
)
{
if
(
release_ctrl
->
rrc_eNB_mui
==
rlc_am_mui
.
rrc_mui
[
mui_num
])
{
release_ctrl
->
flag
=
4
;
LOG_D
(
MAC
,
"DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 2->4
\n
"
,
release_num
,
rnti
,
rlc_am_mui
.
rrc_mui
[
mui_num
],
mui_num
);
break
;
}
}
}
}
if
(
release_total
>=
rrc_release_info
.
num_UEs
)
break
;
}
pthread_mutex_unlock
(
&
rrc_release_freelist
);
}
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
S_DL_SCHEDULED
,
rnti
);
//eNB_UE_stats->dlsch_trials[round]++;
eNB_UE_stats
->
num_retransmission
+=
1
;
eNB_UE_stats
->
rbs_used_retx
=
nb_rb
;
eNB_UE_stats
->
total_rbs_used_retx
+=
nb_rb
;
eNB_UE_stats
->
dlsch_mcs2
=
eNB_UE_stats
->
dlsch_mcs1
;
}
else
{
LOG_D
(
MAC
,
"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have
\n
"
,
for
(
ra_ii
=
0
,
ra
=
&
eNB
->
common_channels
[
CC_id
].
ra
[
0
];
ra_ii
<
NB_RA_PROC_MAX
;
ra_ii
++
,
ra
++
)
{
if
((
ra
->
rnti
==
rnti
)
&&
(
ra
->
state
==
MSGCRNTI
))
{
for
(
uint16_t
mui_num
=
0
;
mui_num
<
rlc_am_mui
.
rrc_mui_num
;
mui_num
++
)
{
if
(
ra
->
crnti_rrc_mui
==
rlc_am_mui
.
rrc_mui
[
mui_num
])
{
ra
->
crnti_harq_pid
=
harq_pid
;
ra
->
state
=
MSGCRNTI_ACK
;
break
;
}
}
}
}
T
(
T_ENB_MAC_UE_DL_SDU
,
T_INT
(
module_idP
),
T_INT
(
CC_id
),
T_INT
(
rnti
),
T_INT
(
frameP
),
T_INT
(
subframeP
),
T_INT
(
harq_pid
),
T_INT
(
DCCH
),
T_INT
(
sdu_lengths
[
0
]));
LOG_D
(
MAC
,
"[eNB %d][DCCH] CC_id %d Got %d bytes from RLC
\n
"
,
module_idP
,
frameP
,
CC_id
,
UE_id
);
}
}
else
{
/* This is a potentially new SDU opportunity */
rlc_status
.
bytes_in_buffer
=
0
;
// Now check RLC information to compute number of required RBs
// get maximum TBS size for RLC request
TBS
=
get_TBS_DL
(
eNB_UE_stats
->
dlsch_mcs1
,
nb_available_rb
);
sdu_lengths
[
0
]);
sdu_length_total
=
sdu_lengths
[
0
];
sdu_lcids
[
0
]
=
DCCH
;
eNB_UE_stats
->
lcid_sdu
[
0
]
=
DCCH
;
eNB_UE_stats
->
sdu_length_tx
[
DCCH
]
=
sdu_lengths
[
0
];
eNB_UE_stats
->
num_pdu_tx
[
DCCH
]
+=
1
;
eNB_UE_stats
->
num_bytes_tx
[
DCCH
]
+=
sdu_lengths
[
0
];
header_length_last
=
1
+
1
+
(
sdu_lengths
[
0
]
>=
128
);
header_length_total
+=
header_length_last
;
num_sdus
=
1
;
#ifdef DEBUG_eNB_SCHEDULER
LOG_T
(
MAC
,
"[eNB %d][DCCH] CC_id %d Got %d bytes :"
,
module_idP
,
CC_id
,
sdu_lengths
[
0
]);
// add the length for all the control elements (timing adv, drx, etc) : header + payload
for
(
j
=
0
;
j
<
sdu_lengths
[
0
];
++
j
)
{
LOG_T
(
MAC
,
"%x "
,
dlsch_buffer
[
j
]);
}
if
(
ue_sched_ctrl
->
ta_timer
==
0
)
{
ta_update
=
ue_sched_ctrl
->
ta_update
;
LOG_T
(
MAC
,
"
\n
"
);
#endif
}
}
/* if we send TA then set timer to not send it for a while */
if
(
ta_update
!=
31
)
{
ue_sched_ctrl
->
ta_timer
=
20
;
// RLC data on DCCH1
if
(
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
>
0
)
{
rlc_status
=
mac_rlc_status_ind
(
module_idP
,
rnti
,
module_idP
,
frameP
,
subframeP
,
ENB_FLAG_YES
,
MBMS_FLAG_NO
,
DCCH
+
1
,
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
,
0
,
0
);
// DCCH SDU
sdu_lengths
[
num_sdus
]
=
0
;
if
(
rlc_status
.
bytes_in_buffer
>
0
)
{
LOG_D
(
MAC
,
"[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)
\n
"
,
module_idP
,
frameP
,
CC_id
,
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
);
sdu_lengths
[
num_sdus
]
+=
mac_rlc_data_req
(
module_idP
,
rnti
,
module_idP
,
frameP
,
ENB_FLAG_YES
,
MBMS_FLAG_NO
,
DCCH
+
1
,
TBS
,
//not used
(
char
*
)
&
dlsch_buffer
[
sdu_length_total
],
0
,
0
);
T
(
T_ENB_MAC_UE_DL_SDU
,
T_INT
(
module_idP
),
T_INT
(
CC_id
),
T_INT
(
rnti
),
T_INT
(
frameP
),
T_INT
(
subframeP
),
T_INT
(
harq_pid
),
T_INT
(
DCCH
+
1
),
T_INT
(
sdu_lengths
[
num_sdus
]));
sdu_lcids
[
num_sdus
]
=
DCCH1
;
sdu_length_total
+=
sdu_lengths
[
num_sdus
];
eNB_UE_stats
->
lcid_sdu
[
num_sdus
]
=
DCCH1
;
eNB_UE_stats
->
sdu_length_tx
[
DCCH1
]
=
sdu_lengths
[
num_sdus
];
eNB_UE_stats
->
num_pdu_tx
[
DCCH1
]
+=
1
;
eNB_UE_stats
->
num_bytes_tx
[
DCCH1
]
+=
sdu_lengths
[
num_sdus
];
header_length_last
=
1
+
1
+
(
sdu_lengths
[
num_sdus
]
>=
128
);
header_length_total
+=
header_length_last
;
num_sdus
++
;
#ifdef DEBUG_eNB_SCHEDULER
LOG_T
(
MAC
,
"[eNB %d][DCCH1] CC_id %d Got %d bytes :"
,
module_idP
,
CC_id
,
sdu_lengths
[
num_sdus
]);
for
(
j
=
0
;
j
<
sdu_lengths
[
num_sdus
];
++
j
)
{
LOG_T
(
MAC
,
"%x "
,
dlsch_buffer
[
j
]);
}
/* reset ta_update */
ue_sched_ctrl
->
ta_update
=
31
;
}
else
{
ta_update
=
31
;
LOG_T
(
MAC
,
"
\n
"
);
#endif
}
}
ta_len
=
(
ta_update
!=
31
)
?
2
:
0
;
// TODO: lcid has to be sorted before the actual allocation (similar struct as ue_list).
for
(
lcid
=
NB_RB_MAX
-
1
;
lcid
>=
DTCH
;
lcid
--
)
{
// TODO: check if the lcid is active
LOG_D
(
MAC
,
"[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)
\n
"
,
module_idP
,
frameP
,
lcid
,
TBS
,
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
);
// RLC data on DCCH
if
(
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
>
0
)
{
rlc_status
=
mac_rlc_status_ind
(
module_idP
,
rnti
,
...
...
@@ -984,660 +1177,453 @@ schedule_ue_spec(module_id_t module_idP,
subframeP
,
ENB_FLAG_YES
,
MBMS_FLAG_NO
,
DCCH
,
lcid
,
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
,
0
,
0
);
sdu_lengths
[
0
]
=
0
;
if
(
rlc_status
.
bytes_in_buffer
>
0
)
{
LOG_D
(
MAC
,
"[eNB %d]
SFN/SF %d.%d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message
)
\n
"
,
LOG_D
(
MAC
,
"[eNB %d]
[USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d
)
\n
"
,
module_idP
,
frameP
,
subframeP
,
CC_id
,
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
);
sdu_lengths
[
0
]
=
mac_rlc_data_req
(
module_idP
,
rnti
,
module_idP
,
frameP
,
ENB_FLAG_YES
,
MBMS_FLAG_NO
,
DCCH
,
TBS
,
//not used
(
char
*
)
&
dlsch_buffer
[
0
],
0
,
0
);
if
((
rrc_release_info
.
num_UEs
>
0
)
&&
(
rlc_am_mui
.
rrc_mui_num
>
0
))
{
while
(
pthread_mutex_trylock
(
&
rrc_release_freelist
))
{
/* spin... */
}
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
,
lcid
,
header_length_total
);
sdu_lengths
[
num_sdus
]
=
mac_rlc_data_req
(
module_idP
,
rnti
,
module_idP
,
frameP
,
ENB_FLAG_YES
,
MBMS_FLAG_NO
,
lcid
,
TBS
,
//not used
(
char
*
)
&
dlsch_buffer
[
sdu_length_total
],
0
,
0
);
T
(
T_ENB_MAC_UE_DL_SDU
,
T_INT
(
module_idP
),
T_INT
(
CC_id
),
T_INT
(
rnti
),
T_INT
(
frameP
),
T_INT
(
subframeP
),
T_INT
(
harq_pid
),
T_INT
(
lcid
),
T_INT
(
sdu_lengths
[
num_sdus
]));
LOG_D
(
MAC
,
"[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d
\n
"
,
module_idP
,
sdu_lengths
[
num_sdus
],
lcid
);
sdu_lcids
[
num_sdus
]
=
lcid
;
sdu_length_total
+=
sdu_lengths
[
num_sdus
];
eNB_UE_stats
->
num_pdu_tx
[
lcid
]
++
;
eNB_UE_stats
->
lcid_sdu
[
num_sdus
]
=
lcid
;
eNB_UE_stats
->
sdu_length_tx
[
lcid
]
=
sdu_lengths
[
num_sdus
];
eNB_UE_stats
->
num_bytes_tx
[
lcid
]
+=
sdu_lengths
[
num_sdus
];
header_length_last
=
1
+
1
+
(
sdu_lengths
[
num_sdus
]
>=
128
);
header_length_total
+=
header_length_last
;
num_sdus
++
;
ue_sched_ctrl
->
uplane_inactivity_timer
=
0
;
// reset RRC inactivity timer after uplane activity
ue_contextP
=
rrc_eNB_get_ue_context
(
RC
.
rrc
[
module_idP
],
rnti
);
if
(
ue_contextP
!=
NULL
)
{
ue_contextP
->
ue_context
.
ue_rrc_inactivity_timer
=
1
;
}
else
{
LOG_E
(
MAC
,
"[eNB %d] CC_id %d Couldn't find the context associated to UE (RNTI %d) and reset RRC inactivity timer
\n
"
,
module_idP
,
CC_id
,
rnti
);
}
}
// end if (rlc_status.bytes_in_buffer > 0)
}
else
{
// no TBS left
break
;
// break for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--)
}
}
uint16_t
release_total
=
0
;
/* Last header does not have length field */
if
(
header_length_total
)
{
header_length_total
-=
header_length_last
;
header_length_total
++
;
}
for
(
release_num
=
0
,
release_ctrl
=
&
rrc_release_info
.
RRC_release_ctrl
[
0
];
release_num
<
NUMBER_OF_UE_MAX
;
release_num
++
,
release_ctrl
++
)
{
if
(
release_ctrl
->
flag
>
0
)
{
release_total
++
;
}
else
{
continue
;
}
// there is at least one SDU or TA command
// if (num_sdus > 0 ){
if
(
ta_len
+
sdu_length_total
+
header_length_total
>
0
)
{
// Now compute number of required RBs for total sdu length
// Assume RAH format 2
mcs
=
eNB_UE_stats
->
dlsch_mcs1
;
if
(
release_ctrl
->
flag
==
1
)
{
if
(
release_ctrl
->
rnti
==
rnti
)
{
for
(
uint16_t
mui_num
=
0
;
mui_num
<
rlc_am_mui
.
rrc_mui_num
;
mui_num
++
)
{
if
(
release_ctrl
->
rrc_eNB_mui
==
rlc_am_mui
.
rrc_mui
[
mui_num
])
{
release_ctrl
->
flag
=
3
;
LOG_D
(
MAC
,
"DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 1->3
\n
"
,
release_num
,
rnti
,
rlc_am_mui
.
rrc_mui
[
mui_num
],
mui_num
);
break
;
}
}
}
}
if
(
mcs
==
0
)
{
nb_rb
=
4
;
// don't let the TBS get too small
}
else
{
nb_rb
=
min_rb_unit
;
}
if
(
release_ctrl
->
flag
==
2
)
{
if
(
release_ctrl
->
rnti
==
rnti
)
{
for
(
uint16_t
mui_num
=
0
;
mui_num
<
rlc_am_mui
.
rrc_mui_num
;
mui_num
++
)
{
if
(
release_ctrl
->
rrc_eNB_mui
==
rlc_am_mui
.
rrc_mui
[
mui_num
])
{
release_ctrl
->
flag
=
4
;
LOG_D
(
MAC
,
"DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 2->4
\n
"
,
release_num
,
rnti
,
rlc_am_mui
.
rrc_mui
[
mui_num
],
mui_num
);
break
;
}
}
}
}
TBS
=
get_TBS_DL
(
mcs
,
nb_rb
);
if
(
release_total
>=
rrc_release_info
.
num_UEs
)
break
;
}
while
(
TBS
<
sdu_length_total
+
header_length_total
+
ta_len
)
{
nb_rb
+=
min_rb_unit
;
//
pthread_mutex_unlock
(
&
rrc_release_freelist
);
}
if
(
nb_rb
>
nb_available_rb
)
{
// if we've gone beyond the maximum number of RBs
// (can happen if N_RB_DL is odd)
TBS
=
get_TBS_DL
(
eNB_UE_stats
->
dlsch_mcs1
,
nb_available_rb
);
nb_rb
=
nb_available_rb
;
break
;
}
for
(
ra_ii
=
0
,
ra
=
&
eNB
->
common_channels
[
CC_id
].
ra
[
0
];
ra_ii
<
NB_RA_PROC_MAX
;
ra_ii
++
,
ra
++
)
{
if
((
ra
->
rnti
==
rnti
)
&&
(
ra
->
state
==
MSGCRNTI
))
{
for
(
uint16_t
mui_num
=
0
;
mui_num
<
rlc_am_mui
.
rrc_mui_num
;
mui_num
++
)
{
if
(
ra
->
crnti_rrc_mui
==
rlc_am_mui
.
rrc_mui
[
mui_num
])
{
ra
->
crnti_harq_pid
=
harq_pid
;
ra
->
state
=
MSGCRNTI_ACK
;
break
;
}
}
}
}
TBS
=
get_TBS_DL
(
eNB_UE_stats
->
dlsch_mcs1
,
nb_rb
);
}
T
(
T_ENB_MAC_UE_DL_SDU
,
T_INT
(
module_idP
),
T_INT
(
CC_id
),
T_INT
(
rnti
),
T_INT
(
frameP
),
T_INT
(
subframeP
),
T_INT
(
harq_pid
),
T_INT
(
DCCH
),
T_INT
(
sdu_lengths
[
0
]));
LOG_D
(
MAC
,
"[eNB %d][DCCH] CC_id %d Got %d bytes from RLC
\n
"
,
module_idP
,
CC_id
,
sdu_lengths
[
0
]);
sdu_length_total
=
sdu_lengths
[
0
];
sdu_lcids
[
0
]
=
DCCH
;
eNB_UE_stats
->
lcid_sdu
[
0
]
=
DCCH
;
eNB_UE_stats
->
sdu_length_tx
[
DCCH
]
=
sdu_lengths
[
0
];
eNB_UE_stats
->
num_pdu_tx
[
DCCH
]
+=
1
;
eNB_UE_stats
->
num_bytes_tx
[
DCCH
]
+=
sdu_lengths
[
0
];
header_length_last
=
1
+
1
+
(
sdu_lengths
[
0
]
>=
128
);
header_length_total
+=
header_length_last
;
num_sdus
=
1
;
#ifdef DEBUG_eNB_SCHEDULER
LOG_T
(
MAC
,
"[eNB %d][DCCH] CC_id %d Got %d bytes :"
,
module_idP
,
CC_id
,
sdu_lengths
[
0
]);
if
(
nb_rb
==
ue_sched_ctrl
->
pre_nb_available_rbs
[
CC_id
])
{
for
(
j
=
0
;
j
<
N_RBG
;
++
j
)
{
// for indicating the rballoc for each sub-band
ue_template
->
rballoc_subband
[
harq_pid
][
j
]
=
ue_sched_ctrl
->
rballoc_sub_UE
[
CC_id
][
j
];
}
}
else
{
nb_rb_temp
=
nb_rb
;
j
=
0
;
for
(
j
=
0
;
j
<
sdu_lengths
[
0
];
++
j
)
{
LOG_T
(
MAC
,
"%x "
,
dlsch_buffer
[
j
]);
while
((
nb_rb_temp
>
0
)
&&
(
j
<
N_RBG
))
{
if
(
ue_sched_ctrl
->
rballoc_sub_UE
[
CC_id
][
j
]
==
1
)
{
ue_template
->
rballoc_subband
[
harq_pid
][
j
]
=
ue_sched_ctrl
->
rballoc_sub_UE
[
CC_id
][
j
];
if
((
j
==
N_RBG
-
1
)
&&
((
N_RB_DL
==
25
)
||
(
N_RB_DL
==
50
)))
{
nb_rb_temp
=
nb_rb_temp
-
min_rb_unit
+
1
;
}
else
{
nb_rb_temp
=
nb_rb_temp
-
min_rb_unit
;
}
}
LOG_T
(
MAC
,
"
\n
"
);
#endif
j
++
;
}
}
// RLC data on DCCH1
if
(
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
>
0
)
{
rlc_status
=
mac_rlc_status_ind
(
module_idP
,
rnti
,
module_idP
,
frameP
,
subframeP
,
ENB_FLAG_YES
,
MBMS_FLAG_NO
,
DCCH
+
1
,
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
,
0
,
0
);
// DCCH SDU
sdu_lengths
[
num_sdus
]
=
0
;
if
(
rlc_status
.
bytes_in_buffer
>
0
)
{
LOG_D
(
MAC
,
"[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)
\n
"
,
module_idP
,
frameP
,
CC_id
,
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
);
sdu_lengths
[
num_sdus
]
+=
mac_rlc_data_req
(
module_idP
,
rnti
,
module_idP
,
frameP
,
ENB_FLAG_YES
,
MBMS_FLAG_NO
,
DCCH
+
1
,
TBS
,
//not used
(
char
*
)
&
dlsch_buffer
[
sdu_length_total
],
0
,
0
);
T
(
T_ENB_MAC_UE_DL_SDU
,
T_INT
(
module_idP
),
T_INT
(
CC_id
),
T_INT
(
rnti
),
T_INT
(
frameP
),
T_INT
(
subframeP
),
T_INT
(
harq_pid
),
T_INT
(
DCCH
+
1
),
T_INT
(
sdu_lengths
[
num_sdus
]));
sdu_lcids
[
num_sdus
]
=
DCCH1
;
sdu_length_total
+=
sdu_lengths
[
num_sdus
];
eNB_UE_stats
->
lcid_sdu
[
num_sdus
]
=
DCCH1
;
eNB_UE_stats
->
sdu_length_tx
[
DCCH1
]
=
sdu_lengths
[
num_sdus
];
eNB_UE_stats
->
num_pdu_tx
[
DCCH1
]
+=
1
;
eNB_UE_stats
->
num_bytes_tx
[
DCCH1
]
+=
sdu_lengths
[
num_sdus
];
header_length_last
=
1
+
1
+
(
sdu_lengths
[
num_sdus
]
>=
128
);
header_length_total
+=
header_length_last
;
num_sdus
++
;
#ifdef DEBUG_eNB_SCHEDULER
LOG_T
(
MAC
,
"[eNB %d][DCCH1] CC_id %d Got %d bytes :"
,
module_idP
,
CC_id
,
sdu_lengths
[
num_sdus
]);
// decrease mcs until TBS falls below required length
while
((
TBS
>
sdu_length_total
+
header_length_total
+
ta_len
)
&&
(
mcs
>
0
))
{
mcs
--
;
TBS
=
get_TBS_DL
(
mcs
,
nb_rb
);
}
for
(
j
=
0
;
j
<
sdu_lengths
[
num_sdus
];
++
j
)
{
LOG_T
(
MAC
,
"%x "
,
dlsch_buffer
[
j
]);
}
// if we have decreased too much or we don't have enough RBs, increase MCS
while
(
TBS
<
sdu_length_total
+
header_length_total
+
ta_len
&&
((
ue_sched_ctrl
->
dl_pow_off
[
CC_id
]
>
0
&&
mcs
<
28
)
||
(
ue_sched_ctrl
->
dl_pow_off
[
CC_id
]
==
0
&&
mcs
<=
15
)))
{
mcs
++
;
TBS
=
get_TBS_DL
(
mcs
,
nb_rb
);
}
LOG_T
(
MAC
,
"
\n
"
);
LOG_D
(
MAC
,
"dlsch_mcs before and after the rate matching = (%d, %d)
\n
"
,
eNB_UE_stats
->
dlsch_mcs1
,
mcs
);
#ifdef DEBUG_eNB_SCHEDULER
LOG_D
(
MAC
,
"[eNB %d] CC_id %d Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)
\n
"
,
module_idP
,
CC_id
,
mcs
,
TBS
,
nb_rb
);
// msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n",
// TBS, sdu_length_total, offset, TBS-sdu_length_total-offset);
#endif
}
if
(
TBS
-
header_length_total
-
sdu_length_total
-
ta_len
<=
2
)
{
padding
=
TBS
-
header_length_total
-
sdu_length_total
-
ta_len
;
post_padding
=
0
;
}
else
{
padding
=
0
;
post_padding
=
1
;
}
// TODO: lcid has to be sorted before the actual allocation (similar struct as ue_list).
for
(
lcid
=
NB_RB_MAX
-
1
;
lcid
>=
DTCH
;
lcid
--
)
{
// TODO: check if the lcid is active
LOG_D
(
MAC
,
"[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)
\n
"
,
offset
=
generate_dlsch_header
((
unsigned
char
*
)
UE_list
->
DLSCH_pdu
[
CC_id
][
0
][
UE_id
].
payload
[
0
],
num_sdus
,
//num_sdus
sdu_lengths
,
//
sdu_lcids
,
255
,
// no drx
ta_update
,
// timing advance
NULL
,
// contention res id
padding
,
post_padding
);
//#ifdef DEBUG_eNB_SCHEDULER
if
(
ta_update
!=
31
)
{
LOG_D
(
MAC
,
"[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_length %d
\n
"
,
module_idP
,
frameP
,
lcid
,
UE_id
,
CC_id
,
sdu_length_total
,
num_sdus
,
sdu_lengths
[
0
],
sdu_lcids
[
0
],
offset
,
ta_update
,
padding
,
post_padding
,
mcs
,
TBS
,
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
);
if
(
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
>
0
)
{
rlc_status
=
mac_rlc_status_ind
(
module_idP
,
rnti
,
module_idP
,
frameP
,
subframeP
,
ENB_FLAG_YES
,
MBMS_FLAG_NO
,
lcid
,
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
,
0
,
0
);
nb_rb
,
header_length_total
);
}
if
(
rlc_status
.
bytes_in_buffer
>
0
)
{
LOG_D
(
MAC
,
"[eNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d)
\n
"
,
module_idP
,
frameP
,
TBS
-
ta_len
-
header_length_total
-
sdu_length_total
-
3
,
lcid
,
header_length_total
);
sdu_lengths
[
num_sdus
]
=
mac_rlc_data_req
(
module_idP
,
rnti
,
module_idP
,
frameP
,
ENB_FLAG_YES
,
MBMS_FLAG_NO
,
lcid
,
TBS
,
//not used
(
char
*
)
&
dlsch_buffer
[
sdu_length_total
],
0
,
0
);
T
(
T_ENB_MAC_UE_DL_SDU
,
T_INT
(
module_idP
),
T_INT
(
CC_id
),
T_INT
(
rnti
),
T_INT
(
frameP
),
T_INT
(
subframeP
),
T_INT
(
harq_pid
),
T_INT
(
lcid
),
T_INT
(
sdu_lengths
[
num_sdus
]));
LOG_D
(
MAC
,
"[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d
\n
"
,
module_idP
,
sdu_lengths
[
num_sdus
],
lcid
);
sdu_lcids
[
num_sdus
]
=
lcid
;
sdu_length_total
+=
sdu_lengths
[
num_sdus
];
eNB_UE_stats
->
num_pdu_tx
[
lcid
]
++
;
eNB_UE_stats
->
lcid_sdu
[
num_sdus
]
=
lcid
;
eNB_UE_stats
->
sdu_length_tx
[
lcid
]
=
sdu_lengths
[
num_sdus
];
eNB_UE_stats
->
num_bytes_tx
[
lcid
]
+=
sdu_lengths
[
num_sdus
];
header_length_last
=
1
+
1
+
(
sdu_lengths
[
num_sdus
]
>=
128
);
header_length_total
+=
header_length_last
;
num_sdus
++
;
ue_sched_ctrl
->
uplane_inactivity_timer
=
0
;
// reset RRC inactivity timer after uplane activity
ue_contextP
=
rrc_eNB_get_ue_context
(
RC
.
rrc
[
module_idP
],
rnti
);
//#endif
#ifdef DEBUG_eNB_SCHEDULER
LOG_T
(
MAC
,
"[eNB %d] First 16 bytes of DLSCH :
\n
"
);
if
(
ue_contextP
!=
NULL
)
{
ue_contextP
->
ue_context
.
ue_rrc_inactivity_timer
=
1
;
}
else
{
LOG_E
(
MAC
,
"[eNB %d] CC_id %d Couldn't find the context associated to UE (RNTI %d) and reset RRC inactivity timer
\n
"
,
module_idP
,
CC_id
,
rnti
);
}
}
// end if (rlc_status.bytes_in_buffer > 0)
}
else
{
// no TBS left
break
;
// break for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--)
}
for
(
int
i
=
0
;
i
<
16
;
i
++
)
{
LOG_T
(
MAC
,
"%x."
,
dlsch_buffer
[
i
]);
}
/* Last header does not have length field */
if
(
header_length_total
)
{
header_length_total
-=
header_length_last
;
header_length_total
++
;
LOG_T
(
MAC
,
"
\n
"
);
#endif
// cycle through SDUs and place in dlsch_buffer
dlsch_pdu
=
&
UE_list
->
DLSCH_pdu
[
CC_id
][
0
][
UE_id
];
memcpy
(
&
dlsch_pdu
->
payload
[
0
][
offset
],
dlsch_buffer
,
sdu_length_total
);
// memcpy(RC.mac[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]);
// fill remainder of DLSCH with 0
for
(
j
=
0
;
j
<
(
TBS
-
sdu_length_total
-
offset
);
j
++
)
{
dlsch_pdu
->
payload
[
0
][
offset
+
sdu_length_total
+
j
]
=
0
;
}
// there is at least one SDU or TA command
// if (num_sdus > 0 ){
if
(
ta_len
+
sdu_length_total
+
header_length_total
>
0
)
{
// Now compute number of required RBs for total sdu length
// Assume RAH format 2
mcs
=
eNB_UE_stats
->
dlsch_mcs1
;
if
(
mcs
==
0
)
{
nb_rb
=
4
;
// don't let the TBS get too small
}
else
{
nb_rb
=
min_rb_unit
[
CC_id
]
;
}
T
BS
=
get_TBS_DL
(
mcs
,
nb_rb
);
while
(
TBS
<
sdu_length_total
+
header_length_total
+
ta_len
)
{
nb_rb
+=
min_rb_unit
[
CC_id
];
//
if
(
nb_rb
>
nb_available_rb
)
{
// if we've gone beyond the maximum number of RBs
// (can happen if N_RB_DL is odd)
TBS
=
get_TBS_DL
(
eNB_UE_stats
->
dlsch_mcs1
,
nb_available_rb
);
nb_rb
=
nb_available_rb
;
break
;
}
TBS
=
get_TBS_DL
(
eNB_UE_stats
->
dlsch_mcs1
,
nb_rb
);
}
if
(
nb_rb
==
ue_sched_ctrl
->
pre_nb_available_rbs
[
CC_id
])
{
for
(
j
=
0
;
j
<
N_RBG
[
CC_id
];
++
j
)
{
// for indicating the rballoc for each sub-band
ue_template
->
rballoc_subband
[
harq_pid
][
j
]
=
ue_sched_ctrl
->
rballoc_sub_UE
[
CC_id
][
j
]
;
}
}
else
{
nb_rb_temp
=
nb_rb
;
j
=
0
;
while
((
nb_rb_temp
>
0
)
&&
(
j
<
N_RBG
[
CC_id
]))
{
if
(
ue_sched_ctrl
->
rballoc_sub_UE
[
CC_id
][
j
]
==
1
)
{
ue_template
->
rballoc_subband
[
harq_pid
][
j
]
=
ue_sched_ctrl
->
rballoc_sub_UE
[
CC_id
][
j
];
if
((
j
==
N_RBG
[
CC_id
]
-
1
)
&&
((
N_RB_DL
[
CC_id
]
==
25
)
||
(
N_RB_DL
[
CC_id
]
==
50
)))
{
nb_rb_temp
=
nb_rb_temp
-
min_rb_unit
[
CC_id
]
+
1
;
}
else
{
nb_rb_temp
=
nb_rb_temp
-
min_rb_unit
[
CC_id
];
}
}
trace_pdu
(
DIRECTION_DOWNLINK
,
(
uint8_t
*
)
dlsch_pdu
->
payload
[
0
],
TBS
,
module_idP
,
WS_C_RNTI
,
UE_RNTI
(
module_idP
,
UE_id
),
eNB
->
frame
,
eNB
->
subframe
,
0
,
0
)
;
T
(
T_ENB_MAC_UE_DL_PDU_WITH_DATA
,
T_INT
(
module_idP
),
T
_INT
(
CC_id
),
T_INT
(
rnti
),
T_INT
(
frameP
),
T_INT
(
subframeP
),
T_INT
(
harq_pid
),
T_BUFFER
(
dlsch_pdu
->
payload
[
0
],
TBS
));
ue_template
->
nb_rb
[
harq_pid
]
=
nb_rb
;
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
S_DL_SCHEDULED
,
rnti
);
// store stats
eNB
->
eNB_stats
[
CC_id
].
dlsch_bytes_tx
+=
sdu_length_total
;
eNB
->
eNB_stats
[
CC_id
].
dlsch_pdus_tx
+=
1
;
eNB_UE_stats
->
rbs_used
=
nb_rb
;
eNB_UE_stats
->
num_mac_sdu_tx
=
num_sdus
;
eNB_UE_stats
->
total_rbs_used
+=
nb_rb
;
eNB_UE_stats
->
dlsch_mcs2
=
mcs
;
eNB_UE_stats
->
TBS
=
TBS
;
eNB_UE_stats
->
overhead_bytes
=
TBS
-
sdu_length_total
;
eNB_UE_stats
->
total_sdu_bytes
+=
sdu_length_total
;
eNB_UE_stats
->
total_pdu_bytes
+=
TBS
;
eNB_UE_stats
->
total_num_pdus
+=
1
;
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
// TDD
ue_template
->
DAI
++
;
update_ul_dci
(
module_idP
,
CC_id
,
rnti
,
ue_template
->
DAI
,
subframeP
);
}
j
++
;
// do PUCCH power control
// this is the snr
// unit is not dBm, it's special from nfapi
// converting to dBm
snr
=
(
5
*
ue_sched_ctrl
->
pucch1_snr
[
CC_id
]
-
640
)
/
10
;
target_snr
=
eNB
->
puCch10xSnr
/
10
;
// 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
->
pucch_tpc_tx_frame
*
10
+
ue_template
->
pucch_tpc_tx_subframe
;
if
(
framex10psubframe
+
10
<=
(
frameP
*
10
)
+
subframeP
||
//normal case
(
framex10psubframe
>
(
frameP
*
10
)
+
subframeP
&&
10240
-
framex10psubframe
+
(
frameP
*
10
)
+
subframeP
>=
10
))
//frame wrap-around
if
(
ue_sched_ctrl
->
pucch1_cqi_update
[
CC_id
]
==
1
)
{
ue_sched_ctrl
->
pucch1_cqi_update
[
CC_id
]
=
0
;
ue_template
->
pucch_tpc_tx_frame
=
frameP
;
ue_template
->
pucch_tpc_tx_subframe
=
subframeP
;
if
(
snr
>
target_snr
+
4
)
{
tpc
=
0
;
//-1
}
else
if
(
snr
<
target_snr
-
4
)
{
tpc
=
2
;
//+1
}
else
{
tpc
=
1
;
//0
}
}
// decrease mcs until TBS falls below required length
while
((
TBS
>
sdu_length_total
+
header_length_total
+
ta_len
)
&&
(
mcs
>
0
))
{
mcs
--
;
TBS
=
get_TBS_DL
(
mcs
,
nb_rb
);
}
// if we have decreased too much or we don't have enough RBs, increase MCS
while
(
TBS
<
sdu_length_total
+
header_length_total
+
ta_len
&&
((
ue_sched_ctrl
->
dl_pow_off
[
CC_id
]
>
0
&&
mcs
<
28
)
||
(
ue_sched_ctrl
->
dl_pow_off
[
CC_id
]
==
0
&&
mcs
<=
15
)))
{
mcs
++
;
TBS
=
get_TBS_DL
(
mcs
,
nb_rb
);
}
LOG_D
(
MAC
,
"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d (normal case)
\n
"
,
module_idP
,
frameP
,
subframeP
,
harq_pid
,
tpc
,
snr
,
target_snr
);
}
// Po_PUCCH has been updated
else
{
tpc
=
1
;
//0
}
// time to do TPC update
else
{
tpc
=
1
;
//0
}
LOG_D
(
MAC
,
"dlsch_mcs before and after the rate matching = (%d, %d)
\n
"
,
eNB_UE_stats
->
dlsch_mcs1
,
dl_config_pdu
=
&
dl_req
->
dl_config_pdu_list
[
dl_req
->
number_pdu
];
memset
((
void
*
)
dl_config_pdu
,
0
,
sizeof
(
nfapi_dl_config_request_pdu_t
));
dl_config_pdu
->
pdu_type
=
NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE
;
dl_config_pdu
->
pdu_size
=
(
uint8_t
)
(
2
+
sizeof
(
nfapi_dl_config_dci_dl_pdu
));
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
dci_format
=
NFAPI_DL_DCI_FORMAT_1
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
aggregation_level
=
get_aggregation
(
get_bw_index
(
module_idP
,
CC_id
),
ue_sched_ctrl
->
dl_cqi
[
CC_id
],
format1
);
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
tl
.
tag
=
NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
rnti
=
rnti
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
rnti_type
=
1
;
// CRNTI : see Table 4-10 from SCF082 - nFAPI specifications
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
transmission_power
=
6000
;
// equal to RS power
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
harq_process
=
harq_pid
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
tpc
=
tpc
;
// dont adjust power when retransmitting
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
new_data_indicator_1
=
1
-
ue_template
->
oldNDI
[
harq_pid
];
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
mcs_1
=
mcs
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
redundancy_version_1
=
0
;
//deactivate second codeword
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
mcs_2
=
0
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
redundancy_version_2
=
1
;
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
//TDD
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
downlink_assignment_index
=
(
ue_template
->
DAI
-
1
)
&
3
;
LOG_D
(
MAC
,
"[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d
\n
"
,
module_idP
,
CC_id
,
harq_pid
,
(
ue_template
->
DAI
-
1
),
mcs
);
#ifdef DEBUG_eNB_SCHEDULER
LOG_D
(
MAC
,
"[eNB %d]
CC_id %d Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)
\n
"
,
}
else
{
LOG_D
(
MAC
,
"[eNB %d]
Initial transmission CC_id %d : harq_pid %d, mcs %d
\n
"
,
module_idP
,
CC_id
,
mcs
,
TBS
,
nb_rb
);
// msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n",
// TBS, sdu_length_total, offset, TBS-sdu_length_total-offset);
#endif
if
(
TBS
-
header_length_total
-
sdu_length_total
-
ta_len
<=
2
)
{
padding
=
TBS
-
header_length_total
-
sdu_length_total
-
ta_len
;
post_padding
=
0
;
}
else
{
padding
=
0
;
post_padding
=
1
;
}
offset
=
generate_dlsch_header
((
unsigned
char
*
)
UE_list
->
DLSCH_pdu
[
CC_id
][
0
][
UE_id
].
payload
[
0
],
num_sdus
,
//num_sdus
sdu_lengths
,
//
sdu_lcids
,
255
,
// no drx
ta_update
,
// timing advance
NULL
,
// contention res id
padding
,
post_padding
);
//#ifdef DEBUG_eNB_SCHEDULER
if
(
ta_update
!=
31
)
{
LOG_D
(
MAC
,
"[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_length %d
\n
"
,
module_idP
,
frameP
,
UE_id
,
CC_id
,
sdu_length_total
,
num_sdus
,
sdu_lengths
[
0
],
sdu_lcids
[
0
],
offset
,
ta_update
,
padding
,
post_padding
,
mcs
,
TBS
,
nb_rb
,
header_length_total
);
}
//#endif
#ifdef DEBUG_eNB_SCHEDULER
LOG_T
(
MAC
,
"[eNB %d] First 16 bytes of DLSCH :
\n
"
);
for
(
i
=
0
;
i
<
16
;
i
++
)
{
LOG_T
(
MAC
,
"%x."
,
dlsch_buffer
[
i
]);
}
LOG_T
(
MAC
,
"
\n
"
);
#endif
// cycle through SDUs and place in dlsch_buffer
dlsch_pdu
=
&
UE_list
->
DLSCH_pdu
[
CC_id
][
0
][
UE_id
];
memcpy
(
&
dlsch_pdu
->
payload
[
0
][
offset
],
dlsch_buffer
,
sdu_length_total
);
// memcpy(RC.mac[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]);
// fill remainder of DLSCH with 0
for
(
j
=
0
;
j
<
(
TBS
-
sdu_length_total
-
offset
);
j
++
)
{
dlsch_pdu
->
payload
[
0
][
offset
+
sdu_length_total
+
j
]
=
0
;
}
trace_pdu
(
DIRECTION_DOWNLINK
,
(
uint8_t
*
)
dlsch_pdu
->
payload
[
0
],
TBS
,
module_idP
,
WS_C_RNTI
,
UE_RNTI
(
module_idP
,
UE_id
),
eNB
->
frame
,
eNB
->
subframe
,
0
,
0
);
T
(
T_ENB_MAC_UE_DL_PDU_WITH_DATA
,
T_INT
(
module_idP
),
T_INT
(
CC_id
),
T_INT
(
rnti
),
T_INT
(
frameP
),
T_INT
(
subframeP
),
T_INT
(
harq_pid
),
T_BUFFER
(
dlsch_pdu
->
payload
[
0
],
TBS
));
ue_template
->
nb_rb
[
harq_pid
]
=
nb_rb
;
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
S_DL_SCHEDULED
,
rnti
);
// store stats
eNB
->
eNB_stats
[
CC_id
].
dlsch_bytes_tx
+=
sdu_length_total
;
eNB
->
eNB_stats
[
CC_id
].
dlsch_pdus_tx
+=
1
;
eNB_UE_stats
->
rbs_used
=
nb_rb
;
eNB_UE_stats
->
num_mac_sdu_tx
=
num_sdus
;
eNB_UE_stats
->
total_rbs_used
+=
nb_rb
;
eNB_UE_stats
->
dlsch_mcs2
=
mcs
;
eNB_UE_stats
->
TBS
=
TBS
;
eNB_UE_stats
->
overhead_bytes
=
TBS
-
sdu_length_total
;
eNB_UE_stats
->
total_sdu_bytes
+=
sdu_length_total
;
eNB_UE_stats
->
total_pdu_bytes
+=
TBS
;
eNB_UE_stats
->
total_num_pdus
+=
1
;
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
// TDD
ue_template
->
DAI
++
;
update_ul_dci
(
module_idP
,
CC_id
,
rnti
,
ue_template
->
DAI
,
subframeP
);
}
// do PUCCH power control
// this is the snr
// unit is not dBm, it's special from nfapi
// converting to dBm
snr
=
(
5
*
ue_sched_ctrl
->
pucch1_snr
[
CC_id
]
-
640
)
/
10
;
target_snr
=
eNB
->
puCch10xSnr
/
10
;
// 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
->
pucch_tpc_tx_frame
*
10
+
ue_template
->
pucch_tpc_tx_subframe
;
if
(
framex10psubframe
+
10
<=
(
frameP
*
10
)
+
subframeP
||
//normal case
(
framex10psubframe
>
(
frameP
*
10
)
+
subframeP
&&
10240
-
framex10psubframe
+
(
frameP
*
10
)
+
subframeP
>=
10
))
//frame wrap-around
if
(
ue_sched_ctrl
->
pucch1_cqi_update
[
CC_id
]
==
1
)
{
ue_sched_ctrl
->
pucch1_cqi_update
[
CC_id
]
=
0
;
ue_template
->
pucch_tpc_tx_frame
=
frameP
;
ue_template
->
pucch_tpc_tx_subframe
=
subframeP
;
harq_pid
,
mcs
);
}
if
(
snr
>
target_snr
+
4
)
{
tpc
=
0
;
//-1
}
else
if
(
snr
<
target_snr
-
4
)
{
tpc
=
2
;
//+1
}
else
{
tpc
=
1
;
//0
}
LOG_D
(
MAC
,
"Checking feasibility pdu %d (new sdu)
\n
"
,
dl_req
->
number_pdu
);
LOG_D
(
MAC
,
"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d (normal case)
\n
"
,
module_idP
,
frameP
,
subframeP
,
harq_pid
,
tpc
,
snr
,
target_snr
);
}
// Po_PUCCH has been updated
else
{
tpc
=
1
;
//0
}
// time to do TPC update
else
{
tpc
=
1
;
//0
}
if
(
!
CCE_allocation_infeasible
(
module_idP
,
CC_id
,
1
,
subframeP
,
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
aggregation_level
,
rnti
))
{
ue_sched_ctrl
->
round
[
CC_id
][
harq_pid
]
=
0
;
dl_req
->
number_dci
++
;
dl_req
->
number_pdu
++
;
dl_req
->
tl
.
tag
=
NFAPI_DL_CONFIG_REQUEST_BODY_TAG
;
eNB
->
DL_req
[
CC_id
].
sfn_sf
=
frameP
<<
4
|
subframeP
;
eNB
->
DL_req
[
CC_id
].
header
.
message_id
=
NFAPI_DL_CONFIG_REQUEST
;
/* CDRX */
ue_sched_ctrl
->
harq_rtt_timer
[
CC_id
][
harq_pid
]
=
1
;
// restart HARQ RTT timer
dl_config_pdu
=
&
dl_req
->
dl_config_pdu_list
[
dl_req
->
number_pdu
];
memset
((
void
*
)
dl_config_pdu
,
0
,
sizeof
(
nfapi_dl_config_request_pdu_t
));
dl_config_pdu
->
pdu_type
=
NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE
;
dl_config_pdu
->
pdu_size
=
(
uint8_t
)
(
2
+
sizeof
(
nfapi_dl_config_dci_dl_pdu
));
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
dci_format
=
NFAPI_DL_DCI_FORMAT_1
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
aggregation_level
=
get_aggregation
(
get_bw_index
(
module_idP
,
CC_id
),
ue_sched_ctrl
->
dl_cqi
[
CC_id
],
format1
);
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
tl
.
tag
=
NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
rnti
=
rnti
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
rnti_type
=
1
;
// CRNTI : see Table 4-10 from SCF082 - nFAPI specifications
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
transmission_power
=
6000
;
// equal to RS power
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
harq_process
=
harq_pid
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
tpc
=
tpc
;
// dont adjust power when retransmitting
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
new_data_indicator_1
=
1
-
ue_template
->
oldNDI
[
harq_pid
];
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
mcs_1
=
mcs
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
redundancy_version_1
=
0
;
//deactivate second codeword
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
mcs_2
=
0
;
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
redundancy_version_2
=
1
;
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
//TDD
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
downlink_assignment_index
=
(
ue_template
->
DAI
-
1
)
&
3
;
LOG_D
(
MAC
,
"[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d
\n
"
,
module_idP
,
CC_id
,
harq_pid
,
(
ue_template
->
DAI
-
1
),
mcs
);
}
else
{
LOG_D
(
MAC
,
"[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d
\n
"
,
module_idP
,
CC_id
,
harq_pid
,
mcs
);
}
if
(
ue_sched_ctrl
->
cdrx_configured
)
{
ue_sched_ctrl
->
drx_inactivity_timer
=
1
;
// restart drx inactivity timer when new transmission
ue_sched_ctrl
->
drx_retransmission_timer
[
harq_pid
]
=
0
;
// stop drx retransmission
/*
* Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop.
*/
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY
,
(
unsigned
long
)
ue_sched_ctrl
->
drx_inactivity_timer
);
LOG_D
(
MAC
,
"Checking feasibility pdu %d (new sdu)
\n
"
,
dl_req
->
number_pdu
);
if
(
!
CCE_allocation_infeasible
(
module_idP
,
CC_id
,
1
,
subframeP
,
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
aggregation_level
,
rnti
))
{
ue_sched_ctrl
->
round
[
CC_id
][
harq_pid
]
=
0
;
dl_req
->
number_dci
++
;
dl_req
->
number_pdu
++
;
dl_req
->
tl
.
tag
=
NFAPI_DL_CONFIG_REQUEST_BODY_TAG
;
eNB
->
DL_req
[
CC_id
].
sfn_sf
=
frameP
<<
4
|
subframeP
;
eNB
->
DL_req
[
CC_id
].
header
.
message_id
=
NFAPI_DL_CONFIG_REQUEST
;
/* CDRX */
ue_sched_ctrl
->
harq_rtt_timer
[
CC_id
][
harq_pid
]
=
1
;
// restart HARQ RTT timer
if
(
ue_sched_ctrl
->
cdrx_configured
)
{
ue_sched_ctrl
->
drx_inactivity_timer
=
1
;
// restart drx inactivity timer when new transmission
ue_sched_ctrl
->
drx_retransmission_timer
[
harq_pid
]
=
0
;
// stop drx retransmission
/*
* Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop.
*/
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY
,
(
unsigned
long
)
ue_sched_ctrl
->
drx_inactivity_timer
);
if
(
harq_pid
==
0
)
{
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0
,
(
unsigned
long
)
ue_sched_ctrl
->
drx_retransmission_timer
[
0
]);
}
if
(
harq_pid
==
0
)
{
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
(
VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0
,
(
unsigned
long
)
ue_sched_ctrl
->
drx_retransmission_timer
[
0
]);
}
// Toggle NDI for next time
LOG_D
(
MAC
,
"CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d
\n
"
,
CC_id
,
frameP
,
subframeP
,
UE_id
,
rnti
,
harq_pid
,
ue_template
->
oldNDI
[
harq_pid
]);
ue_template
->
oldNDI
[
harq_pid
]
=
1
-
ue_template
->
oldNDI
[
harq_pid
];
ue_template
->
oldmcs1
[
harq_pid
]
=
mcs
;
ue_template
->
oldmcs2
[
harq_pid
]
=
0
;
AssertFatal
(
ue_template
->
physicalConfigDedicated
!=
NULL
,
"physicalConfigDedicated is NULL
\n
"
);
AssertFatal
(
ue_template
->
physicalConfigDedicated
->
pdsch_ConfigDedicated
!=
NULL
,
"physicalConfigDedicated->pdsch_ConfigDedicated is NULL
\n
"
);
fill_nfapi_dlsch_config
(
eNB
,
dl_req
,
TBS
,
eNB
->
pdu_index
[
CC_id
],
rnti
,
0
,
// type 0 allocation from 7.1.6 in 36.213
0
,
// virtual_resource_block_assignment_flag, unused here
0
,
// resource_block_coding, to be filled in later
getQm
(
mcs
),
0
,
// redundancy version
1
,
// transport blocks
0
,
// transport block to codeword swap flag
cc
[
CC_id
].
p_eNB
==
1
?
0
:
1
,
// transmission_scheme
1
,
// number of layers
1
,
// number of subbands
// uint8_t codebook_index,
4
,
// UE category capacity
ue_template
->
physicalConfigDedicated
->
pdsch_ConfigDedicated
->
p_a
,
0
,
// delta_power_offset for TM5
0
,
// ngap
0
,
// nprb
cc
[
CC_id
].
p_eNB
==
1
?
1
:
2
,
// transmission mode
0
,
//number of PRBs treated as one subband, not used here
0
);
// number of beamforming vectors, not used here
eNB
->
TX_req
[
CC_id
].
sfn_sf
=
fill_nfapi_tx_req
(
&
eNB
->
TX_req
[
CC_id
].
tx_request_body
,
(
frameP
*
10
)
+
subframeP
,
TBS
,
eNB
->
pdu_index
[
CC_id
],
dlsch_pdu
->
payload
[
0
]);
LOG_D
(
MAC
,
"Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU
\n
"
,
eNB
->
pdu_index
[
CC_id
]);
eNB
->
pdu_index
[
CC_id
]
++
;
program_dlsch_acknak
(
module_idP
,
CC_id
,
UE_id
,
frameP
,
subframeP
,
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
cce_idx
);
}
else
{
LOG_W
(
MAC
,
"Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations
\n
"
,
frameP
,
subframeP
,
UE_id
,
rnti
);
}
}
else
{
// There is no data from RLC or MAC header, so don't schedule
// Toggle NDI for next time
LOG_D
(
MAC
,
"CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d
\n
"
,
CC_id
,
frameP
,
subframeP
,
UE_id
,
rnti
,
harq_pid
,
ue_template
->
oldNDI
[
harq_pid
]);
ue_template
->
oldNDI
[
harq_pid
]
=
1
-
ue_template
->
oldNDI
[
harq_pid
];
ue_template
->
oldmcs1
[
harq_pid
]
=
mcs
;
ue_template
->
oldmcs2
[
harq_pid
]
=
0
;
AssertFatal
(
ue_template
->
physicalConfigDedicated
!=
NULL
,
"physicalConfigDedicated is NULL
\n
"
);
AssertFatal
(
ue_template
->
physicalConfigDedicated
->
pdsch_ConfigDedicated
!=
NULL
,
"physicalConfigDedicated->pdsch_ConfigDedicated is NULL
\n
"
);
fill_nfapi_dlsch_config
(
eNB
,
dl_req
,
TBS
,
eNB
->
pdu_index
[
CC_id
],
rnti
,
0
,
// type 0 allocation from 7.1.6 in 36.213
0
,
// virtual_resource_block_assignment_flag, unused here
0
,
// resource_block_coding, to be filled in later
getQm
(
mcs
),
0
,
// redundancy version
1
,
// transport blocks
0
,
// transport block to codeword swap flag
cc
[
CC_id
].
p_eNB
==
1
?
0
:
1
,
// transmission_scheme
1
,
// number of layers
1
,
// number of subbands
// uint8_t codebook_index,
4
,
// UE category capacity
ue_template
->
physicalConfigDedicated
->
pdsch_ConfigDedicated
->
p_a
,
0
,
// delta_power_offset for TM5
0
,
// ngap
0
,
// nprb
cc
[
CC_id
].
p_eNB
==
1
?
1
:
2
,
// transmission mode
0
,
//number of PRBs treated as one subband, not used here
0
);
// number of beamforming vectors, not used here
eNB
->
TX_req
[
CC_id
].
sfn_sf
=
fill_nfapi_tx_req
(
&
eNB
->
TX_req
[
CC_id
].
tx_request_body
,
(
frameP
*
10
)
+
subframeP
,
TBS
,
eNB
->
pdu_index
[
CC_id
],
dlsch_pdu
->
payload
[
0
]);
LOG_D
(
MAC
,
"Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU
\n
"
,
eNB
->
pdu_index
[
CC_id
]);
eNB
->
pdu_index
[
CC_id
]
++
;
program_dlsch_acknak
(
module_idP
,
CC_id
,
UE_id
,
frameP
,
subframeP
,
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
cce_idx
);
}
else
{
LOG_W
(
MAC
,
"Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations
\n
"
,
frameP
,
subframeP
,
UE_id
,
rnti
);
}
}
else
{
// There is no data from RLC or MAC header, so don't schedule
}
}
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
// TDD
set_ul_DAI
(
module_idP
,
UE_id
,
CC_id
,
frameP
,
subframeP
);
}
}
// UE_id loop
}
// CC_id loop
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
// TDD
set_ul_DAI
(
module_idP
,
UE_id
,
CC_id
,
frameP
,
subframeP
);
}
}
// UE_id loop
fill_DLSCH_dci
(
module_idP
,
frameP
,
...
...
openair2/LAYER2/MAC/mac_proto.h
View file @
99301f43
...
...
@@ -156,8 +156,11 @@ void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,i
void
schedule_dlsch
(
module_id_t
module_idP
,
frame_t
frameP
,
sub_frame_t
subframe
,
int
*
mbsfn_flag
);
void
schedule_ue_spec
(
module_id_t
module_idP
,
int
slice_idxP
,
frame_t
frameP
,
sub_frame_t
subframe
,
int
*
mbsfn_flag
);
void
schedule_ue_spec
(
module_id_t
module_idP
,
int
CC_id
,
frame_t
frameP
,
sub_frame_t
subframe
,
int
*
mbsfn_flag
);
void
schedule_ue_spec_br
(
module_id_t
module_idP
,
frame_t
frameP
,
sub_frame_t
subframeP
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment