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
zzha zzha
OpenXG-RAN
Commits
151873e9
Commit
151873e9
authored
Jan 18, 2019
by
Stefan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
pre_processor improvements
parent
bf25aba2
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
3031 additions
and
2802 deletions
+3031
-2802
openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
+160
-106
openair2/LAYER2/MAC/eNB_scheduler_fairRR.c
openair2/LAYER2/MAC/eNB_scheduler_fairRR.c
+17
-9
openair2/LAYER2/MAC/eNB_scheduler_primitives.c
openair2/LAYER2/MAC/eNB_scheduler_primitives.c
+2782
-2635
openair2/LAYER2/MAC/mac_proto.h
openair2/LAYER2/MAC/mac_proto.h
+4
-4
openair2/LAYER2/MAC/pre_processor.c
openair2/LAYER2/MAC/pre_processor.c
+68
-48
No files found.
openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
View file @
151873e9
...
@@ -70,12 +70,14 @@ extern uint8_t nfapi_mode;
...
@@ -70,12 +70,14 @@ extern uint8_t nfapi_mode;
void
void
add_ue_dlsch_info
(
module_id_t
module_idP
,
add_ue_dlsch_info
(
module_id_t
module_idP
,
int
CC_id
,
int
CC_id
,
int
UE_id
,
sub_frame_t
subframeP
,
UE_DLSCH_STATUS
status
)
int
UE_id
,
sub_frame_t
subframeP
,
UE_DLSCH_STATUS
status
,
rnti_t
rnti
)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
{
{
//LOG_D(MAC, "%s(module_idP:%d, CC_id:%d, UE_id:%d, subframeP:%d, status:%d) serving_num:%d rnti:%x\n", __FUNCTION__, module_idP, CC_id, UE_id, subframeP, status, eNB_dlsch_info[module_idP][CC_id][UE_id].serving_num, UE_RNTI(module_idP,UE_id));
//LOG_D(MAC, "%s(module_idP:%d, CC_id:%d, UE_id:%d, subframeP:%d, status:%d) serving_num:%d rnti:%x\n", __FUNCTION__, module_idP, CC_id, UE_id, subframeP, status, eNB_dlsch_info[module_idP][CC_id][UE_id].serving_num, UE_RNTI(module_idP,UE_id));
eNB_dlsch_info
[
module_idP
][
CC_id
][
UE_id
].
rnti
=
eNB_dlsch_info
[
module_idP
][
CC_id
][
UE_id
].
rnti
=
rnti
;
UE_RNTI
(
module_idP
,
UE_id
);
// eNB_dlsch_info[module_idP][CC_id][ue_mod_idP].weight = weight;
// eNB_dlsch_info[module_idP][CC_id][ue_mod_idP].weight = weight;
eNB_dlsch_info
[
module_idP
][
CC_id
][
UE_id
].
subframe
=
subframeP
;
eNB_dlsch_info
[
module_idP
][
CC_id
][
UE_id
].
subframe
=
subframeP
;
eNB_dlsch_info
[
module_idP
][
CC_id
][
UE_id
].
status
=
status
;
eNB_dlsch_info
[
module_idP
][
CC_id
][
UE_id
].
status
=
status
;
...
@@ -301,7 +303,10 @@ generate_dlsch_header(unsigned char *mac_header,
...
@@ -301,7 +303,10 @@ generate_dlsch_header(unsigned char *mac_header,
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
void
set_ul_DAI
(
int
module_idP
,
int
UE_idP
,
int
CC_idP
,
int
frameP
,
set_ul_DAI
(
int
module_idP
,
int
UE_idP
,
int
CC_idP
,
int
frameP
,
int
subframeP
)
int
subframeP
)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
{
{
...
@@ -312,9 +317,13 @@ set_ul_DAI(int module_idP, int UE_idP, int CC_idP, int frameP,
...
@@ -312,9 +317,13 @@ set_ul_DAI(int module_idP, int UE_idP, int CC_idP, int frameP,
if
(
cc
->
tdd_Config
!=
NULL
)
{
//TDD
if
(
cc
->
tdd_Config
!=
NULL
)
{
//TDD
DAI
=
(
UE_list
->
UE_template
[
CC_idP
][
UE_idP
].
DAI
-
1
)
&
3
;
DAI
=
(
UE_list
->
UE_template
[
CC_idP
][
UE_idP
].
DAI
-
1
)
&
3
;
LOG_D
(
MAC
,
LOG_D
(
MAC
,
"[eNB %d] CC_id %d Frame %d, subframe %d: DAI %d for UE %d
\n
"
,
"[eNB %d] CC_id %d Frame %d, subframe %d: DAI %d for UE %d
\n
"
,
module_idP
,
module_idP
,
CC_idP
,
frameP
,
subframeP
,
DAI
,
UE_idP
);
CC_idP
,
frameP
,
subframeP
,
DAI
,
UE_idP
);
// Save DAI for Format 0 DCI
// Save DAI for Format 0 DCI
switch
(
cc
->
tdd_Config
->
subframeAssignment
)
{
switch
(
cc
->
tdd_Config
->
subframeAssignment
)
{
...
@@ -398,6 +407,8 @@ set_ul_DAI(int module_idP, int UE_idP, int CC_idP, int frameP,
...
@@ -398,6 +407,8 @@ set_ul_DAI(int module_idP, int UE_idP, int CC_idP, int frameP,
break
;
break
;
}
}
}
}
return
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -417,8 +428,11 @@ schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, in
...
@@ -417,8 +428,11 @@ schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, in
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
void
schedule_ue_spec
(
module_id_t
module_idP
,
int
slice_idxP
,
schedule_ue_spec
(
module_id_t
module_idP
,
frame_t
frameP
,
sub_frame_t
subframeP
,
int
*
mbsfn_flag
)
int
slice_idxP
,
frame_t
frameP
,
sub_frame_t
subframeP
,
int
*
mbsfn_flag
)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
{
{
int
CC_id
;
int
CC_id
;
...
@@ -430,7 +444,8 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -430,7 +444,8 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
int
lcid
,
offset
,
num_sdus
=
0
;
int
lcid
,
offset
,
num_sdus
=
0
;
int
nb_rb
,
nb_rb_temp
,
nb_available_rb
;
int
nb_rb
,
nb_rb_temp
,
nb_available_rb
;
uint16_t
sdu_lengths
[
NB_RB_MAX
];
uint16_t
sdu_lengths
[
NB_RB_MAX
];
int
TBS
,
j
,
rnti
,
padding
=
0
,
post_padding
=
0
;
int
TBS
,
j
,
padding
=
0
,
post_padding
=
0
;
rnti_t
rnti
;
unsigned
char
dlsch_buffer
[
MAX_DLSCH_PAYLOAD_BYTES
];
unsigned
char
dlsch_buffer
[
MAX_DLSCH_PAYLOAD_BYTES
];
int
round
=
0
;
int
round
=
0
;
int
harq_pid
=
0
;
int
harq_pid
=
0
;
...
@@ -469,22 +484,17 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -469,22 +484,17 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
break
;
break
;
case
1
:
case
1
:
return
;
break
;
case
2
:
case
2
:
return
;
return
;
break
;
case
3
:
case
3
:
if
(
(
tdd_sfa
!=
2
)
&&
(
tdd_sfa
!=
5
)
)
if
(
tdd_sfa
!=
2
&&
tdd_sfa
!=
5
)
return
;
return
;
break
;
break
;
case
4
:
case
4
:
if
((
tdd_sfa
!=
1
)
&&
(
tdd_sfa
!=
2
)
&&
(
tdd_sfa
!=
4
)
if
(
tdd_sfa
!=
1
&&
tdd_sfa
!=
2
&&
tdd_sfa
!=
4
&&
tdd_sfa
!=
5
)
&&
(
tdd_sfa
!=
5
))
return
;
return
;
break
;
break
;
...
@@ -494,14 +504,13 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -494,14 +504,13 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
case
6
:
case
6
:
case
7
:
case
7
:
if
(
(
tdd_sfa
!=
3
)
&&
(
tdd_sfa
!=
4
)
&&
(
tdd_sfa
!=
5
)
)
if
(
tdd_sfa
!=
3
&&
tdd_sfa
!=
4
&&
tdd_sfa
!=
5
)
return
;
return
;
break
;
break
;
case
8
:
case
8
:
if
((
tdd_sfa
!=
2
)
&&
(
tdd_sfa
!=
3
)
&&
(
tdd_sfa
!=
4
)
if
(
tdd_sfa
!=
2
&&
tdd_sfa
!=
3
&&
tdd_sfa
!=
4
&&
tdd_sfa
!=
5
)
&&
(
tdd_sfa
!=
5
))
return
;
return
;
break
;
break
;
...
@@ -558,43 +567,55 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -558,43 +567,55 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
//}
//}
if
(
RC
.
mac
[
module_idP
]
->
slice_info
.
interslice_share_active
)
{
if
(
RC
.
mac
[
module_idP
]
->
slice_info
.
interslice_share_active
)
{
dlsch_scheduler_interslice_multiplexing
(
module_idP
,
frameP
,
subframeP
,
eNB
->
slice_info
.
rballoc_sub
);
dlsch_scheduler_interslice_multiplexing
(
module_idP
,
frameP
,
subframeP
,
eNB
->
slice_info
.
rballoc_sub
);
/* the interslice multiplexing re-sorts the UE_list for the slices it tries
/* 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 */
* to multiplex, so we need to sort it for the current slice again */
sort_UEs
(
module_idP
,
slice_idxP
,
frameP
,
subframeP
);
sort_UEs
(
module_idP
,
slice_idxP
,
frameP
,
subframeP
);
}
}
for
(
CC_id
=
0
;
CC_id
<
RC
.
nb_mac_CC
[
module_idP
];
CC_id
++
)
{
for
(
CC_id
=
0
;
CC_id
<
RC
.
nb_mac_CC
[
module_idP
];
CC_id
++
)
{
LOG_D
(
MAC
,
"doing schedule_ue_spec for CC_id %d
\n
"
,
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
;
dl_req
=
&
eNB
->
DL_req
[
CC_id
].
dl_config_request_body
;
if
(
mbsfn_flag
[
CC_id
]
>
0
)
if
(
mbsfn_flag
[
CC_id
]
>
0
)
continue
;
continue
;
for
(
UE_id
=
UE_list
->
head
;
UE_id
>=
0
;
UE_id
=
UE_list
->
next
[
UE_id
])
{
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
);
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
continue_flag
=
0
;
// reset the flag to allow allocation for the remaining UEs
rnti
=
UE_RNTI
(
module_idP
,
UE_id
);
rnti
=
UE_RNTI
(
module_idP
,
UE_id
);
eNB_UE_stats
=
&
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
];
eNB_UE_stats
=
&
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
];
ue_sched_ctl
=
&
UE_list
->
UE_sched_ctrl
[
UE_id
];
ue_sched_ctl
=
&
UE_list
->
UE_sched_ctrl
[
UE_id
];
/*
if (rnti == NOT_A_RNTI) {
if (rnti == NOT_A_RNTI) {
LOG_D(MAC, "Cannot find rnti for UE_id %d (num_UEs %d)\n", UE_id, UE_list->num_UEs);
LOG_D(MAC, "Cannot find rnti for UE_id %d (num_UEs %d)\n", UE_id, UE_list->num_UEs);
continue_flag = 1;
continue_flag = 1;
}
}
*/
if
(
eNB_UE_stats
==
NULL
)
{
if
(
eNB_UE_stats
==
NULL
)
{
LOG_D
(
MAC
,
"[eNB] Cannot find eNB_UE_stats
\n
"
);
LOG_D
(
MAC
,
"[eNB] Cannot find eNB_UE_stats
\n
"
);
continue_flag
=
1
;
continue_flag
=
1
;
}
}
if
(
!
ue_dl_slice_membership
(
module_idP
,
UE_id
,
slice_idxP
))
{
// if (!ue_dl_slice_membership(module_idP, UE_id, slice_idxP)) {
LOG_D
(
MAC
,
"UE%d is not part of slice %d ID %d
\n
"
,
// LOG_D(MAC, "UE%d is not part of slice %d ID %d\n",
UE_id
,
slice_idxP
,
RC
.
mac
[
module_idP
]
->
slice_info
.
dl
[
slice_idxP
].
id
);
// UE_id,
/* prevent execution of add_ue_dlsch_info(), it is done by the other
// slice_idxP,
* slice */
// RC.mac[module_idP]->slice_info.dl[slice_idxP].id);
continue
;
// /* prevent execution of add_ue_dlsch_info(), it is done by the other
}
// * slice */
// continue;
// }
if
(
continue_flag
!=
1
)
{
if
(
continue_flag
!=
1
)
{
switch
(
get_tmode
(
module_idP
,
CC_id
,
UE_id
))
{
switch
(
get_tmode
(
module_idP
,
CC_id
,
UE_id
))
{
...
@@ -613,18 +634,21 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -613,18 +634,21 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
break
;
break
;
default:
default:
LOG_W
(
MAC
,
"Unsupported transmission mode %d
\n
"
,
get_tmode
(
module_idP
,
CC_id
,
UE_id
));
LOG_W
(
MAC
,
"Unsupported transmission mode %d
\n
"
,
get_tmode
(
module_idP
,
CC_id
,
UE_id
));
aggregation
=
2
;
aggregation
=
2
;
break
;
}
}
}
}
/* if (continue_flag != 1 */
/* if (continue_flag != 1 */
if
((
ue_sched_ctl
->
pre_nb_available_rbs
[
CC_id
]
==
0
)
||
// no RBs allocated
if
(
ue_sched_ctl
->
pre_nb_available_rbs
[
CC_id
]
==
0
||
// no RBs allocated
CCE_allocation_infeasible
(
module_idP
,
CC_id
,
1
,
subframeP
,
CCE_allocation_infeasible
(
module_idP
,
CC_id
,
1
,
subframeP
,
aggregation
,
rnti
))
{
aggregation
,
rnti
))
{
LOG_D
(
MAC
,
"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue
\n
"
,
LOG_D
(
MAC
,
module_idP
,
"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue
\n
"
,
frameP
,
module_idP
,
frameP
,
UE_id
,
CC_id
);
UE_id
,
CC_id
);
continue_flag
=
1
;
//to next user (there might be rbs availiable for other UEs in TM5
continue_flag
=
1
;
//to next user (there might be rbs availiable for other UEs in TM5
}
}
...
@@ -636,11 +660,20 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -636,11 +660,20 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
cc
[
CC_id
].
tdd_Config
->
subframeAssignment
,
cc
[
CC_id
].
tdd_Config
->
subframeAssignment
,
UE_list
);
UE_list
);
// update UL DAI after DLSCH scheduling
// update UL DAI after DLSCH scheduling
set_ul_DAI
(
module_idP
,
UE_id
,
CC_id
,
frameP
,
subframeP
);
set_ul_DAI
(
module_idP
,
UE_id
,
CC_id
,
frameP
,
subframeP
);
}
}
if
(
continue_flag
==
1
)
{
if
(
continue_flag
==
1
)
{
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
S_DL_NONE
);
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
S_DL_NONE
,
rnti
);
continue
;
continue
;
}
}
...
@@ -653,7 +686,8 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -653,7 +686,8 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
].
harq_round
=
round
;
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
].
harq_round
=
round
;
if
(
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
].
rrc_status
<
RRC_CONNECTED
)
{
if
(
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
].
rrc_status
<
RRC_CONNECTED
)
{
LOG_D
(
MAC
,
"UE %d is not in RRC_CONNECTED
\n
"
,
UE_id
);
LOG_D
(
MAC
,
"UE %d is not in RRC_CONNECTED
\n
"
,
UE_id
);
continue
;
continue
;
}
}
...
@@ -681,10 +715,15 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -681,10 +715,15 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
UE_list
->
UE_template
[
CC_id
][
UE_id
].
rballoc_subband
[
harq_pid
][
j
]
=
0
;
UE_list
->
UE_template
[
CC_id
][
UE_id
].
rballoc_subband
[
harq_pid
][
j
]
=
0
;
}
}
LOG_D
(
MAC
,
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
"
,
"[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
,
module_idP
,
frameP
,
UE_id
,
CC_id
,
rnti
,
harq_pid
,
round
,
frameP
,
UE_id
,
nb_available_rb
,
ue_sched_ctl
->
dl_cqi
[
CC_id
],
CC_id
,
rnti
,
harq_pid
,
round
,
nb_available_rb
,
ue_sched_ctl
->
dl_cqi
[
CC_id
],
eNB_UE_stats
->
dlsch_mcs1
,
eNB_UE_stats
->
dlsch_mcs1
,
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
].
rrc_status
);
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
].
rrc_status
);
...
@@ -697,11 +736,15 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -697,11 +736,15 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
if
(
nb_rb
<=
nb_available_rb
)
{
if
(
nb_rb
<=
nb_available_rb
)
{
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
++
;
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
++
;
update_ul_dci
(
module_idP
,
CC_id
,
rnti
,
update_ul_dci
(
module_idP
,
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
,
subframeP
);
CC_id
,
LOG_D
(
MAC
,
rnti
,
"DAI update: CC_id %d subframeP %d: UE %d, DAI %d
\n
"
,
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
,
CC_id
,
subframeP
,
UE_id
,
subframeP
);
LOG_D
(
MAC
,
"DAI update: CC_id %d subframeP %d: UE %d, DAI %d
\n
"
,
CC_id
,
subframeP
,
UE_id
,
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
);
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
);
}
}
...
@@ -716,18 +759,15 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -716,18 +759,15 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
while
((
nb_rb_temp
>
0
)
&&
(
j
<
N_RBG
[
CC_id
]))
{
while
((
nb_rb_temp
>
0
)
&&
(
j
<
N_RBG
[
CC_id
]))
{
if
(
ue_sched_ctl
->
rballoc_sub_UE
[
CC_id
][
j
]
==
1
)
{
if
(
ue_sched_ctl
->
rballoc_sub_UE
[
CC_id
][
j
]
==
1
)
{
if
(
UE_list
->
UE_template
[
CC_id
][
UE_id
].
rballoc_subband
[
harq_pid
][
j
])
if
(
UE_list
->
UE_template
[
CC_id
][
UE_id
].
rballoc_subband
[
harq_pid
][
j
])
printf
(
"WARN: rballoc_subband not free for retrans?
\n
"
);
LOG_W
(
MAC
,
"WARN: rballoc_subband not free for retrans?
\n
"
);
UE_list
->
UE_template
[
CC_id
][
UE_id
].
rballoc_subband
[
harq_pid
][
j
]
=
ue_sched_ctl
->
rballoc_sub_UE
[
CC_id
][
j
];
UE_list
->
UE_template
[
CC_id
][
UE_id
].
rballoc_subband
[
harq_pid
][
j
]
=
ue_sched_ctl
->
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
-=
min_rb_unit
[
CC_id
];
nb_rb_temp
=
nb_rb_temp
-
min_rb_unit
[
CC_id
]
+
1
;
if
((
j
==
N_RBG
[
CC_id
]
-
1
)
&&
(
N_RB_DL
[
CC_id
]
==
25
||
N_RB_DL
[
CC_id
]
==
50
))
}
else
{
nb_rb_temp
++
;
nb_rb_temp
=
nb_rb_temp
-
min_rb_unit
[
CC_id
];
}
}
}
j
++
;
j
=
j
+
1
;
}
}
}
}
...
@@ -746,7 +786,8 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -746,7 +786,8 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
case
2
:
case
2
:
case
7
:
case
7
:
default:
default:
LOG_D
(
MAC
,
"retransmission DL_REQ: rnti:%x
\n
"
,
rnti
);
LOG_D
(
MAC
,
"retransmission DL_REQ: rnti:%x
\n
"
,
rnti
);
dl_config_pdu
=
&
dl_req
->
dl_config_pdu_list
[
dl_req
->
number_pdu
];
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
));
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_type
=
NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE
;
...
@@ -768,30 +809,40 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -768,30 +809,40 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
// TDD
// TDD
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
if
(
cc
[
CC_id
].
tdd_Config
!=
NULL
)
{
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
downlink_assignment_index
=
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
downlink_assignment_index
=
(
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
-
1
)
&
3
;
(
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
-
1
)
&
3
;
LOG_D
(
MAC
,
"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d
\n
"
,
LOG_D
(
MAC
,
module_idP
,
"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d
\n
"
,
CC_id
,
module_idP
,
CC_id
,
harq_pid
,
round
,
harq_pid
,
(
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
-
1
),
round
,
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
-
1
,
UE_list
->
UE_template
[
CC_id
][
UE_id
].
oldmcs1
[
harq_pid
]);
UE_list
->
UE_template
[
CC_id
][
UE_id
].
oldmcs1
[
harq_pid
]);
}
else
{
}
else
{
LOG_D
(
MAC
,
LOG_D
(
MAC
,
"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d
\n
"
,
"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d
\n
"
,
module_idP
,
module_idP
,
CC_id
,
harq_pid
,
round
,
CC_id
,
harq_pid
,
round
,
UE_list
->
UE_template
[
CC_id
][
UE_id
].
oldmcs1
[
harq_pid
]);
UE_list
->
UE_template
[
CC_id
][
UE_id
].
oldmcs1
[
harq_pid
]);
}
}
if
(
!
CCE_allocation_infeasible
(
module_idP
,
CC_id
,
1
,
subframeP
,
if
(
!
CCE_allocation_infeasible
(
module_idP
,
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
aggregation_level
,
rnti
))
{
CC_id
,
1
,
subframeP
,
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
aggregation_level
,
rnti
))
{
dl_req
->
number_dci
++
;
dl_req
->
number_dci
++
;
dl_req
->
number_pdu
++
;
dl_req
->
number_pdu
++
;
dl_req
->
tl
.
tag
=
NFAPI_DL_CONFIG_REQUEST_BODY_TAG
;
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
].
sfn_sf
=
frameP
<<
4
|
subframeP
;
eNB
->
DL_req
[
CC_id
].
header
.
message_id
=
NFAPI_DL_CONFIG_REQUEST
;
eNB
->
DL_req
[
CC_id
].
header
.
message_id
=
NFAPI_DL_CONFIG_REQUEST
;
fill_nfapi_dlsch_config
(
eNB
,
dl_req
,
TBS
,
-
1
,
fill_nfapi_dlsch_config
(
eNB
,
/* retransmission, no pdu_index */
dl_req
,
rnti
,
0
,
// type 0 allocation from 7.1.6 in 36.213
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
,
// virtual_resource_block_assignment_flag, unused here
0
,
// resource_block_coding, to be filled in later
0
,
// resource_block_coding, to be filled in later
getQm
(
UE_list
->
UE_template
[
CC_id
][
UE_id
].
oldmcs1
[
harq_pid
]),
getQm
(
UE_list
->
UE_template
[
CC_id
][
UE_id
].
oldmcs1
[
harq_pid
]),
...
@@ -809,11 +860,11 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -809,11 +860,11 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
0
,
// nprb
0
,
// nprb
cc
[
CC_id
].
p_eNB
==
1
?
1
:
2
,
// transmission mode
cc
[
CC_id
].
p_eNB
==
1
?
1
:
2
,
// transmission mode
0
,
//number of PRBs treated as one subband, not used here
0
,
//number of PRBs treated as one subband, not used here
0
// number of beamforming vectors, not used here
0
);
// number of beamforming vectors, not used here
);
LOG_D
(
MAC
,
LOG_D
(
MAC
,
"Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d
\n
"
,
"Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d
\n
"
,
eNB
->
pdu_index
[
CC_id
],
eNB
->
pdu_index
[
CC_id
],
round
);
round
);
program_dlsch_acknak
(
module_idP
,
CC_id
,
UE_id
,
frameP
,
subframeP
,
program_dlsch_acknak
(
module_idP
,
CC_id
,
UE_id
,
frameP
,
subframeP
,
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
cce_idx
);
dl_config_pdu
->
dci_dl_pdu
.
dci_dl_pdu_rel8
.
cce_idx
);
// No TX request for retransmission (check if null request for FAPI)
// No TX request for retransmission (check if null request for FAPI)
...
@@ -824,7 +875,7 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -824,7 +875,7 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
}
}
}
}
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
S_DL_SCHEDULED
);
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
S_DL_SCHEDULED
,
rnti
);
//eNB_UE_stats->dlsch_trials[round]++;
//eNB_UE_stats->dlsch_trials[round]++;
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
].
num_retransmission
+=
1
;
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
].
num_retransmission
+=
1
;
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
].
rbs_used_retx
=
nb_rb
;
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
].
rbs_used_retx
=
nb_rb
;
...
@@ -1084,6 +1135,7 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -1084,6 +1135,7 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
UE_list
->
UE_sched_ctrl
[
UE_id
].
uplane_inactivity_timer
=
0
;
UE_list
->
UE_sched_ctrl
[
UE_id
].
uplane_inactivity_timer
=
0
;
// reset RRC inactivity timer after uplane activity
// reset RRC inactivity timer after uplane activity
ue_contextP
=
rrc_eNB_get_ue_context
(
RC
.
rrc
[
module_idP
],
rnti
);
ue_contextP
=
rrc_eNB_get_ue_context
(
RC
.
rrc
[
module_idP
],
rnti
);
if
(
ue_contextP
!=
NULL
)
{
if
(
ue_contextP
!=
NULL
)
{
ue_contextP
->
ue_context
.
ue_rrc_inactivity_timer
=
1
;
ue_contextP
->
ue_context
.
ue_rrc_inactivity_timer
=
1
;
}
else
{
}
else
{
...
@@ -1245,7 +1297,7 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
...
@@ -1245,7 +1297,7 @@ schedule_ue_spec(module_id_t module_idP, int slice_idxP,
T_INT
(
subframeP
),
T_INT
(
harq_pid
),
T_INT
(
subframeP
),
T_INT
(
harq_pid
),
T_BUFFER
(
UE_list
->
DLSCH_pdu
[
CC_id
][
0
][
UE_id
].
payload
[
0
],
TBS
));
T_BUFFER
(
UE_list
->
DLSCH_pdu
[
CC_id
][
0
][
UE_id
].
payload
[
0
],
TBS
));
UE_list
->
UE_template
[
CC_id
][
UE_id
].
nb_rb
[
harq_pid
]
=
nb_rb
;
UE_list
->
UE_template
[
CC_id
][
UE_id
].
nb_rb
[
harq_pid
]
=
nb_rb
;
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
S_DL_SCHEDULED
);
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
S_DL_SCHEDULED
,
rnti
);
// store stats
// store stats
eNB
->
eNB_stats
[
CC_id
].
dlsch_bytes_tx
+=
sdu_length_total
;
eNB
->
eNB_stats
[
CC_id
].
dlsch_bytes_tx
+=
sdu_length_total
;
eNB
->
eNB_stats
[
CC_id
].
dlsch_pdus_tx
+=
1
;
eNB
->
eNB_stats
[
CC_id
].
dlsch_pdus_tx
+=
1
;
...
@@ -1717,68 +1769,68 @@ unsigned char *get_dlsch_sdu(module_id_t module_idP,
...
@@ -1717,68 +1769,68 @@ unsigned char *get_dlsch_sdu(module_id_t module_idP,
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
void
update_ul_dci
(
module_id_t
module_idP
,
update_ul_dci
(
module_id_t
module_idP
,
uint8_t
CC_idP
,
rnti_t
rntiP
,
uint8_t
daiP
,
sub_frame_t
subframe
)
uint8_t
CC_idP
,
rnti_t
rntiP
,
uint8_t
daiP
,
sub_frame_t
subframe
)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
{
{
nfapi_hi_dci0_request_t
*
HI_DCI0_req
=
eNB_MAC_INST
*
eNB
=
RC
.
mac
[
module_idP
];
&
RC
.
mac
[
module_idP
]
->
HI_DCI0_req
[
CC_idP
][
subframe
];
COMMON_channels_t
*
cc
=
&
eNB
->
common_channels
[
CC_idP
];
nfapi_hi_dci0_request_pdu_t
*
hi_dci0_pdu
=
&
HI_DCI0_req
->
hi_dci0_request_body
.
hi_dci0_pdu_list
[
0
];
COMMON_channels_t
*
cc
=
&
RC
.
mac
[
module_idP
]
->
common_channels
[
CC_idP
];
int
i
;
if
(
cc
->
tdd_Config
!=
NULL
)
{
// TDD
if
(
cc
->
tdd_Config
!=
NULL
)
{
// TDD
for
(
i
=
0
;
nfapi_hi_dci0_request_t
*
HI_DCI0_req
=
&
eNB
->
HI_DCI0_req
[
CC_idP
][
subframe
]
;
i
<
HI_DCI0_req
->
hi_dci0_request_body
.
number_of_dci
+
HI_DCI0_req
->
hi_dci0_request_body
.
number_of_hi
;
nfapi_hi_dci0_request_pdu_t
*
hi_dci0_pdu
=
&
HI_DCI0_req
->
hi_dci0_request_body
.
hi_dci0_pdu_list
[
0
]
;
i
++
)
{
int
limit
=
HI_DCI0_req
->
hi_dci0_request_body
.
number_of_dci
+
HI_DCI0_req
->
hi_dci0_request_body
.
number_of_hi
;
if
((
hi_dci0_pdu
[
i
].
pdu_type
==
NFAPI_HI_DCI0_DCI_PDU_TYPE
)
&&
for
(
int
i
=
0
;
i
<
limit
;
i
++
,
hi_dci0_pdu
++
)
{
(
hi_dci0_pdu
[
i
].
dci_pdu
.
dci_pdu_rel8
.
rnti
==
rntiP
)
)
if
(
hi_dci0_pdu
->
pdu_type
==
NFAPI_HI_DCI0_DCI_PDU_TYPE
&&
hi_dci0_pdu
->
dci_pdu
.
dci_pdu_rel8
.
rnti
==
rntiP
)
hi_dci0_pdu
[
i
].
dci_pdu
.
dci_pdu_rel8
.
dl_assignment_index
=
(
daiP
-
1
)
&
3
;
hi_dci0_pdu
->
dci_pdu
.
dci_pdu_rel8
.
dl_assignment_index
=
(
daiP
-
1
)
&
3
;
}
}
}
}
return
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
void
set_ue_dai
(
sub_frame_t
subframeP
,
set_ue_dai
(
sub_frame_t
subframeP
,
int
UE_id
,
uint8_t
CC_id
,
uint8_t
tdd_config
,
int
UE_id
,
uint8_t
CC_id
,
uint8_t
tdd_config
,
UE_list_t
*
UE_list
)
UE_list_t
*
UE_list
)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
{
{
switch
(
tdd_config
)
{
switch
(
tdd_config
)
{
case
0
:
case
0
:
if
((
subframeP
==
0
)
||
(
subframeP
==
1
)
||
(
subframeP
==
3
)
if
(
subframeP
==
0
||
subframeP
==
1
||
subframeP
==
3
||
subframeP
==
5
||
subframeP
==
6
||
subframeP
==
8
)
{
||
(
subframeP
==
5
)
||
(
subframeP
==
6
)
||
(
subframeP
==
8
))
{
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
}
}
break
;
break
;
case
1
:
case
1
:
if
((
subframeP
==
0
)
||
(
subframeP
==
4
)
||
(
subframeP
==
5
)
if
(
subframeP
==
0
||
subframeP
==
4
||
subframeP
==
5
||
subframeP
==
9
)
{
||
(
subframeP
==
9
))
{
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
}
}
break
;
break
;
case
2
:
case
2
:
if
(
(
subframeP
==
4
)
||
(
subframeP
==
5
)
)
{
if
(
subframeP
==
4
||
subframeP
==
5
)
{
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
}
}
break
;
break
;
case
3
:
case
3
:
if
(
(
subframeP
==
5
)
||
(
subframeP
==
7
)
||
(
subframeP
==
9
)
)
{
if
(
subframeP
==
5
||
subframeP
==
7
||
subframeP
==
9
)
{
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
}
}
break
;
break
;
case
4
:
case
4
:
if
(
(
subframeP
==
0
)
||
(
subframeP
==
6
)
)
{
if
(
subframeP
==
0
||
subframeP
==
6
)
{
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
}
}
...
@@ -1792,8 +1844,7 @@ set_ue_dai(sub_frame_t subframeP,
...
@@ -1792,8 +1844,7 @@ set_ue_dai(sub_frame_t subframeP,
break
;
break
;
case
6
:
case
6
:
if
((
subframeP
==
0
)
||
(
subframeP
==
1
)
||
(
subframeP
==
5
)
if
(
subframeP
==
0
||
subframeP
==
1
||
subframeP
==
5
||
subframeP
==
6
||
subframeP
==
9
)
{
||
(
subframeP
==
6
)
||
(
subframeP
==
9
))
{
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
}
}
...
@@ -1801,9 +1852,12 @@ set_ue_dai(sub_frame_t subframeP,
...
@@ -1801,9 +1852,12 @@ set_ue_dai(sub_frame_t subframeP,
default:
default:
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
UE_list
->
UE_template
[
CC_id
][
UE_id
].
DAI
=
0
;
LOG_I
(
MAC
,
"unknown TDD config %d
\n
"
,
tdd_config
);
LOG_I
(
MAC
,
"unknown TDD config %d
\n
"
,
tdd_config
);
break
;
break
;
}
}
return
;
}
}
void
schedule_PCH
(
module_id_t
module_idP
,
frame_t
frameP
,
sub_frame_t
subframeP
)
{
void
schedule_PCH
(
module_id_t
module_idP
,
frame_t
frameP
,
sub_frame_t
subframeP
)
{
...
...
openair2/LAYER2/MAC/eNB_scheduler_fairRR.c
View file @
151873e9
...
@@ -295,7 +295,8 @@ void dlsch_scheduler_pre_ue_select_fairRR(
...
@@ -295,7 +295,8 @@ void dlsch_scheduler_pre_ue_select_fairRR(
CC_id
,
CC_id
,
UE_id
,
UE_id
,
subframeP
,
subframeP
,
S_DL_NONE
);
S_DL_NONE
,
rnti
);
end_flag
[
CC_id
]
=
1
;
end_flag
[
CC_id
]
=
1
;
break
;
break
;
}
}
...
@@ -418,7 +419,8 @@ void dlsch_scheduler_pre_ue_select_fairRR(
...
@@ -418,7 +419,8 @@ void dlsch_scheduler_pre_ue_select_fairRR(
CC_id
,
CC_id
,
UE_id
,
UE_id
,
subframeP
,
subframeP
,
S_DL_NONE
);
S_DL_NONE
,
rnti
);
end_flag
[
CC_id
]
=
1
;
end_flag
[
CC_id
]
=
1
;
break
;
break
;
}
}
...
@@ -541,7 +543,8 @@ void dlsch_scheduler_pre_ue_select_fairRR(
...
@@ -541,7 +543,8 @@ void dlsch_scheduler_pre_ue_select_fairRR(
CC_id
,
CC_id
,
UE_id
,
UE_id
,
subframeP
,
subframeP
,
S_DL_NONE
);
S_DL_NONE
,
rnti
);
end_flag
[
CC_id
]
=
1
;
end_flag
[
CC_id
]
=
1
;
break
;
break
;
}
}
...
@@ -809,7 +812,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
...
@@ -809,7 +812,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
unsigned
char
ta_len
=
0
;
unsigned
char
ta_len
=
0
;
unsigned
char
sdu_lcids
[
NB_RB_MAX
],
lcid
,
offset
,
num_sdus
=
0
;
unsigned
char
sdu_lcids
[
NB_RB_MAX
],
lcid
,
offset
,
num_sdus
=
0
;
uint16_t
nb_rb
,
nb_rb_temp
,
nb_available_rb
;
uint16_t
nb_rb
,
nb_rb_temp
,
nb_available_rb
;
uint16_t
TBS
,
j
,
sdu_lengths
[
NB_RB_MAX
],
rnti
,
padding
=
0
,
post_padding
=
0
;
uint16_t
TBS
,
j
,
sdu_lengths
[
NB_RB_MAX
],
padding
=
0
,
post_padding
=
0
;
rnti_t
rnti
=
0
;
unsigned
char
dlsch_buffer
[
MAX_DLSCH_PAYLOAD_BYTES
];
unsigned
char
dlsch_buffer
[
MAX_DLSCH_PAYLOAD_BYTES
];
unsigned
char
round
=
0
;
unsigned
char
round
=
0
;
unsigned
char
harq_pid
=
0
;
unsigned
char
harq_pid
=
0
;
...
@@ -1214,8 +1218,11 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
...
@@ -1214,8 +1218,11 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
}
}
add_ue_dlsch_info
(
module_idP
,
add_ue_dlsch_info
(
module_idP
,
CC_id
,
UE_id
,
subframeP
,
CC_id
,
S_DL_SCHEDULED
);
UE_id
,
subframeP
,
S_DL_SCHEDULED
,
rnti
);
//eNB_UE_stats->dlsch_trials[round]++;
//eNB_UE_stats->dlsch_trials[round]++;
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
].
UE_list
->
eNB_UE_stats
[
CC_id
][
UE_id
].
num_retransmission
+=
1
;
num_retransmission
+=
1
;
...
@@ -1677,10 +1684,10 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
...
@@ -1677,10 +1684,10 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
if
(
opt_enabled
==
1
)
{
if
(
opt_enabled
==
1
)
{
trace_pdu
(
DIRECTION_DOWNLINK
,
(
uint8_t
*
)
UE_list
->
DLSCH_pdu
[
CC_id
][
0
][
UE_id
].
payload
[
0
],
trace_pdu
(
DIRECTION_DOWNLINK
,
(
uint8_t
*
)
UE_list
->
DLSCH_pdu
[
CC_id
][
0
][
UE_id
].
payload
[
0
],
TBS
,
module_idP
,
WS_RA_RNTI
,
UE_RNTI
(
module_idP
,
UE_id
),
TBS
,
module_idP
,
WS_RA_RNTI
,
UE_RNTI
(
module_idP
,
UE_id
),
eNB
->
frame
,
eNB
->
subframe
,
0
,
0
);
eNB
->
frame
,
eNB
->
subframe
,
0
,
0
);
LOG_D
(
OPT
,
"[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d
\n
"
,
LOG_D
(
OPT
,
"[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d
\n
"
,
module_idP
,
CC_id
,
frameP
,
UE_RNTI
(
module_idP
,
UE_id
),
TBS
);
module_idP
,
CC_id
,
frameP
,
UE_RNTI
(
module_idP
,
UE_id
),
TBS
);
}
}
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
(
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
),
...
@@ -1690,7 +1697,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
...
@@ -1690,7 +1697,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
CC_id
,
CC_id
,
UE_id
,
UE_id
,
subframeP
,
subframeP
,
S_DL_SCHEDULED
);
S_DL_SCHEDULED
,
rnti
);
// store stats
// store stats
eNB
->
eNB_stats
[
CC_id
].
dlsch_bytes_tx
+=
sdu_length_total
;
eNB
->
eNB_stats
[
CC_id
].
dlsch_bytes_tx
+=
sdu_length_total
;
eNB
->
eNB_stats
[
CC_id
].
dlsch_pdus_tx
+=
1
;
eNB
->
eNB_stats
[
CC_id
].
dlsch_pdus_tx
+=
1
;
...
...
openair2/LAYER2/MAC/eNB_scheduler_primitives.c
View file @
151873e9
This source diff could not be displayed because it is too large. You can
view the blob
instead.
openair2/LAYER2/MAC/mac_proto.h
View file @
151873e9
...
@@ -433,7 +433,7 @@ void init_ue_sched_info(void);
...
@@ -433,7 +433,7 @@ void init_ue_sched_info(void);
void
add_ue_ulsch_info
(
module_id_t
module_idP
,
int
CC_id
,
int
UE_id
,
void
add_ue_ulsch_info
(
module_id_t
module_idP
,
int
CC_id
,
int
UE_id
,
sub_frame_t
subframe
,
UE_ULSCH_STATUS
status
);
sub_frame_t
subframe
,
UE_ULSCH_STATUS
status
);
void
add_ue_dlsch_info
(
module_id_t
module_idP
,
int
CC_id
,
int
UE_id
,
void
add_ue_dlsch_info
(
module_id_t
module_idP
,
int
CC_id
,
int
UE_id
,
sub_frame_t
subframe
,
UE_DLSCH_STATUS
status
);
sub_frame_t
subframe
,
UE_DLSCH_STATUS
status
,
rnti_t
rnti
);
int
find_UE_id
(
module_id_t
module_idP
,
rnti_t
rnti
);
int
find_UE_id
(
module_id_t
module_idP
,
rnti_t
rnti
);
int
find_RA_id
(
module_id_t
mod_idP
,
int
CC_idP
,
rnti_t
rntiP
);
int
find_RA_id
(
module_id_t
mod_idP
,
int
CC_idP
,
rnti_t
rntiP
);
rnti_t
UE_RNTI
(
module_id_t
module_idP
,
int
UE_id
);
rnti_t
UE_RNTI
(
module_id_t
module_idP
,
int
UE_id
);
...
@@ -1201,7 +1201,6 @@ void fill_nfapi_dlsch_config(eNB_MAC_INST * eNB,
...
@@ -1201,7 +1201,6 @@ void fill_nfapi_dlsch_config(eNB_MAC_INST * eNB,
void
fill_nfapi_harq_information
(
module_id_t
module_idP
,
void
fill_nfapi_harq_information
(
module_id_t
module_idP
,
int
CC_idP
,
int
CC_idP
,
uint16_t
rntiP
,
uint16_t
rntiP
,
uint16_t
absSFP
,
nfapi_ul_config_harq_information
*
nfapi_ul_config_harq_information
*
harq_information
,
uint8_t
cce_idxP
);
harq_information
,
uint8_t
cce_idxP
);
...
@@ -1212,10 +1211,11 @@ void fill_nfapi_ulsch_harq_information(module_id_t module_idP,
...
@@ -1212,10 +1211,11 @@ void fill_nfapi_ulsch_harq_information(module_id_t module_idP,
*
harq_information
,
*
harq_information
,
sub_frame_t
subframeP
);
sub_frame_t
subframeP
);
uint16_t
fill_nfapi_uci_acknak
(
module_id_t
module_idP
,
void
fill_nfapi_uci_acknak
(
module_id_t
module_idP
,
int
CC_idP
,
int
CC_idP
,
uint16_t
rntiP
,
uint16_t
rntiP
,
uint16_t
absSFP
,
uint8_t
cce_idxP
);
uint16_t
absSFP
,
uint8_t
cce_idxP
);
void
fill_nfapi_dl_dci_1A
(
nfapi_dl_config_request_pdu_t
*
dl_config_pdu
,
void
fill_nfapi_dl_dci_1A
(
nfapi_dl_config_request_pdu_t
*
dl_config_pdu
,
uint8_t
aggregation_level
,
uint8_t
aggregation_level
,
...
...
openair2/LAYER2/MAC/pre_processor.c
View file @
151873e9
...
@@ -467,7 +467,11 @@ void decode_slice_positioning(module_id_t Mod_idP,
...
@@ -467,7 +467,11 @@ void decode_slice_positioning(module_id_t Mod_idP,
// This fuction sorts the UE in order their dlsch buffer and CQI
// This fuction sorts the UE in order their dlsch buffer and CQI
void
sort_UEs
(
module_id_t
Mod_idP
,
int
slice_idx
,
int
frameP
,
sub_frame_t
subframeP
)
void
sort_UEs
(
module_id_t
Mod_idP
,
int
slice_idx
,
int
frameP
,
sub_frame_t
subframeP
)
{
{
int
i
;
int
i
;
int
list
[
MAX_MOBILES_PER_ENB
];
int
list
[
MAX_MOBILES_PER_ENB
];
...
@@ -478,13 +482,12 @@ void sort_UEs(module_id_t Mod_idP, int slice_idx, int frameP, sub_frame_t subfra
...
@@ -478,13 +482,12 @@ void sort_UEs(module_id_t Mod_idP, int slice_idx, int frameP, sub_frame_t subfra
for
(
i
=
0
;
i
<
MAX_MOBILES_PER_ENB
;
i
++
)
{
for
(
i
=
0
;
i
<
MAX_MOBILES_PER_ENB
;
i
++
)
{
if
(
UE_list
->
active
[
i
]
==
FALSE
)
continue
;
if
(
UE_list
->
active
[
i
]
==
TRUE
&&
if
(
UE_RNTI
(
Mod_idP
,
i
)
==
NOT_A_RNTI
)
continue
;
UE_RNTI
(
Mod_idP
,
i
)
!=
NOT_A_RNTI
&&
if
(
UE_list
->
UE_sched_ctrl
[
i
].
ul_out_of_sync
==
1
)
continue
;
UE_list
->
UE_sched_ctrl
[
i
].
ul_out_of_sync
!=
1
&&
if
(
!
ue_dl_slice_membership
(
Mod_idP
,
i
,
slice_idx
))
continue
;
ue_dl_slice_membership
(
Mod_idP
,
i
,
slice_idx
))
{
list
[
list_size
++
]
=
i
;
list
[
list_size
]
=
i
;
}
list_size
++
;
}
}
decode_sorting_policy
(
Mod_idP
,
slice_idx
);
decode_sorting_policy
(
Mod_idP
,
slice_idx
);
...
@@ -1178,13 +1181,14 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
...
@@ -1178,13 +1181,14 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
int
min_rb_unit
[
NFAPI_CC_MAX
];
int
min_rb_unit
[
NFAPI_CC_MAX
];
slice_info_t
*
sli
=
&
RC
.
mac
[
Mod_id
]
->
slice_info
;
eNB_MAC_INST
*
eNB
=
RC
.
mac
[
Mod_id
];
slice_info_t
*
sli
=
&
eNB
->
slice_info
;
uint16_t
(
*
nb_rbs_required
)[
MAX_MOBILES_PER_ENB
]
=
sli
->
pre_processor_results
[
slice_idx
].
nb_rbs_required
;
uint16_t
(
*
nb_rbs_required
)[
MAX_MOBILES_PER_ENB
]
=
sli
->
pre_processor_results
[
slice_idx
].
nb_rbs_required
;
uint16_t
(
*
nb_rbs_accounted
)[
MAX_MOBILES_PER_ENB
]
=
sli
->
pre_processor_results
[
slice_idx
].
nb_rbs_accounted
;
uint16_t
(
*
nb_rbs_accounted
)[
MAX_MOBILES_PER_ENB
]
=
sli
->
pre_processor_results
[
slice_idx
].
nb_rbs_accounted
;
uint16_t
(
*
nb_rbs_remaining
)[
MAX_MOBILES_PER_ENB
]
=
sli
->
pre_processor_results
[
slice_idx
].
nb_rbs_remaining
;
uint16_t
(
*
nb_rbs_remaining
)[
MAX_MOBILES_PER_ENB
]
=
sli
->
pre_processor_results
[
slice_idx
].
nb_rbs_remaining
;
uint8_t
(
*
MIMO_mode_indicator
)[
N_RBG_MAX
]
=
sli
->
pre_processor_results
[
slice_idx
].
MIMO_mode_indicator
;
uint8_t
(
*
MIMO_mode_indicator
)[
N_RBG_MAX
]
=
sli
->
pre_processor_results
[
slice_idx
].
MIMO_mode_indicator
;
UE_list_t
*
UE_list
=
&
RC
.
mac
[
Mod_id
]
->
UE_list
;
UE_list_t
*
UE_list
=
&
eNB
->
UE_list
;
UE_sched_ctrl
*
ue_sched_ctl
;
UE_sched_ctrl
*
ue_sched_ctl
;
// int rrc_status = RRC_IDLE;
// int rrc_status = RRC_IDLE;
...
@@ -1202,7 +1206,10 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
...
@@ -1202,7 +1206,10 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
// Initialize scheduling information for all active UEs
// Initialize scheduling information for all active UEs
memset
(
&
sli
->
pre_processor_results
[
slice_idx
],
0
,
sizeof
(
sli
->
pre_processor_results
[
slice_idx
]));
memset
(
&
sli
->
pre_processor_results
[
slice_idx
],
0
,
sizeof
(
sli
->
pre_processor_results
[
slice_idx
]));
// FIXME: After the memset above, some of the resets in reset() are redundant
// FIXME: After the memset above, some of the resets in reset() are redundant
dlsch_scheduler_pre_processor_reset
(
Mod_id
,
slice_idx
,
frameP
,
subframeP
,
dlsch_scheduler_pre_processor_reset
(
Mod_id
,
slice_idx
,
frameP
,
subframeP
,
min_rb_unit
,
min_rb_unit
,
nb_rbs_required
,
nb_rbs_required
,
rballoc_sub
,
rballoc_sub
,
...
@@ -1211,23 +1218,38 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
...
@@ -1211,23 +1218,38 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
// STATUS
// STATUS
// Store the DLSCH buffer for each logical channel
// Store the DLSCH buffer for each logical channel
store_dlsch_buffer
(
Mod_id
,
slice_idx
,
frameP
,
subframeP
);
store_dlsch_buffer
(
Mod_id
,
slice_idx
,
frameP
,
subframeP
);
// Calculate the number of RBs required by each UE on the basis of logical channel's buffer
// Calculate the number of RBs required by each UE on the basis of logical channel's buffer
assign_rbs_required
(
Mod_id
,
slice_idx
,
frameP
,
subframeP
,
nb_rbs_required
,
min_rb_unit
);
assign_rbs_required
(
Mod_id
,
slice_idx
,
frameP
,
subframeP
,
nb_rbs_required
,
min_rb_unit
);
// Sorts the user on the basis of dlsch logical channel buffer and CQI
// Sorts the user on the basis of dlsch logical channel buffer and CQI
sort_UEs
(
Mod_id
,
slice_idx
,
frameP
,
subframeP
);
sort_UEs
(
Mod_id
,
slice_idx
,
frameP
,
subframeP
);
// ACCOUNTING
// ACCOUNTING
// This procedure decides the number of RBs to allocate
// This procedure decides the number of RBs to allocate
dlsch_scheduler_pre_processor_accounting
(
Mod_id
,
slice_idx
,
frameP
,
subframeP
,
dlsch_scheduler_pre_processor_accounting
(
Mod_id
,
slice_idx
,
frameP
,
subframeP
,
min_rb_unit
,
min_rb_unit
,
nb_rbs_required
,
nb_rbs_required
,
nb_rbs_accounted
);
nb_rbs_accounted
);
// POSITIONING
// POSITIONING
// This procedure does the main allocation of the RBs
// This procedure does the main allocation of the RBs
dlsch_scheduler_pre_processor_positioning
(
Mod_id
,
slice_idx
,
dlsch_scheduler_pre_processor_positioning
(
Mod_id
,
slice_idx
,
min_rb_unit
,
min_rb_unit
,
nb_rbs_required
,
nb_rbs_required
,
nb_rbs_accounted
,
nb_rbs_accounted
,
...
@@ -1237,8 +1259,9 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
...
@@ -1237,8 +1259,9 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
// SHARING
// SHARING
// If there are available RBs left in the slice, allocate them to the highest priority UEs
// If there are available RBs left in the slice, allocate them to the highest priority UEs
if
(
RC
.
mac
[
Mod_id
]
->
slice_info
.
intraslice_share_active
)
{
if
(
eNB
->
slice_info
.
intraslice_share_active
)
{
dlsch_scheduler_pre_processor_intraslice_sharing
(
Mod_id
,
slice_idx
,
dlsch_scheduler_pre_processor_intraslice_sharing
(
Mod_id
,
slice_idx
,
min_rb_unit
,
min_rb_unit
,
nb_rbs_required
,
nb_rbs_required
,
nb_rbs_accounted
,
nb_rbs_accounted
,
...
@@ -1250,7 +1273,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
...
@@ -1250,7 +1273,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
#ifdef TM5
#ifdef TM5
// This has to be revisited!!!!
// This has to be revisited!!!!
for
(
CC_id
=
0
;
CC_id
<
RC
.
nb_mac_CC
[
Mod_id
];
CC_id
++
)
{
for
(
CC_id
=
0
;
CC_id
<
RC
.
nb_mac_CC
[
Mod_id
];
CC_id
++
)
{
COMMON_channels_t
*
cc
=
&
RC
.
mac
[
Mod_id
]
->
common_channels
[
CC_id
];
COMMON_channels_t
*
cc
=
&
eNB
->
common_channels
[
CC_id
];
int
N_RBG
=
to_rbg
(
cc
->
mib
->
message
.
dl_Bandwidth
);
int
N_RBG
=
to_rbg
(
cc
->
mib
->
message
.
dl_Bandwidth
);
i1
=
0
;
i1
=
0
;
i2
=
0
;
i2
=
0
;
...
@@ -1258,35 +1281,24 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
...
@@ -1258,35 +1281,24 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
for
(
j
=
0
;
j
<
N_RBG
;
j
++
)
{
for
(
j
=
0
;
j
<
N_RBG
;
j
++
)
{
if
(
MIMO_mode_indicator
[
CC_id
][
j
]
==
2
)
{
if
(
MIMO_mode_indicator
[
CC_id
][
j
]
==
2
)
{
i1
=
i1
+
1
;
i1
++
;
}
else
if
(
MIMO_mode_indicator
[
CC_id
][
j
]
==
1
)
{
}
else
if
(
MIMO_mode_indicator
[
CC_id
][
j
]
==
1
)
{
i2
=
i2
+
1
;
i2
++
;
}
else
if
(
MIMO_mode_indicator
[
CC_id
][
j
]
==
0
)
{
}
else
if
(
MIMO_mode_indicator
[
CC_id
][
j
]
==
0
)
{
i3
=
i3
+
1
;
i3
++
;
}
}
}
}
if
((
i1
<
N_RBG
)
&&
(
i2
>
0
)
&&
(
i3
==
0
))
{
if
(
i1
<
N_RBG
)
{
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
check_for_SUMIMO_transmissions
=
if
(
i2
>
0
&&
i3
==
0
)
{
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
check_for_SUMIMO_transmissions
=
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
check_for_SUMIMO_transmissions
+
1
;
check_for_SUMIMO_transmissions
+
1
;
}
else
if
(
i3
>
0
)
{
}
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
check_for_MUMIMO_transmissions
=
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
check_for_MUMIMO_transmissions
+
1
;
}
if
(
i3
==
N_RBG
&&
i1
==
0
&&
i2
==
0
)
{
}
else
if
(
i3
==
N_RBG
&&
i1
==
0
&&
i2
==
0
)
{
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
FULL_MUMIMO_transmissions
=
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
FULL_MUMIMO_transmissions
=
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
FULL_MUMIMO_transmissions
+
1
;
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
FULL_MUMIMO_transmissions
+
1
;
}
if
((
i1
<
N_RBG
)
&&
(
i3
>
0
))
{
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
check_for_MUMIMO_transmissions
=
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
check_for_MUMIMO_transmissions
+
1
;
}
}
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
check_for_total_transmissions
=
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
check_for_total_transmissions
+
1
;
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
check_for_total_transmissions
=
PHY_vars_eNB_g
[
Mod_id
][
CC_id
]
->
check_for_total_transmissions
+
1
;
}
}
#endif
#endif
...
@@ -1297,22 +1309,30 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
...
@@ -1297,22 +1309,30 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
for
(
i
=
0
;
i
<
UE_num_active_CC
(
UE_list
,
UE_id
);
i
++
)
{
for
(
i
=
0
;
i
<
UE_num_active_CC
(
UE_list
,
UE_id
);
i
++
)
{
CC_id
=
UE_list
->
ordered_CCids
[
i
][
UE_id
];
CC_id
=
UE_list
->
ordered_CCids
[
i
][
UE_id
];
//PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id];
//PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id];
COMMON_channels_t
*
cc
=
&
RC
.
mac
[
Mod_id
]
->
common_channels
[
CC_id
];
COMMON_channels_t
*
cc
=
&
eNB
->
common_channels
[
CC_id
];
int
N_RBG
=
to_rbg
(
cc
->
mib
->
message
.
dl_Bandwidth
);
int
N_RBG
=
to_rbg
(
cc
->
mib
->
message
.
dl_Bandwidth
);
if
(
ue_sched_ctl
->
pre_nb_available_rbs
[
CC_id
]
>
0
)
{
if
(
ue_sched_ctl
->
pre_nb_available_rbs
[
CC_id
]
>
0
)
{
LOG_D
(
MAC
,
"******************DL Scheduling Information for UE%d ************************
\n
"
,
UE_id
);
LOG_D
(
MAC
,
"******************DL Scheduling Information for UE%d ************************
\n
"
,
LOG_D
(
MAC
,
"dl power offset UE%d = %d
\n
"
,
UE_id
,
ue_sched_ctl
->
dl_pow_off
[
CC_id
]);
UE_id
);
LOG_D
(
MAC
,
"***********RB Alloc for every subband for UE%d ***********
\n
"
,
UE_id
);
LOG_D
(
MAC
,
"dl power offset UE%d = %d
\n
"
,
UE_id
,
ue_sched_ctl
->
dl_pow_off
[
CC_id
]);
LOG_D
(
MAC
,
"***********RB Alloc for every subband for UE%d ***********
\n
"
,
UE_id
);
for
(
j
=
0
;
j
<
N_RBG
;
j
++
)
{
for
(
j
=
0
;
j
<
N_RBG
;
j
++
)
{
//PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[UE_id] = rballoc_sub_UE[CC_id][UE_id][UE_id];
//PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[UE_id] = rballoc_sub_UE[CC_id][UE_id][UE_id];
LOG_D
(
MAC
,
"RB Alloc for UE%d and Subband%d = %d
\n
"
,
UE_id
,
j
,
ue_sched_ctl
->
rballoc_sub_UE
[
CC_id
][
j
]);
LOG_D
(
MAC
,
"RB Alloc for UE%d and Subband%d = %d
\n
"
,
UE_id
,
j
,
ue_sched_ctl
->
rballoc_sub_UE
[
CC_id
][
j
]);
}
}
//PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id];
//PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id];
LOG_D
(
MAC
,
"[eNB %d][SLICE %d]Total RBs allocated for UE%d = %d
\n
"
,
LOG_D
(
MAC
,
"[eNB %d][SLICE %d]Total RBs allocated for UE%d = %d
\n
"
,
Mod_id
,
RC
.
mac
[
Mod_id
]
->
slice_info
.
dl
[
slice_idx
].
id
,
UE_id
,
Mod_id
,
eNB
->
slice_info
.
dl
[
slice_idx
].
id
,
UE_id
,
ue_sched_ctl
->
pre_nb_available_rbs
[
CC_id
]);
ue_sched_ctl
->
pre_nb_available_rbs
[
CC_id
]);
}
}
}
}
...
...
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